
안정적인 예약 시스템과 유연한 확장을 동시에 잡기 위한 고민과 결과물을 정리했습니다. 현재의 안정성을 유지하면서 미래의 트래픽 급증에 대비하는 무중단 확장 전략을 상세히 공유합니다.
IdolGlow는 복잡한 비즈니스 로직이 외부 기술 DB, API에 오염되지 않도록 패키지 계층을 명확히 분리했습니다.
도메인과 애플리케이션 계층은 구체적인 구현체가 아닌 인터페이스에만 의존합니다.
행사 정보 조회 예시:
1. Domain Port: FestivalEventExternalQueryPort 인터페이스 정의
2. Application Service: 포트 인터페이스를 호출하여 비즈니스 로직 수행
3. Infrastructure Adapter: TourFestivalApiClient가 포트를 상속받아 실제 외부 API 호출 구현
설계의 실전 이점:
6e0bcf9 커밋에서 외부 API 응답 형식이 바뀌었을 때, 서비스 로직 수정 없이 어댑터만 수정하여 대응할 수 있었습니다.예약은 PREBOOK → PENDING → BOOKED → CANCELED 순으로 흐릅니다.
도메인 엔티티 내에서 허용되지 않는 전이 예: 취소된 건을 바로 확정 를 원천 차단합니다.
ReservationSlot 엔티티는 "누가, 언제까지 선점했는가"를 스스로 관리합니다. validateAvailability 메서드를 통해 만료된 선점은 자동으로 해제하고, 중복 선점 시도를 방지합니다.
결제 완료 API 안에서 만료된 예약들까지 한꺼번에 스캔하여 처리하면 응답 시간이 느려지고 시스템 부하가 커집니다.
현재 IdolGlow는 데이터베이스 수준의 행 잠금(SELECT ... FOR UPDATE)을 사용해 동시성을 제어합니다.
또한 벤드사 연동 시 Idempotency-Key를 사용하여 중복 결제를 원천 차단합니다.
인스턴스가 늘어나는 멀티 인스턴스 환경을 위해 DistributedLockProvider 인터페이스를 설계해 두었습니다.
현재는 로컬 JVM 메모리를 쓰지만, 설정값 한 줄만 바꾸면 Redis 기반 분산 락으로 즉시 전환 가능한 구조입니다.
6e0bcf9 커밋의 실전 가치:
외부 API의 응답이 불안정하거나 빈 값(items: "")을 줄 때, 어댑터 계층의 역직렬화 로직에서 이를 감지하고 빈 리스트로 변환합니다.
덕분에 코어 서비스와 도메인 모델은 어떤 상황에서도 안정적인 데이터를 보장받게 되었습니다.
IdolGlow의 현재 상태는 도메인이 명확하고 아키텍처가 확장을 고려해 설계되어 있습니다.
이번 작업을 통해 아키텍처는 단순히 폴더 구조를 나누는 것이 아니라, 변경과 장애의 영향을 어디까지 막을 수 있는지 결정하는 설계라는 점을 느꼈습니다.
IdolGlow에서는 외부 API 호출, 예약 상태 전이, 결제 처리, 배치 만료 처리 등을 각 계층의 책임에 맞게 분리했습니다. 덕분에 외부 API 응답 형식이 바뀌어도 어댑터 계층만 수정하면 되었고, 핵심 유스케이스와 도메인 규칙은 흔들리지 않았습니다.
또한 예약 시스템에서는 DB 락, 상태 전이, 멱등성, 배치 처리가 따로 노는 기술이 아니라 하나의 흐름으로 연결되어야 안정성이 생긴다는 점을 배웠습니다. 특히 온라인 요청에서는 빠르게 응답하고, 만료 처리 같은 작업은 배치로 분리하는 방식이 서비스 안정성에 더 현실적이었습니다.
이번 경험을 통해 좋은 설계란 처음부터 Redis, Kafka를 모두 붙이는 것이 아니라, 현재는 단순하게 운영하되 필요할 때 무중단으로 확장할 수 있는 구조를 만드는 것이라고 느꼈습니다.