tech-note 3

[Design Doc] Transactional Outbox Pattern — Kafka 직접 발행의 한계와 설계 (7주차 · 6팀 · 조수현)

TL;DRKafka에 직접 발행하면 트랜잭션 커밋과 Kafka 발행 사이의 원자성을 보장할 수 없다. Outbox 테이블을 경유하는 방식으로 At Least Once 발행을 보장했고, partition-offset 기반 멱등성 키의 한계를 발견해 outboxId 기반으로 진화시켰다.Introduction & GoalsContext / Background좋아요, 조회, 주문 이벤트를 다른 시스템(commerce-streamer)으로 전파해야 했다. 처음엔 서비스 로직 안에서 직접 kafkaTemplate.send()를 호출하는 방식을 고려했는데, 트랜잭션 커밋 직후 Kafka 발행 직전에 애플리케이션이 죽으면 이벤트가 유실된다는 문제가 있었다.// 문제: 커밋 후 send 전에 죽으면 이벤트 유실@Tran..

카테고리 없음 2026.07.03

[Design Doc] PG 외부 연동 장애 대응 설계 (6주차 · 6팀 · 조수현)

TL;DRFeignClient로 PG를 호출하는 결제 시스템에서 Timeout + Retry + CircuitBreaker 조합을 적용해 PG 장애가 전체 서비스로 번지는 Cascading Failure를 차단했다. 타임아웃/CB Open 시 PENDING 유지 + 30초 배치 복구로 상태 정합성을 보장한다.Introduction & GoalsContext / Background결제 요청 시 우리 서버가 PG(Payment Gateway)를 FeignClient로 동기 호출한다. PG는 외부 시스템이므로 응답 지연이나 장애를 제어할 수 없다. Tomcat 스레드 풀(기본 200개)은 PG 응답을 기다리는 동안 블로킹 상태로 묶이며, 스레드가 고갈되면 결제와 무관한 상품 조회나 주문 생성까지 503을 반환..

카테고리 없음 2026.06.26

[Challenge Story] 주문·결제 동시성 제어 — 6개 문제를 연쇄 발견한 설계 여정 (2주차 · 6팀 · 조수현)

TL;DR주문/결제 시스템에서 동시성 문제를 하나씩 해결할 때마다 새로운 문제가 연쇄적으로 드러났다.SAGA 패턴 → 취소 시 Lost Update → 데드락 → 이중 취소까지 6개 문제를 차례로 발견하고,SELECT FOR UPDATE와 정렬 기반 락 획득 순서로 모두 해결했다.문제 1: 결제 실패 중 새 주문 → 트랜잭션 분리로 보상 범위 명확화 (보상 자동 실행은 미구현) ↓문제 2: 주문 취소 시 재고 Lost Update → 취소에도 SELECT FOR UPDATE 추가 ↓문제 3: 여러 상품 주문 시 데드락 → productId 오름차순 정렬로 해결 ↓문제 4: 이중 취소 요청 → Order에 SELECT FOR UPDATE 추가 ↓문제 5: PENDING 방치 → 배치 ..

카테고리 없음 2026.05.22