@Transactional 을 @RestController에 달아 놓았는데 코드 리뷰를 받으면서
해당 경우에는 제대로 @Transactional 자체가 적용되지 않는다는 피드백을 받았습니다.
(글을 읽다보면 정리되겠지만, 결론적으로 적용 자체가 안되는 것은 아닙니다)
이번 포스팅에서는 다음 내용을 정리해보겠습니다.
먼저 스프링에서는 @Transactional 을 활용한 선언적 트랜잭션 관리와,
직접 트랜잭션 매니저를 이용해 트랜잭션 코드를 작성하는 프로그래밍 방식 트랜잭션 관리가 있는 사실을 알고 시작합시다.
실제로는 두 가지 방법 중 대부분 @Transactional 을 활용한 선언적 트랜잭션 관리를 사용합니다.
프로그래밍 방식의 트랜잭션 관리의 단점을 생각해봅시다.
트랜잭션은 일반적으로 다음과 같은 순서로 진행됩니다.
수동 커밋 모드 on (= 트랜잭션의 시작) -> 비즈니스 로직 -> 커밋 혹은 롤백
크게 2가지 문제점이 있습니다.
@Transactional은 앞서 제시된 2가지 문제점을 Proxy 객체를 활용해 해결합니다.
다음 그림을 봅시다.

트랜잭션을 시작하고, 종료하는 부분은 모두 프록시에서 실행되기 때문에,
서비스 계층은 순수한 비즈니스 로직 코드만을 유지할 수 있습니다.
비즈니스 로직 코드의 실행은 프록시가 실제 대상 객체를 가지고 있기 때문에 호출되는 형태로 동작합니다.
스프링 MVC 패턴에서 사용되는 @Repository, @Controller에 @Transactional을 달면 안되는 걸까요?
먼저 스프링 부트는 @Transactinoal에 대해 CGLIB 동적 프록시 방식을 사용함을 언급하겠습니다.
(참고로 CGLIB 동적 프록시, JDK 동적 프록시에 대해서 잘 모르신다면 이 글을 참고해주세요.)
@Repository에는 @Transactional 을 달아도 상관 없습니다.
하지만 우리가 트랜잭션을 사용하는 이유를 생각해봅시다.
트랜잭션을 커밋 or 롤백하는 단위는 단순히 데이터베이스의 접근이 아니라 비즈니스 로직입니다.
그런 비즈니스 로직을 관리하는 곳이 주로 @Service인데 @Repository에 있다면 이런 비즈니스 로직은
트랜잭션으로 관리되지 못할 것이라, 역시 권장되지 않는 방법입니다.
역시 @Transactional 을 달아도 상관 없습니다.
하지만 @Repository와 비슷한 이유로 사용이 권장되지 않습니다.
@Controller의 고유 역할인 고객의 요청을 받고, 적절한 Service 계층의 로직을 위임하는 것만
담당하게 코드를 분리하는 것이 좋습니다.
좋은 글이네요