오늘은 @transactional 애너테이션에 대해서 알아보려고 합니다.
이 애너테이션을 알아보기 전에 일단 영속성 컨텍스트의 내부 구조 및 동작 흐름에 대해서 알아봅시다.
4, 5번이 이 애너테이션을 사용하는 이유입니다.
- persist(엔티티) 를 실행하면 해당 엔티티 객체가 영속성 컨텍스트에서 관리되기 시작
- 1차 캐시라는 곳에 key 는 @ID 의 값, value는 해당 객체
- 바로 쿼리가 db 로 날아가는 것이 아니라, 해당 db 쿼리가 자동으로 만들어져서 쓰기 지연 저장소에 저장
- 트랜잭션 커밋이 실행되면 flush 라는 것이 실행되는데 이것은 쓰기 지연 저장소에 있는 쿼리를 DB 로 날려 변경 내용을 데이터베이스에 동기화하는 것
- 그리고 데이터베이스 커밋을 수행
- 4, 5 는 @Transactionl 이 붙은 메서드에서 자동으로 실행!
@Transactional이 실행되는 흐름
위의 createPost() 메서드가 실행될 때, 내부적으로 스프링 트랜잭션 관리자가 다음과 같은 작업을 수행합니다.
🔥 @Transactional이 적용된 메서드 실행 흐름
1. 메서드 실행 (트랜잭션 시작) - begin transaction;
2. 엔티티 저장 (`postRepository.save(post)`) - INSERT SQL 실행되지 않고 **쓰기 지연 저장소**에 저장됨
3. 메서드 정상 종료 (commit 수행) - `flush()` 실행 (쓰기 지연 저장소에 있던 SQL을 DB로 전송)
- `commit()` 실행 (트랜잭션 완료, 변경 사항 확정)
[예외 발생 시] - rollback 수행 (트랜잭션 롤백)
조금 더 구체적으로 이 애너테이션을 사용하면 어떤일이 일어나는지 적용된 기술과 함께 동작 흐름을 살펴보겠습니다.
게시글을 저장한다고 한다면 아래와 같은 코드를 작성할 수 있습니다.
@Service
public class PostService {
@Autowired
private PostRepository postRepository;
@Transactional
public void createPost() {
Post post = new Post();
post.setTitle("New Post");
postRepository.save(post); // 아직 DB에 SQL 실행되지 않음 (쓰기 지연 저장소에 있음)
// 메서드 내부에서는 flush()와 commit()이 호출되지 않음!
}
}
내부적으로 실행되는 과정
1. 클라이언트가 `createPost()` 호출
- 실제 `PostService`가 아닌 프록시 객체(Proxy)를 호출
- 프록시가 트랜잭션을 시작 (`begin transaction`)
2. 프록시가 `createPost()`를 실행
- 엔티티를 저장 (`postRepository.save(post)`)
- 쓰기 지연 저장소(hibernate ActionQueue)에 SQL이 모아짐
- 아직 DB에 쿼리가 실행되지 않음
3. `createPost()` 메서드 실행 완료 후, 프록시가 `flush()` 실행
- 쓰기 지연 저장소의 SQL을 DB로 전송 (INSERT 실행)
4. 프록시가 `commit()` 실행
- DB 변경 사항 확정
5. 예외 발생 시 `rollback()` 실행
@Transactionl 은 AOP 와 프록시 패턴을 사용하여 트랙잭션을 관리하는 기술입니다!
'Server > Spring' 카테고리의 다른 글
[Spring Cloud] (0) | 2025.03.04 |
---|---|
[JPA] 영속성 컨텍스트 (0) | 2025.02.24 |
HttpMessageConversionException 발생 원인과 해결책 알아보기 (0) | 2023.08.12 |