web의 API 호출은 orval 생성물만 쓴다
- 상태: 채택됨
- 작성일: 2026-07-23
- 관련 문서: APP-66, APP-110, APP-147, APP-204, APP-244
맥락
서버 구현이 끝나기 전에 화면을 만들어야 했다. 손으로 타입을 쓰면 계약이 바뀔 때마다 갈라진다. 목을 손으로 쓰면 계약에 없는 응답을 그리게 된다. 갈라진 것을 알려 주는 장치도 없어서 조용히 어긋난다.
결정
openapi3.yml(서버openapi3산출물의 미러,/internal/**제거본)을 입력으로pnpm orval이 TanStack Query 훅과 MSW 핸들러를 생성한다.- 제품 컴포넌트가 API 경로를 직접
fetch()하면 위반이다. 예외는 생성 훅이 원리적으로 닿지 못하는 세 자리뿐이다: transport 자신(lib/api/, SSE는text/event-stream을 못 읽는다), 토큰 갱신과 순환하는 인증 경로(lib/auth/,proxy.ts), 목 전용 표면(components/mocks/). openapi3.yml과lib/api/generated/**는 손으로 고치지 않는다(hook이 막는다).- MSW 응답은 명시적 override로 준다. orval 기본 목 응답을 그대로 쓰면 무작위
success: false가 나와 인증이 깨진다. 시드를 고정한 faker는 정당하다.
대안
대안 1 — 화면부터 만들고 나중에 계약 맞추기. 서버를 기다리지 않아도 되고 화면이 먼저 나온다. 기각한 이유: 계약 우선 결정(APP-66)과 정면으로 충돌한다.
대안 2 — 손으로 쓴 타입·목. 생성 파이프라인 없이 바로 시작할 수 있다. 기각한 이유: 갱신 누락이 조용히 남는다. 계약과 코드가 갈라지는 것은 파이프라인이 막아야 했다. 사람 눈에 맡길 일이 아니었다.
결과
- 계약이 바뀌면 타입과 목이 함께 따라온다. 어긋나면 생성 단계에서 드러난다.
- 생성물 지도(
docs/generated-api-map.md) 한 곳에서 훅 이름·import 경로·MSW 핸들러를 확인한다. 그 관례가 자리 잡았다. - 생성 훅이 못 닿는 세 자리는 손으로 유지해야 한다. 그만큼 파이프라인 밖 코드가 남는다.
- orval 기본 목 응답을 그대로 못 쓰고 MSW 응답을 명시적 override로 일일이 줘야 한다.
- 계약이 바뀌면 orval → 핸들러 → 화면 순으로 재생성·반영하는 절차 비용이 매번 붙는다. web은 서버 산출물의 미러를 따라갈 수밖에 없다.
- 생성물이 계약의 표현력에 갇힌다. MSW가 nullable 계약의 한쪽 값만 주던 문제(APP-204)는 반대 값 시드 + 회귀 게이트로 따로 잡아야 했다.