KSCOLD LogoKSCOLD
Blog
Feed
Product
Admin Night
Vault
Guestbook
Info

Vault 목록

@Transactional

연결된 노트와 함께 읽기

@Transactional

2026년 5월 17일
  • @Transactional은 Spring에서 메서드 또는 클래스에 트랜잭션 경계를 선언하는 어노테이션이다.
  • 적용된 메서드가 정상 종료되면 COMMIT, 예외가 발생하면 ROLLBACK이 자동으로 처리된다.
  • 내부적으로 AOP 프록시를 사용해 동작하므로, 같은 클래스 내부 호출에는 적용되지 않는다.

기본 사용

Java

주요 속성

속성기본값설명
readOnlyfalsetrue이면 flush 생략, 성능 최적화
propagationREQUIRED트랜잭션 전파 방식
isolationDEFAULT격리 수준 (DB 기본값 사용)
rollbackForRuntimeException롤백할 예외 타입 지정
noRollbackFor-롤백하지 않을 예외 타입
timeout-1 (무제한)트랜잭션 제한 시간 (초)

전파 방식 (Propagation)

Mermaid스크롤로 확대 · 드래그로 이동
전파 방식설명주 사용
REQUIRED (기본)기존 트랜잭션 참여, 없으면 새로 시작대부분 서비스 메서드
REQUIRES_NEW항상 새 트랜잭션 시작, 기존 일시 중단이벤트 리스너 DB 작업
SUPPORTS트랜잭션 있으면 참여, 없어도 실행읽기 전용
NOT_SUPPORTED트랜잭션 없이 실행배치, 비트랜잭션 로직
MANDATORY트랜잭션 없으면 예외반드시 트랜잭션 내에서만 실행
NEVER트랜잭션 있으면 예외
NESTED중첩 트랜잭션 (Savepoint)부분 롤백 필요 시

rollbackFor

  • @Transactional은 기본적으로 RuntimeException (unchecked) 에서만 롤백한다.
  • Checked Exception은 기본 롤백 대상이 아니므로 명시가 필요하다.
Java

주의사항

같은 클래스 내부 호출 — 트랜잭션 미적용

Java
  • Spring의 @Transactional은 AOP 프록시를 통해 동작하므로 this.inner()는 프록시를 거치지 않는다.
  • 해결: inner()를 별도 서비스 클래스로 분리하거나, ApplicationContext를 통해 프록시를 직접 가져온다.

readOnly = true 효과

  • JPA 영속성 컨텍스트의 Dirty Checking(변경 감지)을 비활성화 → flush 생략.
  • DB 드라이버 레벨에서 읽기 전용 최적화.
  • @Transactional(readOnly = true)는 클래스 레벨에 두고, 쓰기 메서드에만 @Transactional을 덮어쓰는 패턴이 권장된다.

@TransactionalEventListener와 연동

  • @TransactionalEventListener(phase = AFTER_COMMIT) 핸들러에서 DB 작업이 필요하면 REQUIRES_NEW와 함께 사용한다.
  • 자세한 내용: @TransactionalEventListener

관련

  • 트랜젝션(transaction)
  • 트랜잭션(Transaction)
  • @TransactionalEventListener
  • JPA(Java Persistence API)
  • 서비스(Service)

Synapse Map Insight

@Service @Transactional(readOnly = true) // 클래스 전체 기본값: 읽기 전용 public class PostService { // 읽기 전용 (SELECT 최적화) public Post findById(String id) { return postRepository.findById(id).orElseThrow(); } @Transactional // 쓰기 작업은 별도 선언 (readOnly = false 기본값) public Post create(CreatePostCommand command) { return postRepository.save(Post.of(command)); } }
@Transactional(rollbackFor = Exception.class) // 모든 예외에 롤백 public void process() throws IOException { ... }
@Service public class PostService { public void outer() { inner(); // 같은 클래스 내부 호출 → @Transactional 무시됨 } @Transactional public void inner() { ... } }