E2E Handoff — Product Info Property + Sales Rules
E2E Handoff — Product Info Property + Sales Rules
핵심 spec:
./product-info-property-and-sales-rules.mdPhase 0 testbed에서 PDP 노출 + 어드민 IA까지 본 사이클로 끝났다. 남은 제품/정책 의사결정은
backlog/product-revamp-followups에서 추적한다.
목적: 스크린샷/브라우저 눈검수가 아니라,
makitt web상품 form submit이 실제 admin API 저장 → shop-api PDP 응답까지 연결되는지를 스크립트로 검증한다.
검증 대상
- Shop: henriette (
71261f65-ee4e-4238-9b4f-d56cee9be523) - Product: 세피라샷 해파리 모공 세럼 (
386d4ca2-6dbf-43bb-9d5e-47e215589ebc) - Slug:
cephira-shot-jellyfish-pore-serum - Seller token:
chance@makitt.io개발자 토큰 - Admin API:
http://localhost:8080 - Shop API:
http://localhost:10000
Shop API i18n dev-bypass
E2E는 브라우저 쿠키 없이 shop-api customer/i18n context를 시뮬레이션한다.
curl \
-H "Authorization: Bearer dev-bypass" \
-H "X-Dev-Language: en" \
-H "X-Dev-Currency: USD" \
http://localhost:10000/shop/{shopId}/products/by-slug/{slug}
Authorization: Bearer dev-bypass: local/dev customer context 우회 생성X-Dev-Language: PDP translation overlay language overrideX-Dev-Currency: pricing context / price label currency override- 자세한 운영 메모:
.agents/memory/shop_api_dev_bypass_i18n.md
E2E 스크립트
node scripts/e2e/product-i18n-form-submit.mjs
스크립트가 재현하는 흐름:
POST /api/v1/admin/developer/token/email로 henriette seller token 발급GET /api/v1/products/{productId}/detail로ProductFormV2edit form의 초기 source payload 확보PUT /api/v1/products/{productId}로 form edit submit과 같은 product update 요청 수행GET /api/v1/shops/{shopId}/products/{productId}/translations로 언어별 draft 로드PUT /api/v1/shops/{shopId}/products/{productId}/translations/{language}로 번역 draft 저장GET /shop/{shopId}/products/by-slug/{slug}를ko/KRW,en/USD,ja/JPYcontext로 호출해 PDP 응답 검증
통과 기준
- Product update가 base product의
name/featuredPrice를 보존한다. - Product translation API가
en,jatranslatedFields를 round-trip 저장한다. - Shop API PDP가 언어별로 아래 필드를 번역 적용한다.
nameshortDescriptiondescriptioncategoryNamebrandNameseo.title→seoTitleseo.description→seoDescription
- Shop API PDP가 가격 context를 별도 파이프라인으로 적용한다.
ko/KRWen/USDja/JPY- 각 응답의
currencyCode,featuredPrice,featuredPriceLabel검증
결과
2026-05-02 로컬 재실행 서버 기준 통과:
✓ Product i18n form-submit E2E passed
확인된 구현 경계
- 상품 본문/SEO 중심 번역은 UX → admin API → DynamoDB
ContentTranslation→ shop-api PDP까지 연결됐다. - 가격은 상품 번역 row가 아니라 shop preference의 market locale / pricing context를 통해 적용된다. 따라서 상품 국제화 UX에서는 마켓별 통화 context를 보여주되, 가격 변환·표시는 shop-api pricing pipeline을 검증 대상으로 둔다.
- 생성 form에서도 번역 draft를 입력한 뒤 product 생성 성공 후 새
productId로 translation row를 저장할 수 있다. - shop-api by-slug endpoint는 기존부터 translation overlay + price conversion을 수행했고, by-id endpoint도 동일하게 overlay/conversion을 적용하도록 맞췄다.
Production blocking 기준
Production blocking = henriette shop PDP에서 target locale로 보이는 모든 고객 노출 문자열과 고객 노출 상품 자산이 국제화되어야 한다. Core product fields만 번역되는 상태는 통과가 아니다. en/USD, ja/JPY PDP 응답에서 한국어가 고객 노출 영역에 남아 있거나 locale별 이미지/가격 override가 적용되지 않으면 blocker로 본다.
2026-05-06 재검증 결과:
en/USD: visible-copy Hangul audit 통과ja/JPY: visible-copy Hangul audit 통과- PDP price context:
ko/KRW,en/USD,ja/JPY통과 - PDP image translation:
image.main.{index}.url,image.detail.{index}.url,image.thumbnail.url통과 - PDP resolve visible-copy audit:
en,ja통과
2026-05-06 field-level coverage
- Product core —
name,shortDescription,description,categoryName,brandName,supplierName번역 저장·적용. - SEO —
seo.slug,seo.title,seo.description번역 저장·적용. - Images — main/detail/thumbnail image URL을 locale별 translation field로 저장하고 ProductDocument overlay에 적용.
- Variant/options — variant group, option, option value, combination, store item display name 번역 저장·적용.
- Additional info — property group title, property label, property description, property value 번역 저장·적용.
- Pricing — 기본은 shop-api pricing context/FX pipeline을 사용하고, product/store item 단위 currency override를 admin submit payload로 저장·적용.
- Shipping option labels — shop-api
shippingOptionscustomer-facing label에서 locale별 기본 문구 적용.
2026-05-06 E2E command
node scripts/e2e/product-i18n-form-submit.mjs --use-expected-translations
결과:
→ Developer token: chance@makitt.io
→ Load product detail: 71261f65-ee4e-4238-9b4f-d56cee9be523/386d4ca2-6dbf-43bb-9d5e-47e215589ebc
→ Submit idempotent product update, matching ProductFormV2 edit submit
→ Load product translation drafts
→ Submit product translation drafts
→ Assert shop-api PDP language + currency pipeline
✓ Product i18n form-submit E2E passed
남은 UX/운영 확인
- makitt web은 실제 빌드 산출물 기준으로 확인해야 하므로, 최신 form UI 확인 전 web rebuild가 필요하다.
- ProductFormV2에는 별도 “상품 국제화” 섹션을 만들지 않고, 기본정보/이미지/옵션/추가정보/SEO 섹션 내부에 표준 i18n 패널을 배치한다.
- 가격 override는 대표가격과 store item 가격에 각각 제공한다. market profile에서 통화가 비어 있어도 언어 설정 기반 fallback currency를 노출한다.
- custom image group 자체의 PDP contract 적용은 main/detail image pipeline과 별개다. 현재 production blocker는 세피라샷 PDP의 main/detail/thumbnail customer-facing asset 기준으로 닫는다.
구현/검증 항목은 2026-05-06 closeout에서 완료했다. 남은 의사결정 항목은 finished 문서에 open checklist로 유지하지 않고 backlog/product-revamp-followups로 분리했다.
완료된 closeout 범위:
- 셀러 페르소나 풀스택 검증은 shop-api PDP E2E + web prod form smoke로 대체 검증했다.
/merchant/products/policies판매 설정 IA와 legacy/merchant/products/shippingroute 제거를 확인했다.SystemPropertyTemplateSeeder는 legacy/unknown status row 방어 +makitt-api전용 best-effort seed +makitt-shop-apiskip 로그를 확인했다.- PDPPreviewV2는 form state 기반 propertyGroups 시뮬레이션을 지원한다.
- HCS validator pre-commit guard, Template delete-impact UX, legacy policy migration/cleanup endpoint,
propertyTemplateKey잔여 제거를 완료했다.
검증된 testbed 데이터
- finn shop (
3d08aa8c-c31d-48a8-aae2-9c8e0a3ce7ac) — 화장품 1개 product - henriette shop (
71261f65-ee4e-4238-9b4f-d56cee9be523) — 화장품 7개 + 식품 1개
각 shop에 시드된 system templates: purchase.payment.note, purchase.return.note, legal.kr.standard.cosmetic. 같은 키를 운영 시드에서도 사용하므로, 운영 마이그레이션 작성 시 멱등성 보장(이미 존재하면 skip).
빌드 상태
- 서버:
./gradlew build -x test통과 - 클라이언트:
pnpm check-types --filter=@makitt/web통과 - E2E: shop-api 응답 + PDP 빌더 미리보기 모두 검증
세피라샷 상품 수정 화면을 실제 makitt web prod build로 열어 국제화 UX를 브라우저에서 확인했다.
UI 확인 결과
- 기본정보/이미지/옵션·판매항목/추가정보/추천영역/SEO 섹션 내부에 표준 언어 탭 기반 i18n 패널이 렌더된다.
- 각 패널은
English (en),日本語 / Japanese (ja)탭과 입력 수 요약을 표시한다. - 긴 필드 목록은 그룹 disclosure로 나뉜다.
- 기본정보: 상품 표시, 분류/브랜드
- 이미지: 메인 이미지, 상세 이미지
- 옵션: 옵션 표시명, 옵션 값, 조합 표시명, 판매 항목 표시명
- 추가정보: 구매정보, 법정고지 등 property group별
- 추천영역: 추천 섹션 제목
- SEO: 검색 노출
- 이미지 현지화 필드는 thumbnail preview와 URL 입력을 함께 보여준다.
- 가격 override는 대표가격과 판매항목 가격 모두 KRW 기준가/비교가와
자동 환율/수동 가격상태를 표시한다. - SEO preview는 active translation language의 title/description/image/slug 값을 사용한다.
- 브라우저 console의 duplicate form field id issue는 제거됐다.
재검증
node scripts/e2e/product-i18n-form-submit.mjs --use-expected-translations
결과:
✓ Product i18n form-submit E2E passed
추가 안정화
- shop-api PDP detail은 review OpenSearch stats timeout이 발생해도 상품 detail 전체를 500으로 실패시키지 않고 review summary fallback을 반환한다.
Translation data cleanup — 2026-05-06
E2E seed가 production visible-copy 검증을 위해 넣던 placeholder 문자열을 실제 세피라샷 번역값으로 교체했다.
-
제거 대상:
English value ...,English label ...,日本語 value ...,日本語 label ...등 dummy translation copy -
정정 범위: option group/value/combination/store item, purchase/legal property group/label/value
-
scripts/e2e/product-i18n-form-submit.mjs --use-expected-translations는 앞으로도 실제 번역 copy를 seed한다. -
API 재조회 결과:
en,jatranslation row 모두 dummy key 0건 -
shop-api PDP 재조회 결과:
en/USD,ja/JPY모두 placeholder/hangul visible-copy audit clean -
Changed image localization from per-image translation fields to product
imageGroupsmedia sets. -
Seeded Sephyra Shot localized media sets through the same admin product update payload used by ProductFormV2:
localized:en:main/localized:en:detaillocalized:ja:main/localized:ja:detail
-
Verified admin translation rows no longer persist
image.*URL override keys for English/Japanese. -
Verified shop-api PDP applies localized media sets for English/Japanese:
mainImages[0]matches the localized main group first image.thumbnailImagefollows the localized main group first image.detailImages[0]matches the localized detail group first image.
-
Verified Product Admin edit page renders the image UI as
언어별 이미지 세트, not the legacy이미지 현지화per-image field panel. -
Browser smoke:
http://makitt.localhost:3002/en/merchant/products/386d4ca2-6dbf-43bb-9d5e-47e215589ebc- Active shop:
Henriette MAKITT ADMIN - UI snippets:
English · 메인 6 / 상세 33,日本語 · 메인 6 / 상세 33,기본 메인 이미지 복사 - Console error count: 0 after aligning edit form
shopIdto the loaded product's shop.
- Active shop:
Validation commands:
cd makitt-server && ./gradlew :makitt-shop-api:compileJava -Dorg.gradle.java.home=/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home -Dfile.encoding=UTF-8
cd makitt-client && pnpm --filter web check-types
node --check scripts/e2e/product-i18n-form-submit.mjs
./makitt-devctl.sh restart shop-api
./makitt-devctl.sh restart web
node scripts/e2e/product-i18n-form-submit.mjs --use-expected-translations
Validation commands run after devctl restart:
cd makitt-server && ./gradlew :makitt-api:compileJava :makitt-shop-api:compileJava -Dorg.gradle.java.home=/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home -Dfile.encoding=UTF-8
cd makitt-client && pnpm --filter web check-types
./makitt-devctl.sh restart api
./makitt-devctl.sh restart shop-api
./makitt-devctl.sh restart web
node scripts/e2e/product-i18n-form-submit.mjs --use-expected-translations
Results:
makitt-api/makitt-shop-apicompile: passed.@makitt/webcheck-types: passed.- Product i18n form-submit E2E: passed.
- Hardening API E2E: passed.
- system templates present for Henriette shop.
legal.kr.standard.cosmeticdelete-impact returnedattachedProductCount=7.- media tree returned
{ unassigned, other, products }. - legacy product policy migration returned
shopsScanned=56,shopsMigrated=1,policiesCleaned=1.
- Browser smoke: actual prod web build loaded
http://makitt.localhost:3002/en/merchant/products/386d4ca2-6dbf-43bb-9d5e-47e215589ebc; product form showed embedded i18n panels and noEnglish value/English labelplaceholder leak. - Browser smoke:
http://makitt.localhost:3002/en/merchant/content/mediashowed media tree전체 / 미분류 / 기타 / 상품sidebar. - Service log:
makitt-shop-apireportedSystem property template seed skipped: applicationName=makitt-shop-api; seeder now runs frommakitt-apionly.
Deferred decision-only items:
- Legal review for Korean cosmetic disclosure fields.
- Category-to-template preset auto-attach behavior.
- Fragment rendering strategy for non-text property types.
- PDP group visibility control in commerce library.
비어 있음
당신이 처리할 항목