generated from ttipo/project-base
feat(backend): 장소·축제·공연·전시 데이터 기반(장소 DB·동기화·조회 API) #1
Reference in New Issue
Block a user
Delete Branch "feat/place-db"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
무엇을 · 왜
MVP 의 데이터 기반이다. 카카오·네이버 장소 데이터는 저장할 수 없어서, 공공데이터·KOPIS·한국문화정보원 데이터를 자체 DB 에 받아 앱이 그 DB 를 조회하게 했다.
1차 지역은 대구이고, 축제·공연·전시는 근교인 경북까지 받는다.
place·place_curation·place_i18n·place_sync_run테이블과place_listing뷰(앱에 노출할 값·AI 후보 등급의 단일 기준), 행사·공연장 테이블, 마이그레이션 5개npm run place:sync -- <작업>GET /api/places·/api/places/{id}·/api/events·/api/events/{id}(거리순·커서 페이지네이션·출처 표기)[대구]등)는 떼고(앵콜)같은 메모는 남긴다.security.md에 유예로 기록했다.maxWorkers: 1) — 빈 DB 에서 여러 스위트가 동시에 마이그레이션하다 부딪히는 문제를 막는다. CI 도 빈 DB 를 쓴다.tools/data-check/)spikes/).dockerignore, 개발 백엔드 메모리 2GB설계:
docs/design/place-db.md(v1.7)확인 방법
npm ci가 npm 10 · 11.6 · 11.20 에서 모두 통과backend/.env.{env}의PUBLIC_DATA_SERVICE_KEY·KOPIS_SERVICE_KEY)영향 범위
.dockerignore만)spikes/naver_map_spike는 별도 시험 앱).dockerignore, 개발 백엔드 메모리 한도)security.md: 유예 취약점 기록testing.md: e2e 순서 실행 규칙체크리스트
BusinessException/error.code분기)npm run sync:error-codes실행 후 생성 파일까지 커밋 — 해당 없음*.example값은 placeholder)🤖 Generated with Claude Code
없으면 Dockerfile 의 `COPY . .` 가 폴더를 통째로 이미지에 넣는다. Windows 호스트에서 백엔드 빌드 컨텍스트가 263MB(호스트 node_modules 포함)로 4분 넘게 걸렸고, 두 가지 문제가 있었다. - 호스트(Windows) node_modules 가 컨테이너의 Linux 모듈을 덮어써 swc 등 네이티브 모듈이 깨질 수 있다 - backend/.env.{환경} 의 키가 이미지 레이어에 남는다(env 는 compose 가 실행할 때 넣으므로 이미지에 필요 없다) node_modules·dist·coverage·.env*·uploads 등을 제외해 컨텍스트가 약 1MB 가 됐다. 프론트엔드는 VITE_API_BASE_URL 을 build arg 로 받으므로 결과가 같다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>검색·지도·상세 화면이 장소 DB 를 쓰도록 조회 API 를 연다(비로그인 허용). - GET /api/places: 이름 검색, 좌표+반경 거리순, 분류·반려동물·실내 필터, 키셋 커서 페이지네이션(정렬값+id), 전체 개수, 항목별 "지금 영업 중"(KST) - GET /api/places/{id}: 영업시간 원문·해석 상태·출처, 반려동물 크기·조건, 이용 안내(요금·주차 등), 추천 이유(추천+확인한 곳만), 출처 표기. 병합된 id 로 들어오면 병합 대상 장소를, 숨김·폐업 추정이면 RES_001 을 준다 - 같은 가게 병합: 관광공사 쪽이 카페·식당·주점이고 100m 안이며 상호가 같거나 포함(짧은 쪽 2글자 이상)이면 상가정보 쪽을 merged_into_id 로 관광공사 쪽에 합친다. tour-kor·store 가 끝날 때 자동으로, place:sync -- dedupe 로 따로도 돈다 - 사후면세점 브랜드 매장(SH040300)은 목록·필터에서 빼고 이름 검색에만 낸다 (반려동물 필터 결과가 더현대 입점 매장으로 덮이던 문제) - 공공 반려동물 조건 원문의 글머리표·줄바꿈 정리 e2e(test/place.e2e-spec.ts)는 시작할 때 마이그레이션을 적용하고 동해 좌표에 테스트 장소를 만들어 노출 규칙·필터·커서·상세·오류 코드를 검증한다. 2026-11-02 대구 실측: 같은 가게 21곳 병합, 도심 반려동물 필터 7곳. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>홈 '이번 주말 축제·행사'와 장소 상세 '근처 축제·행사'에 쓸 데이터를 채운다. - place:sync -- event: 관광공사 searchFestival2 를 오늘~90일 기간으로 받아 festival_event 에 upsert(서버는 기간이 겹치는 행사를 준다). 지역 조건을 보내고 응답에서도 다른 지역 행사는 거른다. 상세(소개·요금·공연 시간·장소)는 새로 생기거나 수정된 행사만 받는다. 기간 안에서 목록에 없는 행사는 숨긴다 - GET /api/events: 기간(기본 오늘~30일, 최대 92일)·근처(좌표+반경)·분류·커서. 60일 넘는 상시 프로그램과 숨김 행사는 뺀다. 항목에 오늘 진행 중 여부 - GET /api/events/{id}: 소개·공연 시간·요금·장소·홈페이지·출처 - 마이그레이션: festival_event 에 분류 코드·지역 코드·장소명·전화·홈페이지· 작은 사진·원본 수정일·상세 수신 시각 추가 e2e(test/festival.e2e-spec.ts)는 2030년 날짜·동해 좌표 픽스처라 실행 날짜와 무관하다. 2026-11-03 실측: 앞으로 90일 관광공사 행사는 전국 106건, 대구 1건, 경북 7건. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>한국문화정보원에 같은 전시가 제목만 다르게 두 번 등록되어 목록에 2건으로 나왔다 ("문준호 전 - 남겨진 것들을 위한 풍경" / "문준호 《남겨진 것들을 위한 풍경》", 같은 갤러리·같은 기간). 같은 장소 · 같은 시작·종료일 · 제목 비교 키가 연속 6글자 이상 겹치면 같은 전시로 보고 먼저 등록된 것만 남긴다. 장소·기간만으로 합치지 않는 이유는 여러 전시실에서 같은 날 여러 전시를 여는 곳이 있어서다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>chore(backend): 공공데이터·카카오·Claude API 키 환경변수 예시 추가to feat(backend): 장소·축제·공연·전시 데이터 기반(장소 DB·동기화·조회 API)