기존 상세 API의 과도한 DB I/O와 가격 캐싱 문제를 해결하기 위해 아키텍처 개선을 진행함
MongoDB 문서 구조 개편 및 가격 계산 모듈화를 통해 조회 성능과 데이터 정확성을 동시에 확보함
Claude Code skill과 쉐도잉 기반 동일성 검증으로 안전하고 효율적인 마이그레이션을 수행함
기존 V2 아키텍처는 상세 API 요청마다 MongoDB aggregation을 통해 여러 컬렉션에서 데이터를 조립했습니다. 특히 $lookup을 10회 이상 사용하여 실제로는 독립적인 쿼리 19개를 직렬 실행하는 구조였습니다.
병렬화 가능한 I/O의 직렬화: 각 $lookup은 순차적으로 실행되어 전체 응답 시간이 지연되고, 단일 쿼리 실패가 전체 장애로 이어질 위험이 있었습니다.
중복 I/O 및 거대 문서 생성: 쿠폰 조회처럼 조건만 다른 경우에도 여러 번 I/O가 발생했으며, 결과 데이터가 비대해져 BSON 문서 크기 제한(16MB)에 근접할 수 있었습니다.
캐싱 불가 및 Read Amplification: 변동 주기가 다른 데이터가 묶여 있어 전체 캐싱만 가능했고, 거의 변하지 않는 이미지 데이터까지 매번 재조회하는 읽기 증폭(Read Amplification)이 발생했습니다.
이러한 구조는 빠른 응답과 정확한 가격 제공 사이의 트레이드오프를 강요했습니다.
V3에서는 읽기 최적화된 문서 구조로 변경하고, 조회 로직을 숙소 메타 모듈과 가격 계산 모듈로 분리했습니다.
문서 구조 개편: 숙소 기본 정보, 객실/요금제, 상품 단위로 데이터를 미리 구성하여 ID 기반 단건/IN 조회로 단순화했습니다. $lookup이 하던 조립 작업은 적재(Write) 파이프라인이 담당합니다.
부분 캐싱 전략: 숙소 메타 모듈은 변동 주기에 맞춰 Cache-Aside 또는 Cache-First 전략을 적용하고, 가격은 실시간 계산으로 정확성을 확보했습니다.
병렬 데이터 조회: 여러 컬렉션 조회가 필요한 경우, 애플리케이션 레벨에서 배치(Batch) 처리하여 병렬로 데이터를 가져옵니다.
이를 통해 V2에서 불가피했던 빠른 응답과 정확한 가격 사이의 트레이드오프를 해결했습니다.
기존에 화면 API마다 흩어져 있던 가격 계산 로직을 goodsprice라는 단일 모듈로 통합했습니다.
중앙 집중식 로직 관리: 전체 기간 합산 할인 정책 등 복잡한 계산 규칙이 단일 모듈 내에서 한 번만 정의되어, 화면 간 가격 불일치 문제를 구조적으로 해결했습니다.
단위 테스트 가능성: JSON 문자열로 관리되던 규칙들이 자바 코드(Java Code)로 전환되면서 단위 테스트 작성이 가능해졌습니다.
향후 확장성: 실시간 가격 API 연동 시, 외부 소스 변경이 goodsprice 모듈에만 집중되어 유지보수성과 확장성이 크게 향상될 것으로 기대됩니다.
이는 모듈화가 가져온 가장 실용적인 자산입니다.
네 개의 화면 API 마이그레이션 반복 작업을 Claude Code skill로 정의하여 표준화했습니다.
명시적 스펙 정의: V2 로직 분석 단계에서 암묵적 규칙을 명시적인 스펙 문서로 정리했습니다.
안전망 구축: 쉐도잉(Shadowing)으로 운영 트래픽을 복제하고, 동일성 검증(Equivalence Verification)을 통해 V2와 V3 응답의 일치 여부를 전수 조사했습니다.
AI 활용의 전제: AI가 코드를 잘 작성해서가 아니라, 검증 가능한 구조와 안전망이 선행되었기에 안전하게 마이그레이션을 진행할 수 있었습니다.
결과적으로 AI를 도구로 활용하여 마이그레이션 생산성을 높였습니다.
V3 아키텍처는 복잡도를 사라지게 한 것이 아니라 다른 곳으로 옮겼습니다.
쓰기/동기화 복잡도 증가: 읽기 최적화 문서를 최신 상태로 유지하기 위한 이벤트 기반 컨슈머 파이프라인이 추가되었고, 데이터 유실 및 순서 문제 복구 방안을 고려해야 합니다.
구조 복잡도 및 운영 포인트 증가: 계층이 늘어나면서 Dispatcher → Composer → 메타 모듈 → 캐시 → 문서로 이어지는 추적 경로가 복잡해졌고, 각 계층별 설정 및 모니터링 포인트가 늘어났습니다.
인지 비용(Cognitive Cost) 증가: 팀원들이 새로운 구조에 익숙해지기까지 온보딩 비용이 발생하며, 마이그레이션 기간 동안 V2와 V3를 모두 이해해야 했습니다.
이러한 비용은 읽기 작업이 압도적으로 많은 서비스 특성상 얻는 이득이 더 크다고 판단하여 감수했습니다.