ADR-002 계약 검증 = MockWebServer 녹화 fixture(CI) + live 태그 실 API 스모크(opt-in)

  • 상태: 채택
  • 날짜: 2026-07-03
  • 근거: PRD FR-2·NFR / TDD “Possible Solutions 방안 B”

맥락

실 API 응답이 mock 스키마(Gateway DTO)와 일치하는지 “검증”이 이 과제의 핵심 코드 산출물이다. 그러나 실 API를 CI에서 상시 호출하면 quota 소모·키 노출·정부/벤더 API 장애로 인한 플레이키가 발생한다(PRD NFR: 저빈도 호출, 키 평문 노출 0). 현재 gateway HTTP 경로 통합 테스트 자체가 없고 MockWebServer/WireMock 의존성도 없다.

결정

2단 검증을 채택한다.

  1. CI 상시 — MockWebServer 녹화 fixture 계약 테스트: 실 API(또는 스키마 동일 mock) 응답 JSON을 test/resources/fixtures/external/**에 1회 캡처해 고정. MockWebServer에 enqueue 후 GatewayImpl을 domain interface로 호출해 역직렬화·매핑·HTTP 경로가 기대 도메인 객체를 내는지 검증(키 불요, 네트워크 불요). 스키마 회귀를 락.
  2. opt-in — live 태그 실 API 스모크: 실 키가 env에 있을 때만 도는 live 태그 스펙. 기본 test에서 제외하고 ./gradlew verifyExternalLive로만 실행. 실 응답이 동일 DTO로 무손실 역직렬화되는지 1회성 확인.

도구: okhttp mockwebserver(테스트 의존성). RestClient 테스트에 경량이며 WireMock보다 의존성이 작다.

근거

  • contract-by-example(Pact 벤치마크): concrete 응답 예시로 계약을 고정 → 스키마 변경을 테스트가 조기 감지.
  • CI에 키 없음 → NFR(키 노출 0·저빈도) 충족. quota 소모 없음.
  • live 스모크는 태그로 분리 → 키 부재 시 스킵, CI를 붉게 만들지 않음.

대안 (미채택)

  • Pact broker + provider verification: 정부/벤더 API에 provider CI를 붙일 수 없다. 브로커 인프라 과함.
  • Spring Cloud Contract stub-runner: stub 저장소·플러그인 체계가 무겁다. MockWebServer 직접 사용이 단순.
  • 실 API CI 상시 호출: quota·키 노출·플레이키. NFR 위반.
  • WireMock record proxy 상시: fixture seed에는 유용하나 상시 proxy 운영은 불필요한 복잡도.

영향

  • build.gradle.kts에 mockwebserver 테스트 의존성 + verifyExternalLive task 추가(BE-01).
  • 3개 GatewayImpl(공공체육시설·기상청·카카오)에 계약 테스트 신설(BE-02/03/04).
  • fixture는 실 응답 1회 캡처로 seed 권장. 키 발급 전에는 mock 응답으로 seed 후 첫 live 실행에서 승격(TDD Open Q).