목적
F1 adapter의 ShopperPreference 입력 화면을 구현한다. 예산(budget_krw) · 쇼핑몰(retailer_scope) · 성별(gender) · 국가(country)를 사용자가 설정하고, client-only fit(오버/슬림/무관)은 ShopperPreference 분리, FE 상태로만 관리 한다. 모든 조건이 기본값을 가지므로 스킵 가능 — ④ Recommended로 진행하거나 설정값을 반영한 추천을 받는다.
범위
화면 설계 (wireframes.md §2 ③)
레이아웃 · 상태 관리 · 조건값 변경
F1 adapter(cody-match.ts)의 ShopperPreference 타입 사용
client-only fit 분리 (ShopperPreference에 fit 필드 없음 — ClientOnlyFitPreference로 별도 관리)
budget → preference_variant tier 매핑 참조(F7 reconcile에서 상세화)
비로그인 가능, auth 미필요
실패 상태 없음 (모든 값이 valid default 존재)
화면 스펙
컴포넌트
예산 슬라이더 (budget_krw, 단위 원)
3단 preset: 20만 / 50만 / 무제한(0)
슬라이더 or 버튼 세트, 자유 입력 가능(선택)
기본값: 50만(budget-500k tier, mvp-scope §2 기준)
쇼핑몰 체크박스 (retailer_scope)
☑ 무신사
☑ 29CM
☑ W컨셉
☑ 전체 (추후 글로벌 옵션, Phase 2)
기본값: 무신사 + 29CM (kr scope)
다중 선택 가능
성별 (gender)
국가 (country, 선택적)
기본값: "KR"
드롭다운(Phase 2에서 multi-country 지원 시 활성화)
핏(오버/슬림/무관) — client-only, ShopperPreference 아님
▢ 오버
☑ 슬림
▢ 무관
기본값: 슬림
이 필드는 ClientOnlyFitPreference (UI 전용) 로 관리 — backend ShopperPreference.fit 없음(CONTEXT.md 정의)
상태
default : 모든 필드가 기본값. 제출 버튼 활성화.
loading : 없음. client-only → 즉시 반영.
error : 없음. 모든 값이 valid.
empty : 해당 없음.
전환
[이 조건으로 추천 → ④] : 설정값을 담아 ④ Recommended로 이동
store 업데이트: ShopperPreference(budget_krw, retailer_scope, country, gender) + ClientOnlyFitPreference(fit)
F5가 이 값을 읽어 추천 재계산
[건너뛰고 추천 → ④] : 기본값으로 ④로 진행
[← Analysis] : 뒤로가기 → ② Analysis로 돌아감
Acceptance Criteria
app/cody/conditions/page.tsx 생성 — 예산·쇼핑몰·성별·핏 입력 폼
lib/stores/codyStore.ts에 ShopperPreference + ClientOnlyFitPreference 상태 추가
ShopperPreference: budget_krw, retailer_scope('kr'|'global'|'both'), country, gender('male'|'female'|'unisex'), excluded_brands[], preferred_retailers[]
ClientOnlyFitPreference: 'over'|'slim'|'any' (FE 전용, backend 미송신)
기본값 설정: budget_krw=500_000, retailer_scope='kr', country='KR', gender='unisex', fit='slim'
슬라이더/버튼으로 budget_krw 변경 시 store 즉시 업데이트
체크박스로 retailer_scope 변경 시 store 즉시 업데이트
fit(오버/슬림/무관) 변경은 ShopperPreference 아님 — ClientOnlyFitPreference만 업데이트 확인
[이 조건으로 추천] 클릭 → store에 현재값 저장 후 app/cody/recommended 라우트 이동
[건너뛰고 추천] 클릭 → 기본값 초기화 후 ④로 이동
[← Analysis] 클릭 → app/cody/analysis 로 뒤로 이동
lib/components/cody/ConditionsForm 컴포넌트 추가(또는 inline)
VTON 무의존성 검증 : app/cody/conditions/*에서 lib/components/vton, lib/stores/vtonStore, /api/v1/vton import 0건 확인
fit 분리 확인 : ShopperPreference 타입에 fit 필드 없고, ClientOnlyFitPreference로만 관리
핵심 파일
경로
역할
packages/web/app/cody/conditions/page.tsx
③ Conditions 화면 페이지 컴포넌트
packages/web/lib/stores/codyStore.ts
ShopperPreference + ClientOnlyFitPreference 상태 저장소 (F1이 먼저 기초 설정)
packages/web/lib/components/cody/ConditionsForm.tsx (선택)
예산·쇼핑몰·성별·핏 폼 컴포넌트
packages/web/lib/api/adapters/cody-match.ts
F1이 정의한 단일 adapter (ShopperPreference 타입 import)
금지 경로 : /recreate, /request, /(request), /(consumer), /cody/screens, /cody/detail
mock · real 경계
Mock : client-only, 즉시 반영. 백엔드 호출 없음.
Real : F5(Recommended)가 이 상태를 읽어 POST /raw-posts/{id}/match?variant=<tier> 호출 시 ShopperPreference 전달.
단, fit은 전달 안 함 — F5가 FE 필터로만 처리(Phase 2+에서 backend로)
Contract 출처 : cody-match-stage2 §2.1 (ShopperPreference, 4-tier budget bucketing) · mvp-scope §2·§1 P4
의존성
F1 (Adapter) : ShopperPreference 타입 + codyStore 초기화
F3 (Analysis) : ③로의 [조건 설정] CTA는 ② 화면에서 발생 → 라우트 기준 정확성
F5 (Recommended) : ShopperPreference를 읽어 추천 요청 시 전달
제약 · 주의
ShopperPreference ≠ ClientOnlyFitPreference : CONTEXT.md 정의 준수
ShopperPreference (backend): budget_krw, retailer_scope, country, gender, excluded_brands, preferred_retailers
ClientOnlyFitPreference (FE): 'over'|'slim'|'any'
codyStore에는 둘 다 저장되지만, F5 요청 시 ShopperPreference만 backend로 송신
단일 adapter 규칙 : cody-match.ts에만 ShopperPreference 타입 정의 — codyAdapterConditions.ts, conditions/adapter.ts 등 별도 파일 생성 금지
budget → preference_variant 매핑 :
20만 → F7에서 확정 (미정: custom budget_krw=200_000 vs snap budget-100k). 본 이슈는 단정하지 않음
50만 이하 → budget-500k
100만 이하 → budget-1M
0(무제한) → authentic
구체적 매핑은 F7 reconcile 체크리스트에서 확정(본 이슈는 예산값 저장만)
기본값 모두 valid : 모든 필드가 스킵 가능 — ④에서도 기본값으로 추천 수신 가능
모바일 우선 (wireframes.md §0): 360–390px 기준 세로 뷰포트
참조
wireframes.md §2 ③ Conditions — 레이아웃·컴포넌트·상태
mvp-scope.md §2·§1 P4 — 조건 화면 정의
cody-match-stage2.md §2.1 — ShopperPreference 타입 (backend 계약)
CONTEXT.md — Shopper Preference · Client-only Fit Preference · 용어 정의
user-scenarios.md §4 — 실패 상태(F4는 없음)
[[F1]] — ShopperPreference 타입 정의 · codyStore 초기화
[[F5]] — ShopperPreference 소비 (추천 요청 시)
목적
F1 adapter의
ShopperPreference입력 화면을 구현한다. 예산(budget_krw) · 쇼핑몰(retailer_scope) · 성별(gender) · 국가(country)를 사용자가 설정하고, client-only fit(오버/슬림/무관)은 ShopperPreference 분리, FE 상태로만 관리한다. 모든 조건이 기본값을 가지므로 스킵 가능 — ④ Recommended로 진행하거나 설정값을 반영한 추천을 받는다.범위
cody-match.ts)의 ShopperPreference 타입 사용화면 스펙
컴포넌트
예산 슬라이더 (
budget_krw, 단위 원)쇼핑몰 체크박스 (
retailer_scope)성별 (
gender)국가 (
country, 선택적)핏(오버/슬림/무관) — client-only, ShopperPreference 아님
상태
전환
Acceptance Criteria
app/cody/conditions/page.tsx생성 — 예산·쇼핑몰·성별·핏 입력 폼lib/stores/codyStore.ts에 ShopperPreference + ClientOnlyFitPreference 상태 추가app/cody/recommended라우트 이동app/cody/analysis로 뒤로 이동lib/components/cody/ConditionsForm컴포넌트 추가(또는 inline)app/cody/conditions/*에서lib/components/vton,lib/stores/vtonStore,/api/v1/vtonimport 0건 확인핵심 파일
packages/web/app/cody/conditions/page.tsxpackages/web/lib/stores/codyStore.tspackages/web/lib/components/cody/ConditionsForm.tsx(선택)packages/web/lib/api/adapters/cody-match.ts금지 경로:
/recreate,/request,/(request),/(consumer),/cody/screens,/cody/detailmock · real 경계
POST /raw-posts/{id}/match?variant=<tier>호출 시 ShopperPreference 전달.의존성
제약 · 주의
ShopperPreference ≠ ClientOnlyFitPreference: CONTEXT.md 정의 준수
단일 adapter 규칙: cody-match.ts에만 ShopperPreference 타입 정의 — codyAdapterConditions.ts, conditions/adapter.ts 등 별도 파일 생성 금지
budget → preference_variant 매핑:
budget_krw=200_000vs snap budget-100k). 본 이슈는 단정하지 않음기본값 모두 valid: 모든 필드가 스킵 가능 — ④에서도 기본값으로 추천 수신 가능
모바일 우선 (wireframes.md §0): 360–390px 기준 세로 뷰포트
참조