주문 서비스 핵심 로직 설계 및 트래픽 대응 구조 - Genie-Uss/genieus GitHub Wiki
🧩 문제 상황 (Problem)
이커머스 도메인에서 주문 생성 흐름은 다음과 같은 복합적인 트랜잭션 처리 및 연동 문제에 직면했습니다:
- 재고, 쿠폰, 결제 등 여러 서비스와의 연동이 필요하지만, 모두 동기 처리할 경우 시스템 병목 위험
- 재고/쿠폰 연동 실패 시, 일괄 롤백이 필요한데, Kafka 기반 비동기 구조에서는 예외 전파가 어렵고 상태 복구가 복잡
- 고트래픽 상황에서는 주문 요청이 몰려들어 DB 커넥션/락/서버 리소스 소모가 급증함
- 주문 만료 처리도 실시간으로 처리하면 리소스 낭비가 심하고, 일관성 유지가 어려움
🎯 선택한 해결 방안 (Decision)
동기/비동기 흐름을 명확히 분리하고, 트래픽 분산과 장애 복구에 강한 구조를 적용했습니다:
- ✅ 즉시 확인이 필요한 흐름은 동기 처리: 주문 생성 시 최저가 검증, 재고 예약
FeignClient
기반 동기 호출 - ✅ 후속 처리가 필요한 흐름은 비동기 처리: 주문 취소 시 재고 복구는 Kafka 이벤트 발행으로 지연 처리
- ✅ 장애 복원력 확보를 위해 Resilience4j 적용: 서킷브레이커 + 재시도 설정을 통해 연동 서비스 장애 시 빠른 격리 가능
- ✅ 주문 만료는 Redis 기반 Delay Queue 사용: ZSet + TTL 방식으로 주문 유효기간 관리 → 스케줄러가 일괄 만료 처리
🧩 주문 생성 흐름 시퀀스 다이어그램 (Mermaid)
sequenceDiagram
participant Client
participant OrderService
participant PromotionService
participant ProductService
participant Redis
participant Kafka
Client->>OrderService: 주문 생성 요청
OrderService->>PromotionService: 최저가 검증 (동기)
PromotionService-->>OrderService: 검증 성공/실패
OrderService->>ProductService: 재고 예약 (동기)
ProductService-->>OrderService: 예약 성공/실패
alt 성공 시
OrderService->>OrderService: 주문 저장
OrderService->>Redis: 만료 시각 등록 (ZSet)
OrderService->>Kafka: 주문 생성 이벤트 발행
else 실패 시
OrderService-->>Client: 실패 응답
OrderService->>Kafka: 주문 생성 실패 이벤트 발행
end
OrderService-->>Client: 주문 생성 결과 반환
✅ 적용 효과 (Outcome)
- 동기/비동기 흐름의 분리로 핵심 로직의 트랜잭션 안정성 확보
- Redis 기반 만료 구조 덕분에 성능 저하 없이 대량 주문 처리 가능
- Resilience4j 도입을 통해 외부 장애에 대한 방어선 확보
- Kafka 기반 이벤트 발행으로 쿠폰/재고 복구 흐름이 느슨하게 결합되어 확장성 강화
- 전체 주문 요청 성공률 및 평균 응답시간이 트래픽 피크 시에도 안정적으로 유지됨
🔭 향후 개선 방향 (Next Steps)
- 🔄 만료 처리 Poller 구조 개선: @Scheduled 기반에서 Kafka Delay Topic 구조로 전환 가능성 검토
- ☁️ 트랜잭션 아웃박스 패턴 도입 검토: 주문 저장과 이벤트 발행을 완전한 원자성으로 처리
- 🔎 관측성 향상: 주문 흐름에 대한 로그/메트릭 강화, k6 + Prometheus 기반 SLA 측정 체계 구축
💬 요약
“프로모션/상품 연동은 동기 호출로 즉시 보장하고, 복구·만료는 Kafka 이벤트와 Redis Delay Queue 기반으로 비동기 처리함으로써, 트래픽 상황에서도 안정적이고 유연한 주문 처리를 가능하게 했습니다.”