--- title: "Implementing a Custom Spring Transaction Interceptor — CatnipCoder" source_type: company-tech-blog url: https://www.catnipcoder.com/custom-spring-transaction-interceptor archive_url: status: raw confidence: medium tags: [ca-transaction-boundary, custom-aop, transaction-interceptor, spring, try-monad] related_projects: [ca-skeleton-operational-contract] related_branches: [feature-application-port-usecase-contract, feature-transaction-concurrency-contract] created: 2026-05-22 last_reviewed: 2026-05-27 --- # Implementing a Custom Spring Transaction Interceptor > Layer: `raw/company-tech-blogs/` — 개인 기술 블로그 (engineering-blog 등급). Spring 공식 문서 아님 — 공식 best practice 단정 금지. > 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성. ## Parent / 활용 branch (필수) | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-application-port-usecase-contract]] | TransactionPort 결정 시 대안 4 (Custom AOP / TransactionInterceptor 확장) 의 reference. application layer 가 Spring AOP 를 깊이 끌어안는 방향의 사례 | | [[raw/branch-notes/feature-transaction-concurrency-contract]] | rollback rule 을 함수형 에러 타입 (Try/Either) 기반으로 재정의하는 패턴의 근거 | | [[raw/project-notes/ca-skeleton-operational-contract]] | §14. Transaction / Concurrency Contract + §5. Exception Ownership Contract 의 대안 비교 base | ## 컨텍스트 ca-tmpl 의 TransactionPort 결정에 대한 대안 5: **Spring `TransactionInterceptor` 확장 / custom TransactionAdvisor**. `@Transactional` 의 default behavior 를 우회하면서도 Spring AOP 인프라를 재사용하는 패턴. 함수형 에러 타입(Try/Either) 에 트랜잭션을 묶고 싶을 때 등장. ## 출처 / Source - 원본 URL: https://www.catnipcoder.com/custom-spring-transaction-interceptor - 참고 구현: https://github.com/VassilisSoum/spring-custom-transaction-interceptor - 아카이브 URL: (미수집) - 저자 / 조직: Vassilis Soum / CatnipCoder (개인 기술 블로그) - 발행일: 2024 - 마지막 확인일: 2026-05-27 ## 핵심 인용 / Key quotes (verbatim) > [§Extending TransactionInterceptor] "To implement a custom Spring Transaction Interceptor, we need to create a class that extends the `TransactionInterceptor` class provided by Spring." > [§Override method] "Our custom interceptor will extend the TransactionInterceptor class and override the `invokeWithinTransaction` method." > [§MethodInterceptor] "CustomTransactionInterceptor is a Spring AOP MethodInterceptor for managing transactions in methods that return Try monad types. It extends TransactionInterceptor to utilize its transaction management functionalities." > [§Motivation — Try monad] "This approach involves using the `Try` monad to handle exceptions in a more functional way while retaining the transactional behavior of the @Transactional annotation." > [§Challenge] "The challenge is to combine the transactional behavior of the @Transactional annotation with the functional error handling provided by the Try monad." > [§Rollback rule code] "if (txAttr.rollbackOn(ex)) { status.setRollbackOnly(); }" ## Claims Extracted / 추출된 주장 | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | CATNIP-TXINT-C1 | Spring TransactionInterceptor 를 확장하고 `invokeWithinTransaction` 을 override 하여 custom 트랜잭션 동작을 구현할 수 있다 | [§Extending TransactionInterceptor] "we need to create a class that extends the `TransactionInterceptor` class" + [§Override method] "override the `invokeWithinTransaction` method" | `engineering-blog` | Spring AOP 기반 transaction 관리 환경 | 이 패턴이 Spring 공식 권장이라는 뜻은 아님 — 개인 블로그 사례 | | CATNIP-TXINT-C2 | `TransactionInterceptor` 는 Spring AOP `MethodInterceptor` 구현체로, 메서드 호출 전후에 custom 로직을 실행할 수 있다 | [§MethodInterceptor] "CustomTransactionInterceptor is a Spring AOP MethodInterceptor for managing transactions in methods that return Try monad types. It extends TransactionInterceptor to utilize its transaction management functionalities." | `engineering-blog` | Spring AOP 인프라 위에서 동작하는 application | TransactionInterceptor 의 모든 internal API 가 stable 하다는 보증은 없음 (Spring 내부 구현) | | CATNIP-TXINT-C3 | 동기는 `Try` monad 가 예외를 던지지 않는 functional style 을 유지하면서도 `@Transactional` 의 트랜잭션 동작과 결합하는 것 | [§Motivation — Try monad] "This approach involves using the `Try` monad to handle exceptions in a more functional way while retaining the transactional behavior of the @Transactional annotation." + [§Challenge] "The challenge is to combine the transactional behavior of the @Transactional annotation with the functional error handling provided by the Try monad." | `engineering-blog` | functional style + Spring 혼합 코드베이스 | 모든 functional 에러 타입 (Either, Result, IO 등) 에 본 패턴이 그대로 적용된다는 뜻은 아님 | | CATNIP-TXINT-C4 | rollback 결정은 `TransactionAttribute.rollbackOn(ex)` 에 위임하여 `status.setRollbackOnly()` 호출로 트리거 | [§Rollback rule code] "if (txAttr.rollbackOn(ex)) { status.setRollbackOnly(); }" | `engineering-blog` | rollback policy 를 코드로 직접 제어할 때 | `@Transactional(noRollbackFor=)` 와 정확히 동등하게 동작한다는 검증은 본 글에 없음 (블로그 댓글로 추정) | ## Usage Boundaries / 적용 경계 - **이 자료가 직접 증명하는 것**: - `CATNIP-TXINT-C1`: TransactionInterceptor 확장 + invokeWithinTransaction override 패턴의 존재 - `CATNIP-TXINT-C2`: TransactionInterceptor 의 MethodInterceptor 기반 메커니즘 - `CATNIP-TXINT-C3`: Try monad 와 @Transactional 결합 동기 - `CATNIP-TXINT-C4`: rollback 결정의 코드 레벨 위임 방식 - **이 자료가 증명하지 않는 것**: - 본 패턴이 Spring 공식 권장 best practice (개인 블로그) - `spring.main.allow-bean-definition-overriding=true` 의 필요 여부 (본 글에 명시 없음 — 추론) - 본 패턴이 clean architecture 의 dependency rule 을 위반/준수하는지의 결론 - production 환경에서의 안정성 (개인 블로그, 사례 검증 없음) - **내 프로젝트에 적용하려면 추가 확인이 필요한 것**: - ca-tmpl 의 application layer 가 Spring AOP 의존성을 가져도 되는가의 architectural 결정 - Try monad 외 ca-tmpl 의 functional error 타입 (Either 등) 에 동일 패턴 적용 가능성 - Spring Boot 3.x / Spring 6.x 의 internal API 변경 risk ## 메모 / Notes > 검증되지 않은 내 해석은 여기에 두지 말 것 — wiki source-summary 단계에서. - 참고 구현: GitHub https://github.com/VassilisSoum/spring-custom-transaction-interceptor - 적용 시나리오: - functional error type(`Try`, `Either`) 메서드 시그니처를 유지하면서도 Spring `@Transactional` 인프라 재사용. - `@Transactional` 의 rollback 정책을 메서드 반환값 기반으로 재정의해야 할 때. - 장점 (추론, 미검증): - 기존 `@Transactional` 코드 자산과 호환. PlatformTransactionManager, propagation 그대로 사용. - rollback rule 을 "예외 던지기" 외 패턴(`Either.Left`) 으로 확장. - 단점 (추론, 미검증): - **여전히 Spring AOP / `TransactionInterceptor` 직접 import → clean architecture dependency rule 관점에선 `@Transactional` 직접 부착과 다를 바 없음.** (단지 옵션 추가일 뿐.) - `spring.main.allow-bean-definition-overriding=true` 같은 위험 플래그를 켜야 할 수 있음 (블로그에 명시 없음, 일반적 패턴 기반 추론). - 디버깅 어려움. 신규 합류자에게 "왜 표준이 아닌가" 설명 필요. - ca-tmpl(TransactionPort) 와의 차이: ca-tmpl 은 application layer 에서 Spring 자체를 보이지 않게 함. 본 패턴은 application 이 Spring AOP 를 더 깊이 끌어안는 방향. **정반대 트레이드오프.** - testability 영향: 낮음 — Spring context 없으면 검증 불가. - code 복잡도 영향: 높음 — AOP 내부 이해 필요. 학습/유지보수 비용 큼. ## Related / 관련 - 같은 주제 다른 raw: (TransactionPort / @Transactional / TransactionTemplate 관련 자료는 별도) - 인용하는 branch: - [[raw/branch-notes/feature-application-port-usecase-contract]] - [[raw/branch-notes/feature-transaction-concurrency-contract]] - 인용하는 project: - [[raw/project-notes/ca-skeleton-operational-contract]] (§14, §5) - 인용한 wiki 요약: (미작성)