Skip to main content
@transactional 데코레이터는 메서드를 자동으로 트랜잭션으로 감싸주어 보일러플레이트 코드를 줄여줍니다.

데코레이터 개요

자동 트랜잭션

메서드 실행을 자동으로 트랜잭션으로 감쌈 성공 시 커밋, 실패 시 롤백

코드 간결화

transaction() 호출 불필요 가독성 향상

Isolation Level

트랜잭션 격리 수준 설정 동시성 제어

중첩 트랜잭션

같은 preset의 DB 트랜잭션 Savepoint 자동 생성 안 함

기본 사용법

Before: 수동 트랜잭션

After: @transactional 데코레이터

@transactional() 데코레이터가 적용된 메서드는 자동으로 트랜잭션 내에서 실행됩니다.

작동 원리

데코레이터 옵션

dbPreset 설정

Isolation Level 설정

Isolation Level 주의사항: - 높은 격리 수준은 동시성 감소 - SERIALIZABLE은 성능 영향 큼 - 대부분의 경우 REPEATABLE READ가 적절

실전 예제

예제 1: 단순 트랜잭션

예제 2: 자동 롤백

예제 3: 복잡한 트랜잭션 (Company → Dept → Employee)

예제 4: 동시성 제어

중첩 트랜잭션

자동 트랜잭션 재사용

같은 preset의 중첩 @transactional 호출은 하나의 DB 트랜잭션에 참여합니다. 같은 preset의 가장 바깥 호출이 커밋과 롤백을 담당합니다.
중첩 트랜잭션의 이점: - 코드 재사용성 향상 - 메서드 조합 자유로움 - 트랜잭션 경계 자동 관리

에러와 Savepoint 의미

같은 preset의 중첩 @transactional 호출은 바깥 DB 트랜잭션에 참여합니다. 새 트랜잭션이나 Savepoint를 만들지 않으며, 같은 preset의 가장 바깥 호출이 커밋과 롤백을 담당합니다.
이 예시는 DB 문장이 성공한 뒤 발생한 애플리케이션 에러를 잡습니다. 바깥 트랜잭션은 계속되어 앞선 작업을 커밋할 수 있습니다. 반면 제약조건이나 SQL 실패 같은 PostgreSQL 문장 오류는 현재 트랜잭션을 중단하므로 catch만으로 다시 사용할 수 없습니다.
실패 후에도 바깥 트랜잭션을 계속해야 하는 직접 DB 쿼리는 중첩 getPuri("w").transaction(...) Savepoint 안에서 실행하세요. 전체 작업을 원자적으로 처리해야 한다면 애플리케이션 에러를 같은 preset의 가장 바깥 @transactional 호출까지 전파해 모두 롤백하세요.

@api와 함께 사용

데코레이터 조합

장단점

장점

코드 간결화

transaction() 호출 불필요 보일러플레이트 제거

가독성

트랜잭션 경계 명확 비즈니스 로직에 집중

자동 관리

커밋/롤백 자동 처리 실수 방지

재사용성

메서드 조합 용이 중첩 트랜잭션 지원

단점

제약사항

메서드 레벨에서만 사용 부분 트랜잭션 불가

디버깅

트랜잭션 경계가 숨겨짐 문제 추적 어려울 수 있음

사용 가이드

언제 사용하나?

✅ 사용 권장:
  • 메서드 전체가 하나의 트랜잭션
  • 여러 DB 작업이 원자성 필요
  • 코드 재사용이 중요한 경우
  • API 핸들러 메서드
❌ 사용 비권장:
  • 메서드 내 부분적 트랜잭션
  • 복잡한 트랜잭션 제어 필요
  • 트랜잭션 경계가 명확해야 하는 경우

패턴 비교

주의사항

반드시 지켜야 할 사항: 1. 메서드는 async 함수여야 함 2. this.getPuri("r"/"w")로 DB 접근 3. 애플리케이션 에러는 throw로 전파 (자동 롤백) 4. 같은 preset의 중첩 호출은 같은 DB 트랜잭션에 참여하며 가장 바깥 호출이 커밋/롤백

흔한 실수

다음 단계

수동 트랜잭션

transaction() 직접 사용하기

모범 사례

트랜잭션 사용 가이드

UpsertBuilder

트랜잭션 내 데이터 저장

데코레이터

Sonamu 데코레이터 이해하기