반응형

Java 125

[Spring 공식 문서 기반] Transaction 7. NESTED는 왜 거의 쓰이지 않을까

6편에서는 REQUIRES_NEW가“기존 트랜잭션의 운명에서 의도적으로 분리되는 선택”이라는 점과, 그만큼 강력하지만 위험한 옵션임을 실무 사례로 살펴봤습니다.그렇다면 전파 옵션 목록에 항상 함께 등장하지만실제 코드에서는 거의 보이지 않는이 옵션은 무엇일까요?NESTED이번 글에서는 NESTED가 무엇을 해결하려 했고, 왜 결과적으로 잘 쓰이지 않게 되었는지를 공식 문서 기준으로 정리해보겠습니다.1. NESTED의 기본 개념NESTED는 REQUIRED와 REQUIRES_NEW의 중간에 위치한 옵션처럼 보입니다.공식 문서에서 정의하는 NESTED의 의미는 다음과 같습니다.기존 트랜잭션이 있으면 그 안에 Savepoint를 만들고, 그 지점으로 롤백할 수 있게 한다즉,새 트랜잭션을 만들지 않고같은 트랜잭션..

[Spring 공식 문서 기반] Transaction 6. REQUIRES_NEW는 언제 진짜 필요할까

5편에서는 트랜잭션 전파 옵션 중왜 REQUIRED가 기본값이 될 수밖에 없는지를 살펴봤습니다.REQUIRED는“같은 유스케이스라면 하나의 트랜잭션으로 묶어야 한다”는 Spring의 기본 철학을 가장 잘 표현하는 옵션이었습니다.그렇다면 다음 질문이 자연스럽게 따라옵니다.그럼 REQUIRES_NEW는 언제 써야 할까?그리고 왜 ‘기본값’이 아니었을까?1. REQUIRES_NEW의 정확한 의미REQUIRES_NEW는 아주 강한 선언입니다.기존 트랜잭션이 있든 없든,무조건 새로운 트랜잭션을 시작한다즉,기존 트랜잭션은 일시 중단(suspend)새 트랜잭션을 별도로 생성해당 메서드 종료 시 즉시 커밋/롤백이라는 동작을 합니다.이 선택은“이 작업은 바깥 흐름과 운명을 같이하지 않는다”는 명확한 의사 표현입니다.2...

[Spring 공식 문서 기반] Transaction 5. REQUIRED는 왜 기본값일까

4편에서는 트랜잭션이“프록시 구현의 결과가 아니라, 비즈니스 유스케이스를 표현하기 위한 메서드 경계”로 설계되었다는 점을 살펴봤습니다.이제 자연스럽게 다음 질문으로 이어집니다.트랜잭션 전파(Propagation)는 왜 이렇게 많은 옵션을 가질까?그리고 그중 왜 REQUIRED가 기본값일까?이 질문에 답하지 못하면,REQUIRES_NEW를 남용하거나의도치 않은 커밋/롤백을 만들고트랜잭션 구조를 복잡하게 만듭니다1. 전파(Propagation)는 무엇을 결정하는 옵션일까Propagation은“이미 트랜잭션이 존재할 때, 이 메서드는 어떻게 행동할 것인가”를 결정하는 옵션입니다.즉,트랜잭션이 없을 때?트랜잭션이 이미 있을 때?이 두 상황에 대한“정책 선언”입니다.2. REQUIRED의 정확한 의미REQUIRE..

[Spring 공식 문서 기반] Transaction 4. 트랜잭션은 왜 메서드 경계에 묶일까

3편에서는 @Transactional이“메서드 실행 전후를 감싸는 프록시 기반 AOP”로 동작한다는 사실을 살펴봤습니다.이제 한 단계 더 깊은 질문으로 들어가야 합니다.왜 하필 ‘메서드’일까?트랜잭션은 클래스나 블록 단위로 관리하면 안 됐을까?이 질문에 답하면,왜 트랜잭션이 서비스 계층에 있어야 하는지왜 유스케이스 단위 설계가 중요한지왜 트랜잭션이 커지면 위험해지는지가 한 번에 연결됩니다.1. 트랜잭션 경계는 ‘시작과 끝’이 명확해야 한다트랜잭션의 본질은 아주 단순합니다.“어디서 시작해서, 어디서 끝나는가”이 경계가 명확하지 않으면,어디까지 롤백해야 하는지어떤 리소스를 묶고 있는지를 결정할 수 없습니다.Spring 공식 문서는 이 경계를“메서드 호출”로 정의합니다.왜냐하면 메서드는:명확한 진입 지점이 있..

[Spring 공식 문서 기반] Transaction 3. @Transactional은 언제 시작되고 언제 끝날까

2편에서는 Spring Transaction의 핵심 추상화인PlatformTransactionManager가 왜 인터페이스로 설계되었는지를 살펴봤습니다.이제 다음 질문으로 자연스럽게 이어집니다.그럼 @Transactional은 정확히 언제 트랜잭션을 시작하고, 언제 끝낼까?이 질문에 답하지 못하면,왜 어떤 메서드는 트랜잭션이 안 걸리는지왜 내부 호출에서는 동작하지 않는지왜 예상과 다른 시점에 커밋되는지를 끝까지 설명할 수 없습니다.1. @Transactional은 메서드가 아니다많은 개발자가 @Transactionl을“메서드 위에 붙이는 어노테이션”으로만 이해합니다.하지만 Spring 공식 문서에서 @Transactionl은AOP 설정 정보입니다.즉,어노테이션 자체가 트랜잭션을 시작하지 않고Spring이..

[Spring 공식 문서 기반] Transaction 2. PlatformTransactionManager는 왜 인터페이스일까

1편에서는 Spring Transaction이“왜 ThreadLocal로 관리될 수밖에 없었는가”를 웹 요청 모델과 실행 흐름 관점에서 살펴봤습니다.이제 다음 질문으로 자연스럽게 이어집니다.트랜잭션을 실제로 시작하고, 커밋하고, 롤백하는 주체는 도대체 누구일까?이 질문의 중심에 있는 것이 바로PlatformTransactionManager입니다.1. 많은 개발자가 잘 보지 않는 인터페이스Spring에서 트랜잭션을 사용할 때 우리는 보통@Transactionalpublic void service() { // business logic}만 작성합니다.그 아래에서 어떤 클래스가트랜잭션을 시작하고리소스를 묶고커밋/롤백을 수행하는지는 거의 의식하지 않습니다.하지만 Spring 공식 문서에서는 트랜잭션의 핵심..

[Spring 공식 문서 기반] Transaction 1. 트랜잭션은 왜 ThreadLocal로 관리될까

Spring에서 트랜잭션을 처음 접하면 대부분 이렇게 사용합니다.@Transactionalpublic void service() { // 비즈니스 로직}하지만 시간이 지나면 자연스럽게 이런 질문이 생깁니다.트랜잭션은 대체 어디에 저장돼 있을까?그리고 왜 비동기에서는 전파되지 않을까?이 질문의 핵심에는ThreadLocal이라는 선택이 있습니다.이번 글에서는 Spring Transaction 공식 문서를 기준으로,“왜 트랜잭션은 ThreadLocal로 관리될 수밖에 없었는가”를 설계 관점에서 풀어보겠습니다.1. 트랜잭션은 ‘기능’이 아니라 ‘상태’다많은 개발자가 트랜잭션을“commit / rollback을 해주는 기능”으로 인식합니다.하지만 Spring 공식 문서에서 트랜잭션은“현재 실행 흐름에 묶인 ..

[Spring JPA 공식 문서 기반] 28. Spring JPA 설계 원칙 총정리

1편부터 27편까지, 이 시리즈에서는 Spring JPA 공식 문서를 기준으로왜 이런 개념이 존재하는지왜 이런 제약이 생겼는지왜 실무에서 문제가 되는지를 하나의 흐름으로 정리해 왔습니다.이 마지막 편에서는 개별 기능 설명이 아니라,Spring JPA를 어떻게 바라보고, 어떤 원칙으로 써야 하는지를 정리하며 시리즈를 마무리하겠습니다.원칙 1. JPA는 “쓰기 모델”에 최적화된 기술이다JPA의 핵심은상태를 가진 엔티티변경 감지(Dirty Checking)트랜잭션 단위의 일관성입니다.즉,JPA는 “상태 변경을 안전하게 관리하는 기술”이지,“모든 조회를 해결하는 ORM”이 아닙니다.그래서 JPA는 쓰기 모델(Command)의 중심에 둘 때 가장 강력합니다.원칙 2. 조회는 엔티티가 아니라 “전략”이다실무에서 가..

[Spring JPA 공식 문서 기반] 27. JPA는 어디까지 책임져야 할까

26편에서는 CQRS 관점에서“읽기 모델과 쓰기 모델을 분리해야 하는 이유”를 살펴봤습니다.이제 자연스럽게 마지막 질문에 도달합니다.“그럼 JPA는 도대체 어디까지 책임져야 할까?”이 질문에 답하지 못하면,JPA로 모든 걸 하려다 망하거나반대로 JPA를 너무 일찍 버리게 됩니다1. JPA의 출발점부터 다시 보자JPA는“객체 모델과 관계형 모델을 조율하기 위한 표준”로 출발했습니다.즉,SQL을 없애기 위한 기술 ❌DB를 추상화하기 위한 기술 ❌이 아닙니다.JPA의 역할은 명확합니다.객체 상태를 DB 변경으로 변환트랜잭션 단위의 일관성 유지반복적인 매핑 코드 제거2. JPA에 기대하면 안 되는 것들실무에서 JPA가 문제가 되는 순간은 대부분“책임을 넘어선 기대”때문입니다.다음 영역은 JPA의 책임이 아닙니다..

[Spring JPA 공식 문서 기반] 26. 읽기 모델과 쓰기 모델은 왜 분리해야 할까

25편에서는 EntityGraph가“엔티티를 반환해야 할 때, Fetch 전략을 국소적으로 제어하는 도구”라는 점과 그 유효 범위를 살펴봤습니다.이제 한 단계 위에서 지금까지의 조회 전략을 정리할 필요가 있습니다.“왜 조회는 점점 복잡해지고, 엔티티는 점점 위험해질까?”이 질문의 답이 바로읽기 모델과 쓰기 모델의 분리즉, CQRS(Command Query Responsibility Segregation) 관점입니다.1. 하나의 엔티티에 모든 책임을 맡기면 생기는 문제전통적인 JPA 사용 방식에서는엔티티가 곧 도메인 모델이고엔티티가 곧 조회 모델이며엔티티가 곧 응답 모델이 되는 경우가 많습니다.하지만 실무가 복잡해질수록 이 구조는 다음 문제를 낳습니다.조회 요구사항이 엔티티를 오염시키고연관관계가 과도하게 ..

반응형