Tag: Backend
이 태그가 달린 글들 "Backend"
-
JPA 낙관락 + retry stampede 의 함정 — @Version 만으론 부족한 6 시나리오
100 worker 가 같은 룰의 priority 를 +1 합니다. @Version 없으면 priority < 100 (Lost Update). @Version 적용하면 OptimisticLockException 만 던지고 처리는 호출자 책임 — 일부만 성공. @Retryable(3) 백오프 0 으로 retry 면 **동시에 retry 가 몰려서** 다시 충돌 (retry stampede). exponential + full jitter 가 retry 를 분산시켜 priority=100 도달. 그리고 측정 도중 만난 자기 Lost Update — 같은 트랜잭션 안에서 SELECT 두 번이 다른 객체 (JDBC) vs 같은 인스턴스 (JPA 1차 캐시 ==). 분산 환경 Lost Update 와는 완전히 별개의 함정. @Transactional + @Retryable AOP 순서, exponential backoff + jitter 의 이론적 근거 (AWS Architecture Blog) 까지 풀었습니다.
-
[JPA + Spring Mastery 01] 1차 캐시 · flush · 트랜잭션 라이프사이클 — readOnly 가 줄이는 set_option, dirty checking 의 진짜 비용
PersistenceContext 가 Identity Map 패턴 (Fowler PoEAA) 위에 어떻게 작동하는지, ActionQueue 4종이 SQL 발행 순서를 어떻게 결정하는지, AutoFlush 가 query 직전에 무엇을 보고 flush 하는지, dirty checking 이 reflection 과 bytecode enhancement 두 방식에서 얼마나 비용이 다른지 — Hibernate 6 의 DefaultFlushEventListener 부터 카카오페이의 readOnly + set_option QPS 58% 감소 회고까지, 1차 캐시와 트랜잭션 라이프사이클을 line 단위로 분해한 기록입니다. JPA 5 ways 측정 (raw JDBC 0.74 / JPA 0.99~1.95 ms) 의 +0.4ms baseline 비용이 어디서 오는지, 그리고 그 비용을 줄이기 위한 readOnly 의 *3단 효과* (Hibernate flush mode + Spring tx 마커 + MySQL Com_set_option 감소) 를 라인 단위로 풀어봅니다.
-
[JPA + Spring Mastery 08] 트랜잭션 분리 패턴 — Saga / Outbox / REQUIRES_NEW, 학술 기원부터 EXP-09b 9 시나리오 실측까지
트랜잭션 안에서 외부 API 호출하지 마라 - 격언은 들어봤지만 어떻게 풀어야 하는지는 잘 다뤄지지 않습니다. 본 글은 PROPAGATION 7종의 정확한 의미부터 2PC (XA) 의 한계, Garcia-Molina 의 1987년 Sagas 논문, Pat Helland 의 CIDR 2005 Data on the Outside, Vogels 의 ACM Queue 2008 Eventually Consistent 까지 학술 기원을 짚고, 토스 SLASH24 SAGA, 29CM/리디 Outbox 한국 운영 사례를 거쳐, EXP-09b 9 시나리오 실측 매트릭스 - 패턴 A/B/C × OFF/DB_FAIL/EXT_FAIL - 로 검증한 기록입니다. 결제 도메인은 Saga, 알림은 Outbox, 캐시류만 단순 분리 - 이 매핑의 학술 + 운영 + 실측 3박자.
-
[JPA + Spring Mastery 07] Spring AOP self-invocation — @Transactional 이 작동하지 않는 진짜 이유, TransactionInterceptor.invoke 6단계까지 분해
낙관락 측정에서 successes=100인데 잔액이 그대로 100. 코드 logic 은 멀쩡한데 잔액이 안 줄어들었습니다. 원인은 같은 클래스 내부 호출이 Spring AOP 프록시를 우회한 것 — @Transactional 이 발동하지 않아 flush 가 일어나지 않았습니다. 이 글은 TransactionInterceptor.invoke 의 6단계 / AOP Alliance MethodInvocation.proceed() 가 raw target 을 호출하는 위치 / 같은 함정에 걸리는 6 어노테이션 (@Async / @Cacheable / @Validated / @Retryable / @PreAuthorize) / 4 가지 워크어라운드 (분리 빈 / getBean(self) / AopContext.currentProxy / AspectJ weaving) 를 Spring 6 / Hibernate 6 소스 라인 단위로 분해한 기록.