Transaction은 여러 DB 작업을 하나의 성공 또는 실패 단위로 묶어 데이터 정합성을 지키는 경계다.
백엔드에서는 트랜잭션 경계가 API 경계, 서비스 메서드, 외부 API 호출, 메시지 발행, 락 보유 시간과 직접 연결된다.
좋은 트랜잭션 설계는 짧고 명확하며, 실패 시 재시도와 보상, 멱등성, 롤백 기준을 설명할 수 있어야 한다.
핵심 정리
ACID는 원자성, 일관성, 격리성, 지속성을 뜻하지만 실제 보장 수준은 DB 엔진, 격리 수준, 쿼리 방식, 애플리케이션 경계에 따라 달라진다.
트랜잭션은 DB 커넥션에 묶인다. Spring에서 @Transactional은 같은 스레드의 트랜잭션 동기화와 커넥션 사용 흐름을 관리한다.
트랜잭션이 길어지면 락 보유 시간이 늘고, 커넥션을 오래 점유하며, MVCC 기반 DB에서는 오래된 row version 정리를 방해할 수 있다.
외부 API 호출을 트랜잭션 안에 넣으면 DB 락과 커넥션이 외부 시스템 응답 시간에 묶인다. 결제, 알림, 파일 업로드는 경계 설계가 특히 중요하다.
롤백은 만능이 아니다. DB 안의 변경은 되돌릴 수 있어도 외부 시스템 호출, 메시지 발행, 이메일 전송은 별도 보상이나 outbox 패턴이 필요할 수 있다.
재시도는 멱등성과 함께 설계해야 한다. 데드락, 일시적 네트워크 오류, serialization failure는 재시도 후보지만, 중복 주문이나 중복 포인트 적립을 막는 키가 필요하다.
Spring의 기본 롤백 규칙, proxy 적용 범위, self-invocation, propagation은 실제 커밋/롤백 결과를 바꾼다. @Transactional을 붙였다는 사실보다 실제 proxy를 통과하는 호출인지, 어떤 예외가 밖으로 전파되는지 확인해야 한다.
읽기 트랜잭션도 운영 자원이다. readOnly=true는 의도와 일부 최적화 힌트가 될 수 있지만, 긴 streaming 조회나 느린 select는 여전히 커넥션과 snapshot을 오래 붙잡는다.
헷갈리는 지점
@Transactional을 붙이면 모든 정합성 문제가 해결된다고 생각하기 쉽다. 선언 하나로 롤백이 되는 모습이 강력해 보이기 때문이다.
핵심은 트랜잭션이 DB 경계 안의 작업을 묶을 뿐 외부 부작용까지 자동으로 되돌리지 않는다는 점이다.
격리 수준, 락, 재시도, 멱등성은 별도로 설계해야 한다.
트랜잭션은 길수록 안전하다고 오해하기 쉽다. 많은 작업을 한 번에 묶으면 일관성이 좋아 보이기 때문이다.
핵심은 긴 트랜잭션이 락과 커넥션을 오래 잡아 장애를 키운다는 점이다.
일관성 단위를 정확히 잡고 외부 I/O는 분리하는 편이 좋다.
읽기 전용 API에는 트랜잭션이 필요 없다고 생각하기 쉽다. 데이터를 변경하지 않기 때문이다.
핵심은 일관된 읽기, Lazy Loading, 커넥션 관리, Hibernate flush mode와 관련이 있다는 점이다.
읽기 전용 트랜잭션은 의도 표시와 최적화 힌트로도 의미가 있다.
Spring에서 예외가 나면 항상 롤백된다고 생각하기 쉽다. 대부분의 예제는 RuntimeException만 보여주기 때문이다.
핵심은 기본적으로 unchecked exception 중심으로 롤백되며, checked exception, 예외 삼키기, 내부 호출, noRollbackFor 설정에 따라 결과가 달라질 수 있다는 점이다.
중요한 변경 작업은 통합 테스트에서 실제 commit/rollback 결과를 확인해야 한다.
확인 질문
트랜잭션 경계를 설계할 때 가장 먼저 정해야 하는 것은 무엇인가?
어떤 데이터 변경들이 하나의 비즈니스 성공 또는 실패 단위인지 정해야 한다.
외부 API 호출을 트랜잭션 안에 넣는 것이 위험한 이유는 무엇인가?
외부 응답 지연 동안 DB 커넥션과 락을 오래 잡아 전체 서비스 지연과 락 경합을 키울 수 있기 때문이다.
재시도를 안전하게 만들기 위해 필요한 것은 무엇인가?
멱등 키, Unique 제약, 상태 전이 규칙, 중복 처리 정책, 재시도 가능한 오류와 불가능한 오류의 구분이다.
트랜잭션이 길어졌는지 운영에서 의심할 수 있는 신호는 무엇인가?
pool pending 증가, connection acquire time 증가, lock wait, long transaction, idle in transaction, vacuum 지연, replica lag, p99 지연 증가다.