Skip to content

Design → Codex 전달 계약

제정: 2026-08-19 (오너 확정) · 관리: PM(쿠리어)

개정: 2026-09-11 오너 결정 #1568. 화면 계약 변경 시 디자인 로컬 샘플이 오래된 화면을 그리는 문제를 해결하기 위해, 타입 검사되는 데이터 fixture를 앱 저장소에서 함께 관리한다. 시연 로직의 프로덕션 유입 금지는 유지한다.

의도: Design이 시연을 위해 만든 목업 로직·데이터가 프로덕션 의미론으로 굳는 것을 규칙이 아니라 구조로 차단한다. UX 의미론(상태 선택·판정·집계·전환)의 전달 규범은 계약문 하나로 고정한다. 전달 채널에 관한 한 이 문서가 docs/process/claude-free-design-contract.md·docs/process/claude-handoff-rules.md보다 우선한다.

배경

Design이 화면 안에 짜 넣은 목업 로직(상태 판정·정렬·집계)이 그대로 프로덕션 렌더 경로에 실려 정규 의미론이 되는 사고가 반복됐다. 대표 사례: 모바일 종목 상세의 빈 상태 판정이 "실측 1RM 유무"로 굳어져 훈련량 2위 종목이 "기록 없음"으로 표시된 버그, 프리뷰용 임시 검색 정렬이 정규 로직으로 유출된 사례. 상대가 LLM 에이전트인 이상 "참고하되 따르지 마라"는 지켜지지 않는다 — 컨텍스트에 있는 동작하는 코드는 사실상 규범이 된다. 따라서 경계를 화면 props 계약·타입 검사·프로덕션 import 경계로 강제한다. 데이터 fixture는 공유하지만 시연용 계산이나 관측 snapshot을 제품의 판정 근거로 가져오지 않는다.

구조

역할 경계는 두 층이다 — Design은 표현을, Codex는 의미론을 소유한다.

위치소유담당
표현src/react/ui/**Claude Design상태들의 생김새, intent 콜백 발화, 일시적 표현 상태
의미론src/react/services/**Codex어떤 상태가 언제 나오는지의 구속력 있는 정의 (viewMappers·공유 판정 모듈)

fixture·preview는 시연·테스트 도구다. 데이터 fixture는 앱 src/react/ui/mobile/fixtures/<screen>.fixture.ts(데스크톱은 ui/desktop/fixtures/)에 저장하고 화면 props 타입으로 검사한다. 공용 합성 원본·시드 관측은 ui/shared/fixtures/에 둔다. 콜백과 외부 사진 URL은 포함하지 않고 상대 날짜를 소비 시점에 해석한다. 앱 빌드 진입점에서는 import하지 않는다.

Claude Design은 다음 재싱크에서 화면 파일·fixture·관련 타입·정적 자산을 verbatim 반입하고 로컬 _fixtures/를 폐기한다. 프리뷰 조작 콜백은 소비 측이 주입한다. Codex도 fixture를 읽고 실제 시드와 대조하되, 계약에 없는 제품 의미론을 fixture에서 추론하지 않는다. 구체적인 사용법은 셸 계약의 fixture 절을 따른다.

  • Design 딜리버리 스코프는 앱 src/react/ui/**와 문서 저장소 docs/contracts/**다. 화면 데이터 계약을 바꾸는 앱 PR은 대응 fixture·관련 데이터 타입을 같은 PR에서 갱신하고 문서 PR을 연결한다.
  • 전달 채널의 규범은 계약문(docs/contracts/*-props.md) 하나다. CHANGE-NOTES는 계약 앵커를 가리키는 변경 목록, 화면 소스는 prop 이름·구조의 기계적 사실이다. 충돌 시 계약문이 이긴다.

Design 규칙

  • 판정·집계·전환 로직을 ui/**/screens에 넣지 않는다. domain 의미를 갖는 값은 계산된 결과가 prop으로 온다 — prop에는 재료가 아니라 결론을 싣는다.
  • 인터랙션 지시("이거 누르면 이게 나오게")의 요구 산출물은 2종: ① 관련 상태들의 생김새(screens) ② 계약문의 전환 규칙 표 + CHANGE-NOTES 앵커 한 줄.
  • 전환 규칙은 산문이 아니라 표로 쓴다: 트리거 → 상태 변화 → 복귀 경로.
  • 각 prop의 의미를 계약문에 명시한다. 순서·선별·개수가 의미를 가지면(검색 랭킹, 상위 N, 정렬 기준) 그 규칙도 계약문에 명시한다 — fixture의 나열 순서는 규범이 아니다.
  • CHANGE-NOTES 배선 항목은 신규 intent onX — 계약 §섹션 참조 형식의 한 줄 포인터로 쓴다.

Codex 규칙

  • 배선하는 모든 전환·판정 의미론은 계약문 앵커를 인용하고, 매퍼 단위 테스트로 고정한다.
  • 계약문에 없는 동작을 시연 재료에서 추론하지 않는다. 합의된 계약과 실제 컨테이너의 props를 기준으로 fixture를 갱신한다.
  • ui/** 수정 권한은 기존 R&R 그대로(합의된 props/callback 연결, 이벤트 포워딩, 중복 business logic 제거, 마커·접근성·타입 보완 — 시각 변경 금지). 화면 내 domain 파생을 props 소비로 바꾸는 것은 허용 범위다.

판정 기준

그 계산이 틀렸을 때 — "데이터가 틀렸다"고 느껴지면 의미론(services로), "표시가 어색하다"고 느껴지면 표현(화면에 남아도 된다).

이관 정책

  • 신규 작업은 즉시 적용: 새 화면·새 상태·새 인터랙션은 이 계약대로만 전달·배선한다.
  • 기존 화면 내 파생은 기회 이관: 버그나 딜리버리가 건드릴 때 매퍼/공유 모듈로 옮긴다. 빅뱅 이관은 하지 않는다.
  • 파일럿: 종목 상세 빈 상태 판정 3벌(mobile RecordsDetail, desktop prDetail, DesktopPrDetailParts)을 매퍼가 내려주는 hasRecords 소비로 통일.
  • 백로그: 모바일 화면 prop 타입 강화(MobileProps 느슨한 타입 → 데스크톱 DesktopPrScreenTypes.ts 수준) — 완성 시 계약문(합의)·tsc(형태)·매퍼 테스트(행동)의 3중 기계 검증이 성립한다.

반입 게이트 (쿠리어 감사 — 반려 사유)

  1. ui/**/screens의 신규 domain 파생(미선언).
  2. 계약문 앵커 없는 CHANGE-NOTES 배선 항목.
  3. 대응 fixture·타입이 누락된 화면 props 변경, 별도 로컬 _fixtures/ 원본, fixture의 콜백·외부 사진 URL, 제품 runtime에서 fixture/preview import. 타입이 맞는 공용 fixture는 화면과 함께 반입한다.

관련 문서

  • docs/process/claude-free-design-contract.md — R&R, 마커 계약
  • docs/process/claude-handoff-rules.md — Design↔Codex 워크플로
  • src/react/ui/README.md — Design 구현 브리프
  • AGENTS.md — Codex 작업 지침