작성
·
432
2
안녕하세요.
영한님의 여러 강의들과 이번 강의들을 보면서 궁금한 점이 생겨 질문드립니다.
물론, 상황과 조직에 따라 구현하는 방법은 여러 가지 있겠지만 실무에서는 어떻게 쓰시는지 궁금합니다.
질문은.
강의에서 말씀하신 방법과는 반대로, 비즈니스로직을 Runtime 예외로 두고, @Transactional 옵션의 noRollbackFor을 사용하여 롤백되지 않도록 하는 방법"을 사용하는 것은 어떤가요?
그 이유는, OrderService의 메소드 시그니쳐에 throws 구문을 강제하고 싶지 않습니다.
첫 번째, OrderController가 OrderService 인터페이스에만 의존하고 있다고 가정하고, OrderService의 구현체들마다 예외를 throw할 수도 안할수도 있다고 가정한다면 비즈니스로직을 Exception 타입으로 정의하여 메소드 시그니쳐에 throws 구문을 강제하는 방법이 문제가 될 수 있습니다. (인터페이스 메소드 시그니쳐에도 throws가 추가되어야 하기 때문에)
=> 추가) 여기에 대한 저 스스로에 대한 답은, 실제로 운영을 하며 서비스 계층의 구현체를 변경할 일도 많지 않고 이에 따라 컨트롤러가 인터페이스가 아닌 구현체에 의존해도 큰 상관은 없을 것 같다. 입니다.
두 번째, 제가 이해하는 개념으로는 예외를 throw 한다는 것은, 자신을 호출한 상위 메소드에서 해당 예외를 적절히 처리하게끔 책임을 위임하는 것이라고 생각합니다. 즉, Controller 계층에서 NotEnoughMoneyException를 처리하도록 하는 것입니다. 물론, Controller 계층에서 해당 예외를 catch하여 "잔고가 부족합니다"와 같이 정상적인 흐름과 다른 응답을 클라이언트에게 응답으로 돌려준다면 적절한 상황(?) 이겠지만 @ExceptionHandler를 이용해서 NotEnoughMoneyException을 핸들링하고 있는 상황에서도 OrderController의 메소드에 throws을 명시하여야 합니다.
그래서, 비즈니스로직을 RuntimException 타입으로 지정하고 무의미할 수도있는 메소드 시그니쳐에 throws는 생략한체로noRollbackFor 옵션을 사용하는 것이 코드를 더 깔끔하게 작성할 수 있지 않을까 생각했습니다.
물론, 스프링이 예외를 바라보는 시선(런타임은 시스템 에러, checked는 비즈니스 에러)과는 반대로 코드를 작성한다는 부담(?)이 있긴 합니다...
답변 1
2
안녕하세요. 이화평님
네 생각하신 부분도 괜찮습니다.
롤백하면 안되는 비즈니스 예외의 상위 클래스를 런타임 예외로 만들고 그것을 상속 받는 식으로 구현하면 더 편리하겠죠?
감사합니다.