Skip to content

feat: 큐레이션 시음회·프로그램 장소검색 계약 정렬 (장소명·우편번호) - #681

Merged
Whale0928 merged 3 commits into
Whale0928/feed-read-pathfrom
Whale0928/curation-place-search
Jul 28, 2026
Merged

feat: 큐레이션 시음회·프로그램 장소검색 계약 정렬 (장소명·우편번호)#681
Whale0928 merged 3 commits into
Whale0928/feed-read-pathfrom
Whale0928/curation-place-search

Conversation

@Whale0928

Copy link
Copy Markdown
Collaborator

배경

  • 이슈: [BE] Curation v2 시음회·프로그램 장소검색 requestSpec 계약 정렬 workspace#344
  • Admin 시음회 form이 requestSpec에 없는 placeName을 FE 하드코딩으로 주입해 submit하고 있었다. CurationPayloadValidator가 미정의 property를 차단하지 않아 그대로 저장된다 — 개발 DB 시음회 14건 중 12건에 실제로 들어 있다
  • 그 결과 계약이 어긋나 있다. 상세 API는 원본 payload를 그대로 내보내므로 placeName이 이미 응답에 나오지만(GET /v2/curations/6placeName: "도시술"), 피드 API와 feed_payload에는 없다. responseSpec에 없어 x-feed 투영에서 빠지기 때문이다
  • PROGRAMplaceNamerequestSpec·responseSpec에 모두 있고 x-feed도 켜져 있다. 시음회를 맞추는 것이 일관성 회복이다

base가 main이 아니라 Whale0928/feed-read-path(PR #680)다. #680 머지 후 리뷰 가능하다.

변경 사항

리소스 JSON 두 개만 바꾼다. 코드·스키마 변경 없음.

WHISKY_TASTING_EVENT

필드 requestSpec responseSpec
placeName 신규, string, maxLength 100, 장소명, address-search 신규, x-feed 켬 (role location, order 25)
zipCode 신규, string, length 5 고정, 우편번호, address-search 신규, x-feed 없음
  • 둘 다 optional. required는 기존 8개 그대로다. required로 올리면 placeName 없는 시음회 2건과 zipCode 없는 전 15건이 어드민 재저장 시 CURATION_PAYLOAD_INVALID로 실패한다
  • placeNamex-feed order를 25로 끼워 기존 order(10·20·30·…)를 하나도 건드리지 않으면서 장소명이 주소 앞에 오게 했다
  • barAddress("장소 및 바(bar) 주소")와 detailAddress("상세 주소")는 이름·의미·스타일 모두 현행 유지

PROGRAM

  • zipCode 신규 (optional)
  • placeName·addressx-field-styleplain-textaddress-search. 이슈는 address만 언급하지만 한쪽만 바꾸면 시음회와 계약이 어긋난다
  • x-field-style은 렌더링 힌트라 응답 값에는 영향이 없다

구현 중 발견해 결정한 것

CurationPayloadValidatorpattern을 검증하지 않는다. 지원하는 제약은 type·required·nullable·enum·maxLength·minLength·maximum·minimum·maxItems·minItems뿐이고, 기존 큐레이션 스펙에 pattern 사용처도 0건이었다. 그대로 뒀다면 지키지도 않는 제약을 계약서에 적어두는 셈이었다.

그래서 zipCodeminLength: 5 + maxLength: 5를 함께 걸었다. 길이는 서버가 실제로 강제하고, pattern: ^\d{5}$는 숫자 제약을 FE·문서용으로 남긴다. review 도메인은 Bean Validation @Pattern을 쓰지만 큐레이션 payload는 자유형 JSON이라 같은 방식을 쓸 수 없다. 검증기에 pattern 지원을 추가하는 것은 후속 과제로 남긴다.

검증

  • 전 단계 PASS, 실패 0: unit 502건(mono 275 / product 206 / observability 21), rule 63건,
    integration 268건, admin integration 209건, admin default 58건, restDocs 136건, Spotless
  • CurationPlaceFieldContractTest 9건 신규
    • placeName 없는 기존 payload가 그대로 통과 (회귀 없음)
    • zipCode가 5자가 아니면 거부
    • 피드에 placeName 포함, zipCode 미포함
    • required 배열이 8개에서 늘지 않음
    • 네 스펙 문서 모두 validateSpec 통과
  • 상세 경로 회귀: responseSpecplaceName이 들어가면서 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만 수정하는 범위였다
  • 미정의 property 차단 — 막으면 FE가 보내는 다른 필드까지 깨질 수 있어 별건이다
  • FE 연계 — 이슈에 적힌 대로 barAddress 전용 자동 동기화 의존 제거, 필드별 선택 결과 저장 대상 연결은 FE 작업이다. 이 PR은 그 매핑의 백엔드 계약을 확정한다

FE 필드 매핑 (계약 확정)

장소검색 선택 결과 시음회 프로그램
장소명 placeName placeName
우편번호 zipCode zipCode
선택 주소 barAddress address
상세 위치(사용자 입력) detailAddress detailLocation

Whale0928 and others added 3 commits July 28, 2026 16:46
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>
@Whale0928
Whale0928 merged commit de9396f into Whale0928/feed-read-path Jul 28, 2026
8 checks passed
@Whale0928
Whale0928 deleted the Whale0928/curation-place-search branch July 28, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant