feat: 큐레이션 시음회·프로그램 장소검색 계약 정렬 (장소명·우편번호) - #681
Merged
Whale0928 merged 3 commits intoJul 28, 2026
Conversation
Admin 시음회 form이 requestSpec에 없는 placeName을 FE 하드코딩으로 주입해 저장하고 있었다(개발 DB 14건 중 12건). 스펙을 SSoT로 되돌린다. placeName과 zipCode를 requestSpec·responseSpec에 추가하고 둘 다 optional로 둔다. required로 올리면 placeName 없는 기존 2건과 zipCode 없는 전 건이 어드민 재저장 시 검증 실패한다. placeName은 x-feed를 켜 피드에 노출한다. order는 시간(20)과 주소(30) 사이인 25로 끼워 기존 order 값을 건드리지 않는다. zipCode는 피드에 싣지 않는다. CurationPayloadValidator가 pattern을 검증하지 않으므로 zipCode에 minLength/maxLength 5를 함께 건다. 길이는 서버가 강제하고 pattern은 FE·문서용으로 남긴다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
placeName과 address의 x-field-style을 plain-text에서 address-search로 바꾸고 zipCode를 optional로 추가한다. 이슈는 address만 언급하지만 한쪽만 바꾸면 시음회와 계약이 어긋난다. x-field-style은 렌더링 힌트라 응답 값에는 영향이 없다. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경
requestSpec에 없는placeName을 FE 하드코딩으로 주입해 submit하고 있었다.CurationPayloadValidator가 미정의 property를 차단하지 않아 그대로 저장된다 — 개발 DB 시음회 14건 중 12건에 실제로 들어 있다placeName이 이미 응답에 나오지만(GET /v2/curations/6→placeName: "도시술"), 피드 API와feed_payload에는 없다.responseSpec에 없어x-feed투영에서 빠지기 때문이다PROGRAM은placeName이requestSpec·responseSpec에 모두 있고x-feed도 켜져 있다. 시음회를 맞추는 것이 일관성 회복이다변경 사항
리소스 JSON 두 개만 바꾼다. 코드·스키마 변경 없음.
WHISKY_TASTING_EVENT
placeName장소명,address-searchx-feed켬 (rolelocation, order 25)zipCode우편번호,address-searchx-feed없음required는 기존 8개 그대로다. required로 올리면placeName없는 시음회 2건과zipCode없는 전 15건이 어드민 재저장 시CURATION_PAYLOAD_INVALID로 실패한다placeName의x-feedorder를 25로 끼워 기존 order(10·20·30·…)를 하나도 건드리지 않으면서 장소명이 주소 앞에 오게 했다barAddress("장소 및 바(bar) 주소")와detailAddress("상세 주소")는 이름·의미·스타일 모두 현행 유지PROGRAM
zipCode신규 (optional)placeName·address의x-field-style을plain-text→address-search. 이슈는address만 언급하지만 한쪽만 바꾸면 시음회와 계약이 어긋난다x-field-style은 렌더링 힌트라 응답 값에는 영향이 없다구현 중 발견해 결정한 것
CurationPayloadValidator는pattern을 검증하지 않는다. 지원하는 제약은type·required·nullable·enum·maxLength·minLength·maximum·minimum·maxItems·minItems뿐이고, 기존 큐레이션 스펙에pattern사용처도 0건이었다. 그대로 뒀다면 지키지도 않는 제약을 계약서에 적어두는 셈이었다.그래서
zipCode에minLength: 5+maxLength: 5를 함께 걸었다. 길이는 서버가 실제로 강제하고,pattern: ^\d{5}$는 숫자 제약을 FE·문서용으로 남긴다. review 도메인은 Bean Validation@Pattern을 쓰지만 큐레이션 payload는 자유형 JSON이라 같은 방식을 쓸 수 없다. 검증기에pattern지원을 추가하는 것은 후속 과제로 남긴다.검증
integration 268건, admin integration 209건, admin default 58건, restDocs 136건, Spotless
CurationPlaceFieldContractTest9건 신규placeName없는 기존 payload가 그대로 통과 (회귀 없음)zipCode가 5자가 아니면 거부placeName포함,zipCode미포함required배열이 8개에서 늘지 않음validateSpec통과responseSpec에placeName이 들어가면서materialize의 검증 대상이 됐다. 기존 저장값 통과와 100자 초과 거부를 각각 고정했고, 개발 DB 실측으로 기존 15건이 최대 9자, 비문자열 0건, 100자 초과 0건임을 확인했다배포 시 동작
responseSpec이 바뀌므로 PR #680의 재생성이 두 스펙에 대해 자동 실행된다. 개발 DB 기준 시음회 14건 + 프로그램 1건의feed_payload가 갱신되어placeName이 채워진다. 별도 backfill 작업이 필요 없다.피드 응답에
placeName이 추가되는 것은 가산적 변경이라 기존 클라이언트를 깨지 않는다.제외 범위 (후속 과제)
placeName·zipCode의 required 승격 — FE가 장소검색을 연결해 데이터가 채워진 뒤pattern지원 — 이번엔 리소스 JSON만 수정하는 범위였다barAddress전용 자동 동기화 의존 제거, 필드별 선택 결과 저장 대상 연결은 FE 작업이다. 이 PR은 그 매핑의 백엔드 계약을 확정한다FE 필드 매핑 (계약 확정)
placeNameplaceNamezipCodezipCodebarAddressaddressdetailAddressdetailLocation