Commit Graph

50 Commits

Author SHA1 Message Date
ttipo 29e9611bd9 docs: AI 코스 생성 설계안 추가
MVP 의 AI 코스 생성(디자인 화면 8–10)을 만들기 전에 흐름·API·비용 보호·평가 방법을 정한다.
DB 가 후보를 고르고 AI 는 후보 번호로만 고르며, 이동 시간·영업·반려 조건 검증과 순서 고치기는 코드가 한다.
화면의 사실 값(영업시간·동반 조건·출처)은 모두 DB 에서 붙여 AI 가 지어낼 수 없게 한다.

§13 의 8가지(하루 횟수·비용 상한·영업시간 미확인·반려 엄격도·이동 시간·공연 제외·보관 기간·모델)는
2026-11-05 사용자가 추천안대로 정했다. 대구 평가셋을 만들며 찾은 것도 반영했다 — 조건 해석 issues 3개,
별칭이 가리키는 장소를 중심으로, 전시는 실내, 실내 후보가 모자라면 알림으로, 코스를 못 만들면 이유를 함께.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 23:23:16 +09:00
ttipo 57f332a731 fix(backend): 쉬는날 문구를 잘못 읽어 영업 중 표시가 틀리던 것 수정
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m37s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 12m11s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m39s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m42s
CI / Frontend (lint · type-check · test) (push) Successful in 11m2s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m25s
관광공사 쉬는날(restdate) 원문에서 'X요일' 낱말만 골라 읽어서, 영업 중 표시가 틀린 장소가 17곳 있었다
(2026-11-05 관광공사 상세 26곳을 받은 뒤 점검).
- "공휴일이면 다음 첫 번째 평일 휴관" 의 '번째' 가 '매월 둘째 일요일' 규칙에 걸려 매주 월요일 휴무까지 빠졌다
  (국립대구박물관 등 4곳이 월요일에 영업 중으로 보였다)
- "월요일~목요일" 은 양 끝 요일만 읽고, "주말"·"평일" 은 아예 읽지 않았다(8곳)
- "일요일을 제외한 공휴일", "월요일이 공휴일인 경우 화요일 휴무" 처럼 조건 속 요일을 정기 휴무로 읽었다(5곳)

쉬는날 원문을 '/'·'※'·괄호 단위 구절로 나눠, 조건·예외 문구는 버리고 요일 범위·평일·주말까지 읽는다.
매주가 아닌 휴무(매월·격주·N주차 등)는 구절마다 판단해 안내로만 남기고, 시설별 쉬는날은 모든 시설이
쉬는 요일만 휴무로 둔다. 시기별 쉬는날은 어느 시기인지 몰라 계절 구분으로 두고 영업 중 판단을 하지 않는다.
영업시간 문장 속 "월요일 휴관" 구절에는 범위·평일을 적용하지 않는다 — 같은 구절의 "월~금 10:00~18:00" 은
여는 요일이다.

reparse-hours 로 22곳이 바뀌었고 모두 원문과 대조했다(위 17곳 + 격주·매달 휴무 4곳 + 시기별 1곳).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:16:50 +09:00
ttipo 43e339a95f fix(flutter): 대구 밖 현재 위치는 대구 도심으로 대신하고 안내함
CI (Flutter) / Flutter (analyze · test) (push) Successful in 20m41s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m16s
CI / Frontend (lint · type-check · test) (push) Successful in 11m4s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m8s
현재 위치를 그대로 쓰면 대구 밖(서울 등)에서는 모든 칸이 "근처에 아직 없어요"로 비었다(2026-11-04 회귀 점검).
서비스 지역(대구, 군위 포함 — 백엔드 geo.ts 와 같은 영역) 밖이면 대구 도심을 기준으로 쓰고,
홈에서 "아직 대구 지역만 볼 수 있어요"를 한 번 알린다.
위치를 받지 못해 대신하는 경우도 지금까지는 기준만 조용히 바뀌었는데, 같은 방식으로 알린다.
대신한 이유는 BasePoint.fallback 에 남는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 15:34:23 +09:00
ttipo 90d41f0e6d fix(backend): KOPIS 에 일정변경으로 다시 등록된 같은 공연을 하나로 합침
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m7s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 10m52s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m21s
CI / Frontend (lint · type-check · test) (push) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (push) Has been cancelled
CI / Backend (lint · test · e2e · build) (push) Has been cancelled
KOPIS 는 일정이 바뀐 공연 제목에 "[일정변경]" 을 붙이고 새 id 로 다시 등록한다. 그래서 같은 공연장·같은 날
같은 공연이 두 번 보였다(2026-11-04 회귀 점검: 고령 남진 콘서트).
- 제목 앞의 "[일정변경]" 은 뗀다(화면에는 바뀐 날짜가 이미 보인다)
- 같은 공연장·같은 기간·같은 제목이면 먼저 등록된 것만 남기고 나머지는 숨긴다

문화포털 전시에 쓰는 "제목 6글자 이상 겹침" 기준은 공연에 쓰지 않는다. 처음 적용했을 때 음악제 이름을 앞에 붙인
같은 날 다른 공연("포항국제음악제, …" 두 공연)을 합쳐 버려서, 제목이 같을 때만 합치게 했다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:37:16 +09:00
ttipo 898ef04266 fix(backend): 관광공사 사진 주소를 https 로 맞춤
관광공사 장소 사진 1,059건 중 279건이 http 였다. 같은 서버(tong.visitkorea.or.kr)가 https 로도 주므로
저장할 때 https 로 바꾼다(장소·행사 모두). 앱은 http 사진도 받지만 웹(https 페이지)에서는 혼합 콘텐츠로 막힌다.
확인하지 않은 다른 서버의 주소는 그대로 둔다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:37:16 +09:00
ttipo 4f50df00d8 fix(backend): 좌표가 주소와 맞지 않거나 실제 위치가 아닌 관광공사 장소를 받지 않음
관광공사 원본 좌표가 실제 위치가 아닌 장소가 거리·지도에 엉뚱하게 나왔다(2026-11-04 회귀 점검).
- 오천서원: 주소는 대구 수성구인데 좌표는 포항이라 대구 목록에 70km 떨어진 곳으로 나왔다
- 대구올레 팔공산 3·4·5코스: 주소·좌표 모두 운영 사무실(수성구)이라 김광석길에서 '도보 7분'으로 보였다

좌표가 주소(없으면 법정동 코드)의 시·도 밖이면 받지 않는다(geo.ts isInSido 재사용).
시·도 검사로 못 거르는 곳은 확인한 contentid 목록(TOUR_WRONG_LOCATION_IDS)으로 받지 않는다.
이미 있던 장소는 목록을 끝까지 받은 뒤 숨겨진다. 관광공사 장소 1,174곳에 적용해 이 4곳만 걸리는 것을 확인했고,
개발 DB 는 tour-kor --skip-details 로 반영했다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:37:15 +09:00
ttipo d4d99c9127 perf(flutter): 사진을 그릴 크기로 줄여 메모리 사용을 줄임
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 20m27s
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 11m41s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 10m47s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m8s
CI (Flutter) / Flutter (analyze · test) (push) Successful in 20m40s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m4s
CI / Frontend (lint · type-check · test) (push) Successful in 10m55s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m7s
공연(KOPIS) 포스터는 목록 썸네일도 원본이라(표본 15개 중앙 0.45MB · 최대 9.2MB) 그대로 풀면
사진 한 장에 수십 MB 를 쓴다. 그릴 크기 × 화면 배율로 가로를 정해 줄여 푼다(memCacheWidth).
cover 는 가로가 긴 사진도 세로를 채우도록 세로 × 2 까지 가로를 두고, 원본보다 크게 늘리지는 않는다.
내려받는 양은 그대로다(원본만 제공된다).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:00:14 +09:00
ttipo c6017fd0ed fix(flutter): 화면 읽기 프로그램으로 누를 수 없던 버튼 6종 수정
Semantics(excludeSemantics: true) 로 감싼 버튼은 안쪽 InkWell 의 누르기 동작까지 지워져
TalkBack·VoiceOver 로 누를 수 없었다(하단 탭 · 언어 · 홈 검색창 · 카테고리 · 기준 위치 · 반려견 칩).
Semantics 에도 같은 onTap 을 준다. 기기 접근성 트리에서 누를 수 있음으로 바뀐 것을 확인했고,
누르기 동작이 빠지면 위젯 테스트가 실패한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:00:14 +09:00
ttipo 5caed15482 fix(flutter): 함께 가기 좋은 곳을 서버 trusted 조건으로 받아 도심에서도 채움
출처와 상관없이 가까운 30곳을 받아 관광공사·확인 장소만 고르던 것을 서버 조건(trusted)으로 바꿨다.
도심에서는 받은 30곳이 모두 상가라 칸이 비었다(봉산서원 0곳 → 6곳, 김광석길 2곳 → 6곳).
자기 자신이 섞여 오므로 보일 수(6)보다 하나 더 받는다.

백엔드 trusted 조건(fix/place-hours-and-nearby)이 먼저 배포되어야 한다 — 모르는 조건은 400 이다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 00:00:14 +09:00
ttipo 4bd2a9b4ad feat(backend): 장소 목록에 관광공사·확인 장소만 받는 trusted 조건 추가
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 11m54s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m0s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m5s
CI / Frontend (lint · type-check · test) (push) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (push) Has been cancelled
CI / Backend (lint · test · e2e · build) (push) Has been cancelled
장소 상세 '함께 가기 좋은 곳'은 확인 안 된 상가정보 매장을 빼야 한다(2026-11-02 합의).
앱이 가까운 30곳을 받아 거르면 도심처럼 상가가 빽빽한 곳은 받은 곳이 모두 상가라 칸이 비었다.
관광공사 장소 상세 860곳 중 30곳은 칸이 사라지고 186곳은 덜 보였다(봉산서원은 1.5km 안에
관광공사 장소가 53곳인데 0곳).

trusted=true 면 관광공사 장소와 운영자가 확인한 장소만 주고 '추천 안 함' 판정도 뺀다.
선택 조건이라 기존 호출은 그대로다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 23:58:27 +09:00
ttipo 785afcc53f fix(backend): 행사 목록에서 끝을 생략한 없는 시작일이 500 이 나던 것 수정
from=2030-13-01 처럼 없는 시작일에 to 를 생략하면 끝 날짜를 계산하다 RangeError 가 나서
VAL_001(400) 대신 SYS_001(500)이 나갔다. from=9999-12-31 은 DB 가 읽지 못하는 끝 날짜를 만들었다.
날짜 계산을 shared/utils/iso-date.ts 순수 함수로 옮기고, 없는 날짜와 네 자리 연도를 넘는 결과는
null 로 알려 VAL_001 로 응답한다. 앱은 항상 두 날짜를 보내므로 사용자에게는 보이지 않았다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 23:58:27 +09:00
ttipo ff56d78022 fix(backend): 줄바꿈 없이 붙은 영업시간 원문을 구간마다 나눠 읽음
관광공사 원문 107곳이 "- 11:00~21:00- 준비시간 16:00~17:00- 마지막 주문 20:20" 처럼
줄바꿈 없이 붙어 온다. 맨 앞 글머리표만 지우던 파서는 이를 한 구간으로 보고 영업시간까지
준비시간·마지막 주문으로 읽었다. 그래서 39곳이 영업 중인 낮에 '영업 종료'로 보였고
41곳은 요일 시간이 통째로 비었다(2026-11-04 회귀 점검).

- 시각·닫는 괄호 뒤의 '- '(다음이 숫자가 아닌 말)와 대괄호 머리말 앞에서 구간을 나눈다
- 시설 머리말("[칠성시장] … [칠성야시장] …")마다 시간표를 따로 만들고 요일별로 합친다.
  나누기만 하면 뒤 시설의 요일 시간이 앞 시설 시간을 지워 일부 시간대가 빠졌다
- '휴게시간'은 쉬는 시간, '점심시간'은 2시간 이하일 때만 쉬는 시간으로 읽는다(식당의 점심 영업과 구분)
- 요일 사이의 '/' 는 나열로 읽고, 0분 구간("13:00~13:00")은 24시간으로 읽지 않고 버린다

개발 DB 는 reparse-hours 로 다시 해석했다(107곳 바뀜, 공공데이터 API 재호출 없음).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 23:58:27 +09:00
ttipo 377181eade fix(flutter): 홈 축제·행사 반경을 120km 에서 50km 로 줄임
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 11m11s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 10m27s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 10m44s
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 20m26s
CI / Backend (lint · test · e2e · build) (push) Successful in 11m56s
CI (Flutter) / Flutter (analyze · test) (push) Successful in 20m16s
CI / Frontend (lint · type-check · test) (push) Successful in 10m49s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 10m29s
120km 는 관광공사 행사뿐이던 2026-11-03 에 대구 행사가 너무 적어 경북까지 넓힌 값이다.
KOPIS·문화포털이 들어온 뒤로는 대구 안에서도 충분히 차고(도심 기준 이번 주말 50km 32건 ·
120km 42건), 120km 면 영덕·영주처럼 차로 2시간 거리까지 나왔다.
50km 는 군위를 포함한 대구 전역과 경산·칠곡까지다(2026-11-04 결정).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 17:27:58 +09:00
ttipo c21fbbd973 fix(flutter): 화면 아래가 내비게이션 바에 가려지고 상세 위가 상태 표시줄과 겹치는 것 수정
실기기(Android 16)에서 확인했다. Android 15 부터 앱이 화면 끝까지 그려지는데,
목록에 여백을 직접 준 화면은 시스템 여백이 빠져 마지막 출처 줄이 내비게이션 바에 가렸다
(장소 상세 · 행사 상세 · 행사 목록).

장소 상세는 사진 위에서 상태 표시줄 글자가 검은색이라 잘 안 보였고, 내리면 본문 제목이
상태 표시줄과 겹쳤다. 사진 위에서는 흰 글자와 위쪽 그늘을 두고, 사진을 지나면 흰 제목 줄
(뒤로 · 장소 이름)을 깐다. 상단 바가 없는 화면의 기본값(검은 글자)은 앱 뿌리에서 정한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 17:27:58 +09:00
ttipo 4bd142a9b7 feat(flutter): 장소 검색·상세 화면과 홈 검색창·카테고리·반려동물 장소 칸
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 21m21s
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m16s
CI / Frontend (lint · type-check · test) (pull_request) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Has been cancelled
디자인 캔버스 4(검색)·6·7(장소 상세) 중 지금 장소 API 로 되는 부분을 붙였다.

- 검색은 반경 20km(백엔드 최대) 거리순. 대구 도심에서 대구 전역이 들어온다.
- 영업시간을 모르는 곳은 "영업시간 미확인 · 방문 전 확인"으로 보인다.
- 한눈에 보기는 공공데이터 원문으로 확실한 것만 올린다(주차 '인근 공영주차장' 같은 애매한 값은 빼기).
- 함께 가기 좋은 곳에는 확인 안 된 상가정보 매장을 넣지 않는다(2026-11-02 합의).
- 1330 관광통역안내는 영어 화면에만(2026-10-29 합의).

검색의 '축제' 탭과 실내·무료·주차·이번 주말 조건은 데이터가 없어 넣지 않았다
(행사 API 검색어 조건 · 운영자 확인 장소 · 날씨).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 16:44:56 +09:00
ttipo 8f711c1706 refactor(flutter): 공공데이터 사진 위젯과 출처 모델을 공용으로 분리
장소 화면도 공공누리 사진과 출처 표기를 써야 해서, 행사 쪽에 있던 것을
shared 로 옮겼다. Type3 사진을 자르지 않는 규칙이 한 위젯(PublicImage)에만 있게 한다.
event_models 는 출처 모델을 다시 내보내 기존 import 는 그대로 동작한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 16:44:55 +09:00
ttipo b6abc3d118 chore(ci): 러너 compose 프로젝트 이름을 러너 이름으로 고정
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m21s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m58s
CI (Flutter) / Flutter (analyze · test) (pull_request) Successful in 22m22s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m22s
CI / Backend (lint · test · e2e · build) (push) Has been cancelled
CI / Frontend (lint · type-check · test) (push) Has been cancelled
CI / 에러 코드 SSOT 동기화 검사 (push) Has been cancelled
CI (Flutter) / Flutter (analyze · test) (push) Has been cancelled
프로젝트 이름을 지정하지 않으면 폴더 이름(ci)이 되어, 같은 PC 에서 다른 저장소의
ci/ 러너와 이름이 겹쳐 그 러너를 덮어쓸 수 있다(2026-11-04 arasystem 러너와 같은 PC 에서 확인).
compose 파일에 name: ${RUNNER_NAME} 을 두어 -p 없이도 겹치지 않게 하고, README 에 이름을 다르게 지으라고 적었다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 14:53:50 +09:00
ttipo 19f3574d97 chore(flutter): 앱 패키지 ID 를 net.wandergo.app 으로 정하고 Pretendard 글꼴 번들
패키지 ID 는 스토어 등록·네이버 지도 Client ID 등록에 쓰이고 출시 후 바꿀 수 없어
템플릿 값(com.example.tma_app)을 보유 도메인(wandergo.net) 기준으로 정했다(2026-11-04 사용자 결정).
Android applicationId·namespace·MainActivity 경로, iOS 번들 ID 를 바꾸고
출시 대상이 아닌 macOS·Linux·웹은 식별자·이름만 맞췄다.

디자인 캔버스의 Pretendard 는 woff2 라 Flutter 가 읽지 못해, 공식 저장소
(github.com/orioncactus/pretendard v1.3.9)의 정적 OTF 중 디자인이 쓰는 400·500·600·700 만 넣었다.
SIL OFL 1.1 원문을 함께 두고 라이선스 화면에 등록했다(고지 조건).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 14:53:50 +09:00
ttipo 0f306e71ba feat(flutter): 앱 뼈대와 홈 이번 주말 축제·행사 화면
데이터 기반(장소·행사 조회 API)이 생겨 앱 화면을 붙이기 시작한다.
디자인 캔버스의 1~7번(시작·둘러보기) 중 지금 API 로 바로 되는 것부터 만들었다.

- 앱 뼈대: 디자인 캔버스의 색·글자 크기·선 아이콘을 옮긴 테마, go_router 하단 탭
  (홈·지도·내 코스·내 정보 — 지도·내 코스·내 정보는 자리만), 한/영 문구(arb, 4개 언어 전제)
- 첫 실행: 현재 위치를 쓰거나 대구 동네(도심·수성못·앞산 카페거리)를 고른다.
  위치를 못 쓰면 대구 도심을 기준으로 시작하고 알린다. 좌표는 저장하지 않는다
- 홈 '이번 주말 축제·행사': 기준 위치 반경 120km 거리순, 비면 다가오는 30일 (2026-11-03 합의)
- 행사 전체 목록(커서 페이지)·상세(시간·요금·예매·전화·소개·출처)
- 한국어 문단은 단어 단위 줄바꿈(keepAll) — Flutter 기본은 글자 단위로 끊는다
- 공공누리 Type3 사진은 자르지 않고, 꼬리말에 관광공사·KOPIS·문화포털 출처를 적는다
- 한/영 생성물(lib/l10n/generated)은 flutter pub get 이 만들므로 git 에서 뺀다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 14:51:02 +09:00
ttipo 170be20b6d test(backend): e2e 스위트를 순서대로 실행
CI / Backend (lint · test · e2e · build) (pull_request) Successful in 12m48s
CI / Frontend (lint · type-check · test) (pull_request) Successful in 11m39s
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Successful in 11m33s
CI / Backend (lint · test · e2e · build) (push) Successful in 12m27s
CI / Frontend (lint · type-check · test) (push) Successful in 11m0s
CI / 에러 코드 SSOT 동기화 검사 (push) Successful in 11m46s
빈 DB 에서 여러 e2e 스위트가 동시에 마이그레이션하면 같은 테이블을 만들다
pg_class_relname_nsp_index 중복으로 무작위 실패했다(스위트 5개에서 재현, CI 도 빈 DB 라 같은 위험).
스위트들은 한 DB 를 함께 쓰므로 maxWorkers 1 로 순서대로 돌린다. 빈 DB 두 번 연속 통과(약 30초).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 23:27:59 +09:00
ttipo e383c2e242 feat(backend): 같은 출처에 두 번 등록된 전시를 하나로 합침
한국문화정보원에 같은 전시가 제목만 다르게 두 번 등록되어 목록에 2건으로 나왔다
("문준호 전 - 남겨진 것들을 위한 풍경" / "문준호 《남겨진 것들을 위한 풍경》", 같은 갤러리·같은 기간).

같은 장소 · 같은 시작·종료일 · 제목 비교 키가 연속 6글자 이상 겹치면 같은 전시로 보고
먼저 등록된 것만 남긴다. 장소·기간만으로 합치지 않는 이유는 여러 전시실에서 같은 날
여러 전시를 여는 곳이 있어서다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 23:27:59 +09:00
ttipo 7e59ac0205 docs: 한국문화정보원 전시 동기화와 KOPIS 제목 정리 기록
place-db.md §12.1 에 지역 꼬리표 제거 규칙, §12.2 에 전시 동기화 순서·중복 판단·이미지 보류를 적었다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 23:02:16 +09:00
ttipo 175e2d454b feat(backend): 한국문화정보원 전시 동기화 추가
전시는 관광공사·KOPIS 어디에도 없다. 한국문화정보원 한눈에보는문화정보(대구 90일 전시 13건)를
place:sync -- kcisa 로 매일 받는다.

- 분야가 '전시'인 것만 받는다(공연은 KOPIS 와 겹친다)
- 관광공사·KOPIS 에 이름 비교 키가 같고 기간이 겹치는 행사가 있으면 넣지 않는다(event-name.ts)
- 상세는 새 전시와 7일 지난 전시만(원본에 수정일이 없다), 좌표는 목록의 gpsY(위도)·gpsX(경도)
- 이미지는 이용 조건(공공누리 1유형 여부)을 확인하기 전이라 저장하지 않는다
- htmlToText 가 따옴표·가운뎃점·번호 엔티티도 푼다 — 제목이 &amp;lsquo; 처럼 이중 인코딩되어 온다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 23:02:15 +09:00
ttipo 94c8693dad test(backend): 에러 코드 계약 테스트의 타입 오류 수정
ERROR_CODES 는 코드마다 리터럴 타입이 달라 선택 속성 clientOnly 를 바로 읽으면 tsc 가 실패했다
(jest 는 타입 검사를 하지 않아 통과하고 있었다). 공통 정의 타입으로 넓혀 읽는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:31:53 +09:00
ttipo 4b6eecd679 docs(rules): 유예 취약점과 잠금 파일 npm 버전 주의 기록
- security.md: 남은 36건(glob·minimatch 보통, deepmerge·jest 낮음)의 도달 가능성·유예 이유·다시 볼 조건,
  multer ^2.5.0 · swagger 아래 js-yaml override 근거
- nestjs 스킬: 컨테이너 npm 11.20 이 지운 선택 peer 항목 때문에 CI(npm 10)의 npm ci 가 깨질 수 있다 —
  npx npm@10 ci --dry-run 으로 확인하는 절차

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:31:53 +09:00
ttipo 3e2adea95c chore(backend): 의존성 취약점 정리(치명 4·높음 3 → 0)
npm audit 47건(치명 4 · 높음 3) 중 범위 안에서 올릴 수 있는 것을 모두 올렸다.

- 컨테이너 안에서 npm audit fix: proxy-addr·piscina·handlebars·decompress·body-parser·qs 등
- Nest 11 최신판(11.2.8)으로 업데이트: 낡은 path-to-regexp 8.2.0(높음) 고정 해소
- overrides: multer ^2.5.0(2.4.0 에 DoS 취약점, platform-express 12.3.2 가 2.5.0 선언),
  @nestjs/swagger 아래 js-yaml ^5.4.3(5.3.0 고정, swagger 12.1.0 이 5.5.0 선언)

컨테이너 npm 11.20 이 선택 peer 의존성 항목(chokidar 4.0.3)을 잠금 파일에서 지워
CI 와 같은 npm 10 의 npm ci 가 실패해서, 그 항목만 이전 잠금 파일에서 되살렸다.
npm 10 · 11.6 · 11.20 모두 npm ci 통과, lint · 단위 185 · e2e 39 · 빌드 · 서버 기동(/api-docs-yaml 포함) 확인.
남은 36건(보통 33 · 낮음 3)은 메이저 업그레이드로만 풀려 security.md 에 유예로 기록한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:31:53 +09:00
ttipo 307204ef09 fix(backend): KOPIS 공연 제목의 지역 꼬리표 제거
순회 공연은 제목 끝에 "[대구]"·"[대구 북구]"·"[안동] (11월)" 같은 지역 표시가 붙어 온다
(대구·경북 244건 중 203건). 앱 목록에서는 군더더기라 저장할 때 뗀다.
꼬리표 안이 지역 이름과 괄호 메모로만 되어 있을 때만 떼고, "(앵콜)" 같은 메모는 남긴다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:13:03 +09:00
ttipo e7c2506ce7 chore: 공연·전시 API 진단 스크립트 추가
KOPIS(https·조회 기간·건수·시설 좌표·afterdate)와 한눈에보는문화정보(건수·분야·좌표 채움)를
구현 전에 실제로 불러 확인한다. 키는 backend env 에서 읽고 출력하지 않는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:07:44 +09:00
ttipo ec4a2a3db8 docs: 공연·전시 출처 조사와 KOPIS 동기화 설계 정리
- 조사 문서: KOPIS·한국문화정보원·대구문화예술진흥원 이용 조건·필드·한도, 사용자 확인(KOPIS 저장·포스터 재사용 가능), 2026-11-03 진단 결과
- place-db.md v1.7: 여러 출처 스키마(§2.4), KOPIS 동기화 순서·좌표 검사·호출량·알려진 한계(§12.1), 다음 출처(§12.2)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:07:44 +09:00
ttipo 45db80d683 feat(backend): KOPIS 공연 동기화 추가
대구 공연은 관광공사에 거의 없고(90일 1건) KOPIS 에는 153건이 있다.
place:sync -- kopis 로 대구·경북 공연을 매일 받는다.

- 목록 → 새·바뀐(afterdate)·7일 지난 공연만 상세 → 새 공연장만 시설 상세 → 시설 좌표를 공연에 복사
- 시설 좌표가 주소의 시·도 영역 밖이면 비운다(대구 중구 주소에 경주 좌표인 시설이 있었다)
- 포스터 http 주소를 https://kopis.or.kr 로 바꿔 저장, 0.6초 간격 호출(초당 10회 차단)
- 공공데이터 클라이언트에 키 파라미터 이름·호출 간격·경로를 나눠 받게 함
- XML 응답 해석에 fast-xml-parser 추가. 컨테이너 npm 11.20 이 만든 잠금 파일은
  선택 peer·@emnapi 항목을 지워 CI(npm 10)·호스트의 npm ci 가 실패해서, 새 패키지 항목만 기존 잠금에 더했다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:02:31 +09:00
ttipo d3d66444bc feat(backend): 행사 출처 구분·전시 종류·공연장 테이블 추가
KOPIS 공연·한국문화정보원 전시를 관광공사 행사와 같은 테이블에 받으려면
관광공사 contentid 단독 유니크로는 출처가 섞인다. (source, source_id) 로 바꾸고,
KOPIS 공연은 좌표가 공연장 상세에만 있어 event_venue 에 따로 둔다.

- 전시는 몇 달씩 하는 것이 보통이라 상시 프로그램 기간 상한을 종류별로 나눔(전시 183일)
- 관광공사 동기화는 관광공사 행사만 숨기도록 범위를 좁힘
- 조회 API 에 장르·예매 링크·출처별 표기 추가, 없는 날짜(2030-13-01)가 500 이 되던 것을 VAL_001 로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:01:23 +09:00
ttipo 009a287533 feat(backend): 축제·행사 범위를 대구 근교(경북)까지 넓힘
관광공사에 등록된 앞으로 90일 행사가 대구 1건·경북 7건뿐이라(조회 조건 문제 아님)
홈 '이번 주말 축제·행사'가 대부분 비게 된다. 근교 행사를 거리와 함께 보여 준다.

- place:sync -- event 가 기본으로 대구(27)·경북(47)을 받는다(--regions= 로 변경,
  시·도마다 실행 기록을 따로 남긴다)
- GET /api/events 반경 상한 50km → 150km(포항 약 85km·청송 약 100km). 기본 5km 는 그대로
- 설계 문서에 화면 규칙: 홈은 동네 좌표 120km 거리순(대구 먼저), 이번 주말이 비면
  같은 반경 30일로 '다가오는 축제·행사'. 장소 상세 '근처'는 5km, 없으면 칸 숨김

2026-11-03 실측: 이번 주말 대구 도심 120km 안 5건(수성국제비엔날레 5km 가 맨 앞).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:44:28 +09:00
ttipo 16757b31f2 chore: 축제 지역 조회 진단 스크립트 추가
대구 축제·행사가 90일 동안 1건만 잡힌 이유가 데이터 부족인지 조회 조건 때문인지
가르려고 만들었다(지역+종료일 / 지역만 / 전국 비교, searchFestival2 5~6회).
2026-11-03 결과: 조건 문제는 없고(코드 빈 행사 0건) 등록된 대구 행사가 실제로 적었다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:30:09 +09:00
ttipo 4371f24c46 chore(docker): 개발 백엔드 메모리 한도를 2GB 로 올림
dev 는 파일 감시(폴링)와 타입 검사(nest start --watch)가 함께 돌아 운영보다 무겁다.
base 의 1GB 로는 여러 파일을 연달아 저장할 때 두 번(2026-11-02·03) 메모리 부족으로
종료됐다(OOMKilled). 운영 한도는 그대로 두고 dev 오버라이드에서만 올린다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:30:08 +09:00
ttipo 295d74f4d3 feat(backend): 축제·공연·행사 동기화와 조회 API 추가
홈 '이번 주말 축제·행사'와 장소 상세 '근처 축제·행사'에 쓸 데이터를 채운다.

- 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>
2026-11-03 19:30:08 +09:00
ttipo 55f10c5c7a fix(backend): 숨김·폐업 처리 안전장치를 항목 수에 맞게 조정
"이번 목록이 기존의 80% 미만이면 원본 장애로 보고 숨기지 않는다"는 규칙은
항목이 적은 곳(축제 몇 건, 동네 빙수집 5곳)에서 정상적인 한 건 취소도 막았다.
사라진 수를 직접 세어, 5건을 넘고 기존의 20% 도 넘을 때 또는 기존이 전부
사라졌을 때(빈 응답)만 원본 장애로 본다. 관광공사·상가정보 동기화가 함께 쓴다.

상가정보는 업종이 바뀐 업소(카페 → 빵집)를 사라진 것으로 세지 않도록
묶음별 개수 대신 이번에 본 업소 id 전체와 비교한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:30:07 +09:00
ttipo 3d2cd99ef0 fix(backend): 영업시간 파서가 붙은 구간·요일 머리말을 잘못 읽던 문제 수정
대구 관광공사 원문을 실제로 적재해 보니 형식이 제각각이라 시간표를 잘못 읽는 곳이 있었다.
예: 더현대 대구 "월요일~목요일 10:30~20:00금요일~일요일 10:30~20:30" 을
월~목에 두 시간대, 금~일은 비어 있음으로 읽어 월요일 20:15 에 "영업 중"으로 나갔다.

- 줄바꿈을 구간 구분으로 본다(동기화가 <br> 을 줄바꿈으로 바꿔 저장하는데 공백으로 합쳐지고 있었다)
- 시각 바로 뒤에 요일·평일·주말·'[' 가 붙으면 구간을 나눈다(하이픈 시간 범위는 그대로)
- 괄호·대괄호 안의 '/' 로 구간을 자르지 않고, 괄호 안 브레이크타임·라스트오더를 각각 읽는다
- "[토요일]" 같은 대괄호 요일 머리말을 다음 줄들의 시간에 적용하고, "[1월]" 의 '월'은
  월요일로 읽지 않는다(달마다 다르면 계절별처럼 시각 판단을 하지 않는다)
- 주중·평일 줄의 브레이크타임은 평일 전용으로 본다
- htmlToText 가 잘못 쓴 </br> 도 줄바꿈으로 바꾼다

저장된 원문을 API 재호출 없이 다시 해석하는 `place:sync -- reparse-hours` 를 추가했다
(jsonb 키 순서와 무관하게 비교). 2026-11-03 대구 1,174곳 중 124곳의 시간표를 바로잡았다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:59:20 +09:00
ttipo df48ed78eb feat(backend): 장소 조회 API와 같은 가게 중복 병합 추가
검색·지도·상세 화면이 장소 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>
2026-11-03 18:57:58 +09:00
ttipo 71aaf0bcae feat(backend): 상가정보 데이트 업종 적재 명령 추가
`npm run place:sync -- store [--signgu=...]` 로 소상공인 상가정보의 데이트 업종
6개(카페·빵/도넛·아이스크림/빙수·샌드위치/샐러드·요리 주점·생맥주)를 장소 DB 에
적재한다. 기본 범위는 1차 큐레이션 동네가 속한 대구 중구·남구·수성구다.

- 분기마다 다시 실행하면, 끝까지 받은 (시군구, 업종) 묶음에서 사라진 업소를
  gone(폐업 추정)으로 숨긴다. 지우지 않고, 결과가 기존의 80% 미만이면 건너뛴다
- 기준년월(stdrYm)을 source_snapshot 에 남긴다
- 공공데이터포털 공통 규칙(키 가림·간격·재시도·한도)을 PublicDataClient 로 묶어
  관광공사·상가정보 클라이언트가 함께 쓴다(TourApiFactory → PublicDataApiFactory)

2026-11-02 대구 실측: 기준 2026-09, 3,776곳(18회 호출). 세 동네 반경 안 업소 수는
후보표(반경 API)와 거의 같다(도심 1,295/1,316 · 수성못 425/425 · 앞산 262/263).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 17:00:13 +09:00
ttipo 9775d6de45 feat(backend): 관광공사 장소·반려동물 동기화 명령 추가
`npm run place:sync -- tour-kor|tour-pet|status` 로 관광공사 국문 장소와
반려동물 동반 정보를 장소 DB 에 적재한다. API 서버가 아니라 CLI(운영은 cron)로 돈다.

- tour-kor: 시·도 지역 목록 전체 → place upsert → 상세(개요·영업시간·요금·주차).
  개발 계정 한도(오퍼레이션별 하루 1,000건)에 닿으면 멈추고 detail_synced_at 으로
  다음 실행이 이어 받는다. 서버의 한도 초과 응답(코드 22)도 정상 멈춤으로 본다.
  수정일이 바뀐 장소만 상세를 다시 받고, 목록에서 사라진 장소는 숨긴다
- tour-pet: detailPetTour2 전체(약 10회)를 받아 전구역/일부구역으로 요약
- 분류 대응을 「신분류체계 연계 정의서」 소분류 240개로 확정하고 'other' 분류 추가
- 키는 어떤 오류 메시지에도 남기지 않는다(원문·URL 인코딩 모두 가림)

CHECK 제약 변경은 migration:generate 가 감지하지 못해 마이그레이션에 직접 적었다.
2026-11-02 대구 실측: 목록 1,193건 → 장소 1,174곳, 상세 535곳(영업시간 해석 92%),
반려동물 정보 288곳(그중 쇼핑 매장 275곳).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 16:46:43 +09:00
ttipo cd089f76fb chore(docker): 백엔드·프론트엔드 .dockerignore 추가
없으면 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>
2026-11-02 16:46:41 +09:00
ttipo 13bf3c6e40 chore: 네이버 지도 Flutter 1일 시험 앱 추가
flutter_naver_map 은 권장안이지만 유지보수 1인·최근 릴리스 공백이 있어
채택 전에 하루 시험한다. 코스 지도(마커·경로선), 핀 1,000개 묶음,
지명 언어, 한 화면에 지도 두 개, 지도 화면 열고 닫기 20번의 5개 화면으로
우리 요구와 안정성을 확인한다. NCP Client ID 는 코드에 두지 않고
--dart-define=NAVER_MAP_CLIENT_ID 로만 받는다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:53:52 +09:00
ttipo 5535ba19ed docs: AI 코스 추천 평가셋 초안 추가
AI 코스 생성 품질을 프롬프트·모델을 바꿀 때마다 같은 기준으로 재기 위한
62개 사례(데이트·축제·반려동물·카카오 데이터 경계·날씨·예외 입력)와
사례별 확인 항목·기대 동작이다. 대구 사례는 아직 넣지 않았다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:53:25 +09:00
ttipo 166f5a04b9 docs: 공공데이터 API 원본 활용 매뉴얼 보관
관광공사(국문·영문·반려동물·신청 방법·분류코드), 기상청 단기예보,
소상공인 상가정보의 공공데이터포털 배포 매뉴얼 원본이다.
docs/research/data-openapi-review/ 의 검토 노트가 이 파일들을 근거로 인용한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:53:25 +09:00
ttipo 0b385a896e docs: 착수 전 조사와 공공데이터 점검 결과 정리
개발 전에 확정해야 할 전제(데이터 저장 가능 범위·지도 SDK·계정 리드타임)와
공공데이터 실측 결과를 남긴다.

- pre-dev-check: 카카오 장소 데이터 저장·LLM 전송 금지 조건, 지도 SDK 비교
  (네이버 권장), 스토어·위치기반서비스 신고 등 계정·승인 체크리스트
- data-openapi-review: 관광공사 국문·영문·반려동물, 상가정보, 단기예보 매뉴얼 검토
- data-check: 서울·부산·대구 점검 요약과 원자료(JSON, 키 미포함)

10-29 점검의 관광공사·반려동물 개수는 위치 검색으로 센 과소 집계였다.
2026-11-02 재측정 결과를 각 요약 맨 위에 정정 메모로 달았다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:53:24 +09:00
ttipo 82087b7ac7 chore: 공공데이터 점검·큐레이션 후보 도구 추가
대구 1차 출시 지역의 공공데이터를 점검하고 큐레이션 작업표를 만드는
스크립트다. 키는 backend/.env.development 에서 읽고 출력·오류 문구에서 가린다.

- public_data_check(2).py · run_region.py: 관광공사·반려동물·축제·상가정보·
  단기예보 점검 (결과는 docs/research/data-check/)
- curation_candidates.py: 동네별 큐레이션 후보표(CSV). 관광공사는 위치 검색이
  반경 안 장소의 15–38%만 돌려줘서 시·도 지역 목록을 받아 반경을 직접 거른다
- curation_shortlist.py: 후보표에 우선순위(1~4·제외)를 매기고 시범표를 만든다
  (키 불필요)

결과 CSV 는 data/ 아래에 생기며 .gitignore 대상이다. 파이썬 캐시도 무시한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:53:09 +09:00
ttipo 2d0d760d98 feat(backend): 장소 DB 스키마와 마이그레이션 추가
공공데이터 장소(place)와 운영자 큐레이션(place_curation)을 테이블로 나눠
동기화가 사람이 확인한 값을 덮어쓰지 않게 한다. 앱이 보는 값(큐레이션 >
공공 > 미확인)과 노출 규칙은 place_listing 뷰 한 곳에서만 정한다.

- 노출 규칙(2026-11-02 합의): 노출 중인 장소는 모두 검색, 홈 추천은
  추천(O)+확인일, AI 후보는 1순위 큐레이션 추천·2순위 관광공사 장소.
  확인 안 된 상가정보 매장은 AI 후보가 아니다
- 축제·공연·행사(festival_event), 언어별 텍스트(place_i18n),
  동기화 기록(place_sync_run) 포함
- 코드값은 place.constants.ts 하나로 CHECK 제약·뷰가 공유
- 전역 SnakeNamingStrategy(DB snake_case ↔ TS camelCase), uuid 는 pgcrypto

임시 Postgres 15 에서 생성 → 적용 → 재생성 무차이 → revert 를 확인했고,
뷰 규칙은 8가지 경우로 검증했다. 설계: docs/design/place-db.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:51:03 +09:00
ttipo 52de9917e4 feat(backend): 공공데이터 영업시간 문장 파서 추가
관광공사 영업시간·쉬는날은 "11:00~21:00 (준비 시간 15:30~17:00)",
"화~일 10:00~18:00 (월요일 휴관)", "점포별 상이"처럼 자유 문장이라
코스 영업시간 경고와 AI 시간 검증에 바로 쓸 수 없다.
요일별 시간표·준비시간·마지막 주문·정기 휴무·명절 휴무로 해석하고,
정할 수 없는 경우(점포별 상이·계절별·값 없음)는 지어내지 않고 상태로 남긴다.
테스트는 2026-10-29 공공데이터 점검에서 받은 실제 문장으로 작성했다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:46:55 +09:00
ttipo da4db6123b chore(backend): 공공데이터·카카오·Claude API 키 환경변수 예시 추가
장소 데이터 적재(공공데이터포털)·장소 검색(카카오)·AI 코스 생성(Claude)에
필요한 키 자리를 placeholder 로 추가한다. 카카오 응답의 저장·LLM 전송 금지
조건을 주석으로 남겨 키를 쓰는 사람이 바로 알 수 있게 한다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:45:28 +09:00
ttipo 696e34f403 Initial commit 2026-10-28 15:30:05 +09:00