트랜잭션이 이미 진행중인데, 여기에 추가로 트랜잭션을 수행하면 어떻게 될까?
기존 트랜잭션과 별도의 트랜잭션을 진행해야 할까? 아니면 기존 트랜잭션을 그대로 이어 받아서 트랜잭션을 수행해야 할까?
이런 경우 어떻게 동작할지 결정하는 것을 트랜잭션 전파(propagation)라 한다.
스프링은 다양한 트랜잭션 전파 옵션을 제공한다.

스프링은 논리 트랜잭션과 물리 트랜잭션이라는 개념을 나눈다.
논리 트랜잭션들은 하나의 물리 트랜잭션으로 묶인다.
물리 트랜잭션 - 우리가 이해하는 실제 데이터베이스에 적용되는 트랜잭션을 뜻한다. 실제 커넥션을 통해서 트랜잭션을 시작( setAutoCommit(false)) 하고, 실제 커넥션을 통해서 커밋, 롤백하는 단위이다.
논리 트랜잭션 - 트랜잭션 매니저를 통해 트랜잭션을 사용하는 단위이다.
가장 많이 사용되는 전파 옵션이다.
내부 트랜잭션이 기존 트랜잭션에 참여하며 하나의 트랜잭션으로 묶인다. 따라서 내부 트랜잭션 코드는 사실상 트랜잭션 관련해서 참여만 할 뿐 아무것도 하지 않는다.
내부트랜잭션에서 에러가 발생하면 외부 트랜잭션도 롤백이 된다.
참고로 내부트랜잭션 로직을 try catch 문으로 처리 해도 rollback-only를 체크하므로 외부 트랜잭션도 롤백이 된다.
그리고 트랜잭션의 커밋, 롤백은 외부트랜잭션(처음 시작하는 트랜잭션)이 담당한다.


REQUIRED는 기존에 참여했다면 REQUIRES_NEW는 무조건 새로운 트랜잭션을 만들어 실행한다.
따라서 커넥션을 두개 사용하며 내부 트랜잭션 코드가 에러가나서 롤백이 났다고 해도 외부 트랜잭션 코드는 그에 상관없이 로직이 실행되고 커밋 또는 롤백이 된다.


그 외에도 다양한 전파 옵션이 있지만 사실상 REQUIRED 또는 REQUIRES_NEW를 대부분 사용하기 때문에 따로 정리하지는 않았다.
isolation, timeout, readOnly 는 트랜잭션이 처음 시작될 때만 적용된다. 트랜잭션에 참여하는 경우에는 적용되지 않는다.
예를 들어서 REQUIRED 를 통한 트랜잭션 시작, REQUIRES_NEW 를 통한 트랜잭션 시작 시점에만 적용된다.
트랜잭션 전파... 공부해도 어렵고 헷갈리지만 더 열심히 해서 마스터 해야겠다!
그래도 어느정도 트랜잭션 흐름을 생각하며 코드를 짤 수 있게 된 것 같다!