[fix] site/scripts: 끼니 간격·체류 대비 이동을 규칙으로 — 섬 코스가 103분 만에 두 번째 상

사장님 지적("1시간 30분 걸려서 갔는데 짧게 머문다")을 전수로 다시 셌다.
대상은 선유도가 아니었다(150분). 섬에서 돌아오는 길의 **끼니 간격**이다 —
늦은 점심 15:47 종료, 저녁 17:30 시작으로 103분이다. 늦은 점심 창(≤15:00)과
저녁 창(≥17:30)이 둘 다 합법이라 규칙 14종을 그냥 통과했다. 창 밖에 규칙이 따로 필요했다.

- build_itinerary.py: MEAL_GAP=180. `_window_of()` 가 앞 끼니 종료 + 3시간 뒤로 다음 끼니
  창을 민다. 섬 2박3일 둘째 날이 쉼 168분으로 늘고 저녁이 18:47 로 밀렸다
- build_itinerary.py audit(): 규칙 15(끼니 간격) · 16(볼거리는 편도 이동보다 오래 머문다)
  추가. 16은 **끼니를 뺀다** — 밥집은 목적지가 아니라 돌아오는 길에 들르는 자리다
- audit_schedule.py 신설: 구워진 payload 를 표로 펴고, 만들 때 규칙이 **안 보는** 논리
  12가지(L0~L11)를 센다 → SCHEDULE.md
- README: 규칙 14종 → 16종. 장소 대장 프롬프트에 "멀리 있는 곳 근처 식당도 넣어라" 추가 —
  규칙만 고치면 다음 지역에서 또 난다
- README: 일정 프롬프트 위치 정정. shared/section-prompts.ts 가 아니라
  frontend/.../canvas/dataSpec.ts:556 이고, video·event·itinerary 셋은 **빌더에만** 있어
  서버 생성 잡이 만들 줄 모른다(daily 와 같은 사고). 그 프롬프트가 모델에게 시각 계산을
  시키고 있는 것도 적었다 — 시연본 첫 판이 망가진 직접 원인이다
- README: 목업을 지울 때 1부를 docs/ 로 옮기라는 안내

검증: 규칙 16종 위반 0건 · audit_schedule 21/21 검수완료 · audit-all.mjs 34/34

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mina Choi 2026-09-11 11:10:16 +09:00
parent b86a055278
commit 703f831273
5 changed files with 1047 additions and 18 deletions

View File

@ -2,7 +2,9 @@
> **이 문서 하나만 읽으면 된다.** 예전에는 README · SECTIONS · PROMPTS · REVIEW 로 흩어져
> 있었고 무엇을 먼저 볼지 알 수 없었다. 전부 여기로 합쳤다(2026-09-11).
> 같은 폴더의 `TEXT.md` 만 따로다 — 그건 지침이 아니라 화면에 나가는 **텍스트 전문 덤프**다.
> 같은 폴더에 **생성물 두 개**가 더 있는데 지침이 아니라 **데이터**다 —
> `TEXT.md`(화면에 나가는 텍스트 전문, `python3 dump_text.py`)와
> `SCHEDULE.md`(일정 21개 전수 검수표, `python3 audit_schedule.py`).
대상 `https://web4ai.o2osolution.ai/s/stay` (스테이,머뭄 · 전북 군산)
@ -32,7 +34,8 @@
|---|---|
| `solution/shared/src/types/site-payload.ts` | payload 필드 정의. `Narrative`(`:316`) · `MediaItem` · `Unit` |
| `solution/shared/src/lib/section-data.ts` | 섹션 봉투(`{kind,version,title,items[]}`) 타입 + `planDay()`. **21시 넘는 칸을 버리는 규칙이 여기 있다**(`:535`) |
| `solution/shared/src/lib/section-prompts.ts` | **프롬프트 단일 출처.** 고친 뒤 `npm run export:prompts` |
| `solution/shared/src/lib/section-prompts.ts` | 프롬프트 — **서버 생성 잡이 쓰는 6종**(songs · daily · people · chronicle · postcard · quiz). 고친 뒤 `npm run export:prompts` |
| `solution/frontend/src/features/builder/canvas/dataSpec.ts` | 프롬프트 — **빌더 [콘텐츠] 탭에서 붙여넣는 9종**. 위 6종은 shared 를 import 하고, **video · event · itinerary 셋은 여기에만 있다**(`itinerary` 는 `:556`) |
### ② 생성 — 값을 만드는 곳
@ -56,7 +59,7 @@
| 파일 | 옮길 자리 |
|---|---|
| 이 문서 **1.4 프롬프트 전문** | `shared/src/lib/section-prompts.ts` |
| `build_itinerary.py` (규칙 14종) | `backend/services/itinerary.py` |
| `build_itinerary.py` (규칙 16종) | `backend/services/itinerary.py` |
| `build_story.py` (위키 사진 수집) | `backend/services/external/wikimedia.py` |
| `inject.js` (렌더러에 **없는** 기능 3개) | `site/src/sections/` |
@ -79,7 +82,7 @@
| `map` | 오시는 길 | `place` + `routes[]` | 수집 | |
| `festival` | 계절별 축제 | `local.festivals` | TourAPI 수집 | |
| `local` | 지역 정보 | `local.attractions/restaurants` | TourAPI 수집 | |
| `itinerary` | **추천 일정** | `data(kind=itinerary)` | `services/itinerary.py` | **T2** |
| `itinerary` | **추천 일정** | `data(kind=itinerary)` | `services/itinerary.py` + 빌더 프롬프트 `dataSpec.ts:556` | **T2** |
| `story` | 군산 이야기 | 아래 6탭 껍데기 | — | |
| `songs` | 가요 다방 | `data(kind=songs)` | LLM `section-prompts.ts:67` | **T3 T5** |
| `daily` | 오늘의 한 장 | `data(kind=daily)` | LLM `:91` | 섹션 자리가 없다 |
@ -131,10 +134,23 @@
### T2 — 추천 일정 ★ 가장 큰 일
**증상** 서버 생성기(`services/itinerary.py`)는 하루를 **관광지 2 + 맛집 2** 로 짠다.
**증상** 서버 생성기(`services/itinerary.py`)는 하루를 **관광지 2 + 맛집 2** 로 짠다.
체류시간·이동시간·입퇴실·끼니 시각 개념이 없다. 그래서 나온 하루가
"둘째 날 해산물축제 → 근대건축관" 으로 끝난다.
**증상 ② 프롬프트가 두 곳으로 갈려 있다.**
일정 프롬프트는 `shared/src/lib/section-prompts.ts` 에 **없고**
`frontend/src/features/builder/canvas/dataSpec.ts:556` 에만 있다.
그 파일은 **빌더에서 붙여넣는 9종**을 담는데, 그중 `songs` 등 6종은 shared 를 import 하고
**`video` · `event` · `itinerary` 셋은 자기 자리에 직접 적혀 있다.**
→ 서버 생성 잡(`story_service.py`)은 shared 만 읽으므로 **이 셋을 만들 줄 모른다.**
`daily` 가 빈칸이던 것과 **같은 종류의 사고**다. 옮기면서 shared 로 올린다.
**증상 ③ 지금 프롬프트가 모델에게 시각 계산을 시킨다.**
`dataSpec.ts` 의 일정 규칙에 이런 줄이 있다 — "밤 9시를 넘기는 칸은 화면에서 빠진다 —
**시각을 계산해 보고 넣는다**", 그리고 `minutes` · `moveMinutes` 를 모델이 적게 한다.
모델은 못 한다. 이게 시연본 첫 판이 망가진 직접 원인이다.
**★ 프롬프트 하나로 일정을 받지 않는다.** 모델은 시각 계산을 못 한다 —
이동시간을 지어내고, 점심을 09:40 에 넣고, 21시를 넘겨 **렌더러가 조용히 버리는** 칸을
만든다(`shared/src/lib/section-data.ts:535`). 시연본 첫 판이 정확히 그랬다.
@ -145,7 +161,7 @@
|---|---|---|---|
| **① 장소 대장** | LLM | 장소 30곳 × `{stayMinutes:{min,base,max}, todo, indoor, needsCar, bestTime, searchQuery}` | **1.4 ②** |
| **② 좌표** | 코드 | 카카오 로컬로 `searchQuery` → 위경도. **LLM 이 적은 좌표는 쓰지 않는다** | — |
| **③ 조립** | **코드** | 이동시간·도착시각·끼니 창 맞추기·규칙 14종 감사 | 없음 (`build_itinerary.py`) |
| **③ 조립** | **코드** | 이동시간·도착시각·끼니 창 맞추기·규칙 16종 감사 | 없음 (`build_itinerary.py`) |
| **④ 테마** | LLM | 테마 20개 × `{name, duration, audience, why, days[{kind, places[]}]}` | **1.4 ③** |
**코드가 하는 일(③)에서 반드시 옮겨야 하는 것** — 근거는 `build_itinerary.py` 줄번호
@ -157,7 +173,8 @@
| 시각 창 | 입실 15:00+ · 퇴실 11:00 · 점심 11:3013:30 · 늦은 점심 13:0015:00 · 저녁 17:3020:00 · 밤산책 18:3020:00 | `:156` `:166` |
| 창 맞추기 | 어긋나면 **앞 칸 체류를 범위(min~max) 안에서** 늘이고 줄인다. 이동시간을 고치지 않는다. 그래도 안 되면 시작 시각을 10분씩 옮기고, 그래도 안 되면 **그 조합을 만들지 않는다** | `plan_day()` |
| 테마별 완급 | 시작 시각·체류 배율이 테마마다 다르다(쉬러 오면 1.25배, 사진 찍으면 0.8배) → 끝나는 시각이 13:35~21:00 로 퍼진다 | `:470` |
| **감사 14종** | 하나라도 어기면 **payload 를 쓰지 않고 멈춘다** | `:526` · 목록은 **2.4** |
| 끼니 간격 | 앞 끼니가 끝나고 **3시간**이 지나야 다음 끼니 창이 열린다(`MEAL_GAP`). 창만 지키면 통과하던 자리다 | `_window_of()` |
| **감사 16종** | 하나라도 어기면 **payload 를 쓰지 않고 멈춘다** | `:526` · 목록은 **2.4** |
**감사는 생성기 안에 둔다.** 밖에 두면 뼈대를 고칠 때마다 "이번에 안 본 규칙"이 생긴다 —
실제로 그래서 33건이 통과했다(**3.2**).
@ -239,6 +256,15 @@
## 1.4 프롬프트 전문
**프롬프트는 지금 두 파일에 나뉘어 있다. 이게 문제다.**
| 파일 | 담는 것 | 누가 읽나 |
|---|---|---|
| `shared/src/lib/section-prompts.ts` | songs · daily · people · chronicle · postcard · quiz | 빌더 **+ 서버 생성 잡** |
| `frontend/.../canvas/dataSpec.ts` | 위 6종(shared 를 import) **+ video · event · itinerary** | 빌더만 |
**`video` · `event` · `itinerary` 는 서버가 만들 줄 모른다.** 옮기면서 shared 로 올린다.
**단일 출처는 `solution/shared/src/lib/section-prompts.ts` 다.**
사장님이 [콘텐츠] 탭에서 복사해 가는 프롬프트와, 서버 생성 잡(`services/story_service.py`)이
**같은 문장**을 써야 한다. 두 벌로 두면 "빌더에서 뽑은 것과 서버가 채운 것의 모양이 다르다"가
@ -329,7 +355,7 @@ backend/services/prompts/section_prompts.json ← 산출물. 손으로 고치
---
### ② 여행 일정 · 장소 대장 (T2 ① · 신규)
### ② 여행 일정 · 장소 대장 (T2 ① · `dataSpec.ts:556` 의 일정 프롬프트를 **대체**한다)
```
너는 지역 여행 코디네이터다. 아래 조건에 맞는 JSON 하나만 출력한다.
@ -368,11 +394,15 @@ backend/services/prompts/section_prompts.json ← 산출물. 손으로 고치
· needsCar 는 [업소] 에서 걸어서 못 가는 곳(1.5km 초과)이면 true 다.
· 좌표는 적지 않는다. 코드가 카카오 로컬에서 받는다 — 지어낸 좌표는 지도에 엉뚱한 핀을 찍는다.
· 영업시간·휴무일이 확인되면 source 에 그 페이지를 단다.
· **[업소]에서 40분 넘게 걸리는 곳을 넣었다면, 그 근처 식당도 하나 이상 넣는다.**
멀리 다녀온 뒤 시내까지 돌아와 밥을 먹으면 점심이 오후 3시가 된다 —
시연본에서 실제로 그랬다(섬에서 88분 달려와 15:47 에 늦은 점심).
· 끼니 장소는 **한 끼 40~70분**이다. 여기에 이동시간을 얹는 것은 코드가 한다.
```
---
### ③ 여행 일정 · 테마 짓기 (T2 ④ · 신규)
### ③ 여행 일정 · 테마 짓기 (T2 ④ · 신규 · ②와 짝)
```
[해야 할 일]
@ -522,7 +552,7 @@ backend/services/prompts/section_prompts.json ← 산출물. 손으로 고치
stay-payload.json 원본 payload (건드리지 않는다 · 되돌릴 때 기준)
orig/index.html 원본 HTML (건드리지 않는다)
├─ build_itinerary.py 여행 일정을 계산해 넣는다 (+ 규칙 14종 감사)
├─ build_itinerary.py 여행 일정을 계산해 넣는다 (+ 규칙 16종 감사)
├─ build_story.py 가요 다방 · 인물 열전을 넣는다
└─ patch_stay.py 캐치프레이즈 · 객실 사진 · 자작곡 · 주입 CSS/JS · 자산 경로 교정
@ -659,7 +689,7 @@ docker cp vendor/. \$C:/app/solution/site/out/s/stay/vendor/"
---
## 2.4 규칙 14종 — 어기면 빌드가 멈춘다
## 2.4 규칙 16종 — 어기면 빌드가 멈춘다
`build_itinerary.py``audit()`(`:526`)이 매 실행 검사한다.
하나라도 어기면 **payload 파일을 쓰지 않고** 위반 목록을 찍고 멈춘다.
@ -680,6 +710,8 @@ docker cp vendor/. \$C:/app/solution/site/out/s/stay/vendor/"
| 12 | "걸어서만/차 없이" 테마에 차 필요한 곳 금지 | |
| 13 | 1박 2일 = 2일, 2박 3일 = 3일 | |
| 14 | 아이 동반 테마에 술집 금지 | |
| **15** | **끼니 사이 3시간 이상** | 늦은 점심 15:47 종료 → 저녁 17:30. 창은 둘 다 합법인데 배가 안 꺼진다 |
| **16** | **볼거리는 편도 이동보다 오래 머문다**(끼니 제외) | 사장님 지적 — 밥집은 목적지가 아니라 돌아오는 길에 들르는 자리라 뺀다 |
**왜 빌드 안인가** — 전에는 이 검사를 매번 따로 쓴 일회용 스크립트로 돌렸다.
그래서 뼈대를 고칠 때마다 "이번에 안 본 규칙"이 생겼고 사장님이 화면에서 먼저 찾으셨다.
@ -829,7 +861,7 @@ docker cp vendor/. \$C:/app/solution/site/out/s/stay/vendor/"
|---|---|
| `README.md` | **이 문서.** 지침은 전부 여기 |
| `TEXT.md` | 화면에 나가는 텍스트 전문 (생성물 — `python3 dump_text.py`) |
| `build_itinerary.py` | 여행 일정 계산 + 규칙 14종 감사 |
| `build_itinerary.py` | 여행 일정 계산 + 규칙 16종 감사 |
| `build_story.py` | 가요 다방 · 인물 열전 + 위키 사진 |
| `patch_stay.py` | 캐치프레이즈 · 객실 · 자작곡 · HTML 조립 · 자산 경로 교정 |
| `dump_text.py` | `TEXT.md` 생성 |
@ -837,6 +869,8 @@ docker cp vendor/. \$C:/app/solution/site/out/s/stay/vendor/"
| `audit-all.mjs` | 브라우저로 34개 항목 전수 점검 |
| `rails-test.mjs` | 카로셀 13개 × 데스크톱·모바일 |
| `kingcheck.mjs` | 킹서버 반영분 확인 |
| `audit_schedule.py` | 일정 전수 검수표 생성 → `SCHEDULE.md` (규칙이 안 보는 논리 12가지) |
| `SCHEDULE.md` | 그 결과물 (생성물) |
### 원본 · 원자료 (건드리지 않는다)
@ -883,6 +917,9 @@ docker exec o2o-web4ai-solution-prerender rm -rf /app/solution/site/out/s/stay
ssh King_admin "rm -rf ~/data2/o2o-site-AEO/tmp-stay-deploy"
```
**지우기 전에 1부를 `docs/` 로 옮긴다.** 1부(제품 구현 지침)는 목업이 사라져도 남아야 하는
내용이다 — 이 폴더째 지우면 같이 없어진다. 2·3부는 목업과 함께 버린다.
`stay2` · `stay3` 도 같은 성격의 목업이다. 함께 정리한다.
★ 지우기 전에 [CLAUDE.md 의 ★★ 함정](../../../../CLAUDE.md)을 읽는다 —
`out/s/**` 이 참조하는 자산을 먼저 빼야 다른 사이트가 안 끊긴다.
@ -897,5 +934,5 @@ ssh King_admin "rm -rf ~/data2/o2o-site-AEO/tmp-stay-deploy"
| 가요 다방 25곡 (목표 50) | 출처에서 확인되는 군산 곡이 거기까지다. 더 채우려면 **지어내야 한다** — 하지 않는다 |
| 인물 사진 18/57 | 위키 문서에 사진이 있는 사람이 18명뿐이다. 동명이인 함정 때문에 이름 검색으로 늘리지 않는다 |
| 렌더러의 카로셀 자동 넘김 | 운영 사이트에 그대로 있다. 고치려면 `use-rail-autoplay.ts` 를 고치고 **전체 재굽기 + `republish_all.py`** |
| 일정 정거장의 체류 대비 이동 | 해망굴처럼 **이동 21분에 체류 30분**인 자리가 몇 개 있다. 감사에 "체류 ≥ 편도 이동" 규칙(15번)을 넣을지 결정 필요 |
| ~~일정 정거장의 체류 대비 이동~~ | **해결(2026-09-11)** — 규칙 15·16 을 감사에 넣었다. 전수 검수 21/21 (`SCHEDULE.md`) |
| 일정을 이미지/링크로 공유 | 이미지 저장은 가능(카드를 PNG 로). 링크는 지금 섹션까지만 간다 — 탭·코스가 URL 에 안 남는다 |

View File

@ -0,0 +1,764 @@
# `/s/stay` 여행 일정 전수 검수표
생성 `python3 audit_schedule.py` · 테마 21개 · 53일 · 304정거장
표는 **구워진 payload 를 렌더러와 같은 방식으로 계산한 값**이다(화면에 뜨는 것과 같다).
규칙 14종(만들 때 거는 것)은 `build_itinerary.py` `audit()` 가 이미 통과시켰고,
이 표는 그 규칙이 **안 보는 논리**를 따로 센다.
## 결과 — 21/21 검수완료
**전부 통과.** 12개 항목 위반 0건.
| 코드 | 검수 항목 |
|---|---|
| L0 | 21시를 넘겨 화면에서 버려지는 칸이 없다 |
| L1 | **체류 ≥ 편도 이동** — 볼거리는 가는 데 든 시간보다 오래 머문다 (끼니 제외 — 밥집은 돌아오는 길에 들르는 자리다) |
| L2 | 가운데 날은 점심과 저녁이 둘 다 있다 |
| L3 | 점심 끝나고 저녁까지 3시간 이상 |
| L4 | 하루의 40% 넘게 길에서 쓰지 않는다 |
| L5 | 바깥 정거장 체류 15분 이상 |
| L6 | 하루가 14시간을 넘지 않는다 |
| L7 | 입실 15:00 이후 · 퇴실 11:00 전 |
| L8 | 하루의 첫 칸·마지막 칸이 숙소 |
| L9 | 같은 자리가 연달아 서지 않는다 |
| L10 | 한 테마 안에서 같은 곳을 두 번 가지 않는다 |
| L11 | 걷는 테마에 편도 25분 넘는 이동이 없다 |
---
## 섬까지 다녀오는 1박 2일
1박 2일 · 차를 가져온 손님 — ✅ **검수완료**
> 첫날은 걸어서 도심, 이튿날은 다리를 건너 섬입니다. 두 날의 성격이 아주 다릅니다.
**첫째 날** 15:0020:11 (총 5시간 11분 · 이동 36분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:45 | 체크인 | 스테이 머뭄 | –분 | 45분 |
| 2 | 15:4816:33 | 오후 | 히로쓰 가옥 | 3분 | 45분 |
| 3 | 16:3717:22 | 오후 | 초원사진관 | 4분 | 45분 |
| 4 | 17:3018:40 | 저녁 | 빈해원 | 8분 | 70분 |
| 5 | 18:4519:25 | 밤 산책 | 군산 내항 | 5분 | 40분 |
| 6 | 19:4120:11 | 머뭄으로 | 스테이 머뭄 | 16분 | 30분 |
**둘째 날** 08:2016:36 (총 8시간 16분 · 이동 176분 · 정거장 4)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:2009:35 | 아침 | 스테이 머뭄 | –분 | 75분 |
| 2 | 10:5913:29 | 오전 | 고군산군도 선유도 | 84분 | 150분 |
| 3 | 14:5415:49 | 늦은 점심 | 국제반점 | 85분 | 55분 |
| 4 | 15:5616:36 | 마무리 | 스테이 머뭄 | 7분 | 40분 |
---
## 걸어서만 도는 1박 2일
1박 2일 · 차 없이 오는 손님 — ✅ **검수완료**
> 모든 정거장이 머뭄에서 걸어 닿습니다. 이틀 동안 차를 한 번도 타지 않습니다.
**첫째 날** 15:0020:05 (총 5시간 5분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:49 | 체크인 | 스테이 머뭄 | –분 | 49분 |
| 2 | 15:5216:37 | 오후 | 히로쓰 가옥 | 3분 | 45분 |
| 3 | 16:4117:26 | 오후 | 초원사진관 | 4분 | 45분 |
| 4 | 17:3018:22 | 저녁 | 일흥옥 | 4분 | 52분 |
| 5 | 18:3519:17 | 밤 산책 | 군산 내항 | 13분 | 42분 |
| 6 | 19:3320:05 | 머뭄으로 | 스테이 머뭄 | 16분 | 32분 |
**둘째 날** 09:2013:52 (총 4시간 32분 · 이동 26분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:2010:39 | 아침 | 스테이 머뭄 | –분 | 79분 |
| 2 | 10:4911:36 | 오전 | 군산근대건축관 | 10분 | 47분 |
| 3 | 11:4012:32 | 점심 | 한일옥 | 4분 | 52분 |
| 4 | 12:3613:02 | 오후 | 우체통거리 | 4분 | 26분 |
| 5 | 13:1013:52 | 마무리 | 스테이 머뭄 | 8분 | 42분 |
---
## 비가 와도 되는 1박 2일
1박 2일 · 비 예보를 보고 오는 손님 — ✅ **검수완료**
> 실내가 이어집니다. 비가 그치기를 기다리지 않아도 하루가 찹니다.
**첫째 날** 15:1020:57 (총 5시간 47분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:1015:49 | 체크인 | 스테이 머뭄 | –분 | 39분 |
| 2 | 16:0017:28 | 오후 | 군산근대역사박물관 | 11분 | 88분 |
| 3 | 17:3118:15 | 오후 | 군산근대미술관 | 3분 | 44분 |
| 4 | 18:2019:28 | 저녁 | 빈해원 | 5분 | 68분 |
| 5 | 19:3320:12 | 밤 산책 | 군산 내항 | 5분 | 39분 |
| 6 | 20:2820:57 | 머뭄으로 | 스테이 머뭄 | 16분 | 29분 |
**둘째 날** 09:4015:36 (총 5시간 56분 · 이동 52분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4011:00 | 아침 | 스테이 머뭄 | –분 | 80분 |
| 2 | 11:1012:02 | 오전 | 군산근대건축관 | 10분 | 52분 |
| 3 | 12:1013:07 | 점심 | 일흥옥 | 8분 | 57분 |
| 4 | 13:2214:31 | 오후 | 째보선창 근처 카페 | 15분 | 69분 |
| 5 | 14:5015:36 | 마무리 | 스테이 머뭄 | 19분 | 46분 |
---
## 근대건축만 보는 1박 2일
1박 2일 · 건물을 보러 오는 손님 — ✅ **검수완료**
> 1900년대 건물만 골라 돕니다. 머뭄도 그 시기에 지은 집입니다.
**첫째 날** 15:0020:14 (총 5시간 14분 · 이동 50분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:38 | 체크인 | 스테이 머뭄 | –분 | 38분 |
| 2 | 15:5116:19 | 오후 | 구 군산세관 본관 | 13분 | 28분 |
| 3 | 16:2317:24 | 오후 | 군산근대건축관 | 4분 | 61분 |
| 4 | 17:3018:41 | 저녁 | 명월갈비 | 6분 | 71분 |
| 5 | 18:5219:30 | 밤 산책 | 군산 내항 | 11분 | 38분 |
| 6 | 19:4620:14 | 머뭄으로 | 스테이 머뭄 | 16분 | 28분 |
**둘째 날** 08:5013:35 (총 4시간 45분 · 이동 37분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:5010:03 | 아침 | 스테이 머뭄 | –분 | 73분 |
| 2 | 10:1211:22 | 오전 | 군산근대미술관 | 9분 | 70분 |
| 3 | 11:3012:18 | 점심 | 일흥옥 | 8분 | 48분 |
| 4 | 12:3012:49 | 오후 | 해망굴 | 12분 | 19분 |
| 5 | 12:5713:35 | 마무리 | 스테이 머뭄 | 8분 | 38분 |
---
## 이성당으로 시작하는 1박 2일
1박 2일 · 빵을 좋아하는 손님 — ✅ **검수완료**
> 이튿날 아침을 빵으로 엽니다. 문 여는 시간에 맞춰 걸어갑니다.
**첫째 날** 16:1020:36 (총 4시간 26분 · 이동 46분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 16:1016:46 | 체크인 | 스테이 머뭄 | –분 | 36분 |
| 2 | 16:5017:17 | 오후 | 초원사진관 | 4분 | 27분 |
| 3 | 17:2317:45 | 오후 | 우체통거리 | 6분 | 22분 |
| 4 | 17:5119:03 | 저녁 | 도란 | 6분 | 72분 |
| 5 | 19:1719:53 | 밤 산책 | 군산 내항 | 14분 | 36분 |
| 6 | 20:0920:36 | 머뭄으로 | 스테이 머뭄 | 16분 | 27분 |
**둘째 날** 08:4014:26 (총 5시간 46분 · 이동 35분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:4010:28 | 아침 | 스테이 머뭄 | –분 | 108분 |
| 2 | 10:3511:25 | 오전 | 이성당 | 7분 | 50분 |
| 3 | 11:3012:06 | 점심 | 만남스넥 | 5분 | 36분 |
| 4 | 12:1813:39 | 오후 | 군산근대역사박물관 | 12분 | 81분 |
| 5 | 13:5014:26 | 마무리 | 스테이 머뭄 | 11분 | 36분 |
---
## 철길마을까지 가는 1박 2일
1박 2일 · 사진을 찍는 손님 — ✅ **검수완료**
> 빛이 좋은 자리만 이어 붙였습니다. 철길마을은 오전 빛이 낫습니다.
**첫째 날** 15:4020:04 (총 4시간 24분 · 이동 47분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:4016:18 | 체크인 | 스테이 머뭄 | –분 | 38분 |
| 2 | 16:2216:50 | 오후 | 초원사진관 | 4분 | 28분 |
| 3 | 16:5817:31 | 오후 | 동국사 | 8분 | 33분 |
| 4 | 17:4118:33 | 저녁 | 국제반점 | 10분 | 52분 |
| 5 | 18:4219:20 | 밤 산책 | 군산 내항 | 9분 | 38분 |
| 6 | 19:3620:04 | 머뭄으로 | 스테이 머뭄 | 16분 | 28분 |
**둘째 날** 08:3014:06 (총 5시간 36분 · 이동 36분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:3009:47 | 아침 | 스테이 머뭄 | –분 | 77분 |
| 2 | 09:5911:19 | 오전 | 경암동 철길마을 | 12분 | 80분 |
| 3 | 11:3012:18 | 점심 | 일흥옥 | 11분 | 48분 |
| 4 | 12:2413:21 | 오후 | 군산 시간여행마을 | 6분 | 57분 |
| 5 | 13:2814:06 | 마무리 | 스테이 머뭄 | 7분 | 38분 |
---
## 항구만 도는 1박 2일
1박 2일 · 바다가 보고 싶은 손님 — ✅ **검수완료**
> 부잔교에서 째보선창까지, 이틀 동안 물가만 걷습니다.
**첫째 날** 15:4020:55 (총 5시간 15분 · 이동 67분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:4016:22 | 체크인 | 스테이 머뭄 | –분 | 42분 |
| 2 | 16:3817:15 | 오후 | 군산 내항 부잔교 | 16분 | 37분 |
| 3 | 17:3217:53 | 오후 | 해망굴 | 17분 | 21분 |
| 4 | 18:0619:20 | 저녁 | 빈해원 | 13분 | 74분 |
| 5 | 19:2520:07 | 밤 산책 | 군산 내항 | 5분 | 42분 |
| 6 | 20:2320:55 | 머뭄으로 | 스테이 머뭄 | 16분 | 32분 |
**둘째 날** 09:2014:14 (총 4시간 54분 · 이동 51분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:2010:39 | 아침 | 스테이 머뭄 | –분 | 79분 |
| 2 | 10:5811:30 | 오전 | 째보선창 | 19분 | 32분 |
| 3 | 11:4212:40 | 점심 | 국제반점 | 12분 | 58분 |
| 4 | 12:4713:19 | 오후 | 구 군산세관 본관 | 7분 | 32분 |
| 5 | 13:3214:14 | 마무리 | 스테이 머뭄 | 13분 | 42분 |
---
## 소설 『탁류』를 따라 걷는 1박 2일
1박 2일 · 채만식을 읽어 본 손님 — ✅ **검수완료**
> 소설이 지나간 자리를 순서대로 밟습니다. 세관·선창·문학관이 한 줄로 이어집니다.
**첫째 날** 15:1020:19 (총 5시간 9분 · 이동 62분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:1015:54 | 체크인 | 스테이 머뭄 | –분 | 44분 |
| 2 | 16:1316:46 | 오후 | 째보선창 | 19분 | 33분 |
| 3 | 16:5117:29 | 오후 | 군산 내항 부잔교 | 5분 | 38분 |
| 4 | 17:4018:35 | 저녁 | 한일옥 | 11분 | 55분 |
| 5 | 18:4619:30 | 밤 산책 | 군산 내항 | 11분 | 44분 |
| 6 | 19:4620:19 | 머뭄으로 | 스테이 머뭄 | 16분 | 33분 |
**둘째 날** 09:0014:40 (총 5시간 40분 · 이동 60분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:0010:22 | 아침 | 스테이 머뭄 | –분 | 82분 |
| 2 | 10:4011:46 | 오전 | 채만식문학관 | 18분 | 66분 |
| 3 | 12:0312:58 | 점심 | 일흥옥 | 17분 | 55분 |
| 4 | 13:1013:43 | 오후 | 구 군산세관 본관 | 12분 | 33분 |
| 5 | 13:5614:40 | 마무리 | 스테이 머뭄 | 13분 | 44분 |
---
## 아이와 함께 1박 2일
1박 2일 · 아이를 데려온 손님 — ✅ **검수완료**
> 걷는 거리가 짧고, 아이가 지루해할 자리를 뺐습니다.
**첫째 날** 16:0019:46 (총 3시간 46분 · 이동 43분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 16:0016:34 | 체크인 | 스테이 머뭄 | –분 | 34분 |
| 2 | 16:3817:04 | 오후 | 초원사진관 | 4분 | 26분 |
| 3 | 17:1017:31 | 오후 | 우체통거리 | 6분 | 21분 |
| 4 | 17:3518:17 | 저녁 | 만남스넥 | 4분 | 42분 |
| 5 | 18:3019:04 | 밤 산책 | 군산 내항 | 13분 | 34분 |
| 6 | 19:2019:46 | 머뭄으로 | 스테이 머뭄 | 16분 | 26분 |
**둘째 날** 10:1014:10 (총 4시간 0분 · 이동 42분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 10:1011:00 | 아침 | 스테이 머뭄 | –분 | 50분 |
| 2 | 11:1211:54 | 오전 | 경암동 철길마을 | 12분 | 42분 |
| 3 | 12:0512:35 | 점심 | 이성당 | 11분 | 30분 |
| 4 | 12:4513:27 | 오후 | 월명호수 | 10분 | 42분 |
| 5 | 13:3614:10 | 마무리 | 스테이 머뭄 | 9분 | 34분 |
---
## 늦게 도착하는 1박 2일
1박 2일 · 퇴근하고 오는 손님 — ✅ **검수완료**
> 첫날은 저녁 한 끼로 끝냅니다. 대신 이튿날을 아침부터 저녁까지 씁니다.
**첫째 날** 18:2020:55 (총 2시간 35분 · 이동 10분 · 정거장 3)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 18:2019:00 | 체크인 | 스테이 머뭄 | –분 | 40분 |
| 2 | 19:0520:20 | 저녁 | 명월갈비 | 5분 | 75분 |
| 3 | 20:2520:55 | 머뭄으로 | 스테이 머뭄 | 5분 | 30분 |
**둘째 날** 08:4014:39 (총 5시간 59분 · 이동 39분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:4009:55 | 아침 | 스테이 머뭄 | –분 | 75분 |
| 2 | 10:0611:36 | 오전 | 군산근대역사박물관 | 11분 | 90분 |
| 3 | 11:4212:32 | 점심 | 한일옥 | 6분 | 50분 |
| 4 | 12:3613:21 | 오후 | 군산근대건축관 | 4분 | 45분 |
| 5 | 13:3113:51 | 오후 | 해망굴 | 10분 | 20분 |
| 6 | 13:5914:39 | 마무리 | 스테이 머뭄 | 8분 | 40분 |
---
## 천천히 도는 2박 3일
2박 3일 · 쉬러 오는 손님 — ✅ **검수완료**
> 하루에 두어 곳만 봅니다. 마당에 앉아 있는 시간을 일정에 넣었습니다.
**첫째 날** 15:2021:00 (총 5시간 40분 · 이동 46분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:2016:06 | 체크인 | 스테이 머뭄 | –분 | 46분 |
| 2 | 16:0916:44 | 오후 | 히로쓰 가옥 | 3분 | 35분 |
| 3 | 16:5017:30 | 오후 | 동국사 | 6분 | 40분 |
| 4 | 17:3719:09 | 저녁 | 도란 | 7분 | 92분 |
| 5 | 19:2320:09 | 밤 산책 | 군산 내항 | 14분 | 46분 |
| 6 | 20:2521:00 | 머뭄으로 | 스테이 머뭄 | 16분 | 35분 |
**둘째 날** 09:4019:27 (총 9시간 47분 · 이동 32분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4013:23 | 머뭄에서 쉬는 날 | 스테이 머뭄 | –분 | 223분 |
| 2 | 13:2814:21 | 점심 | 한일옥 | 5분 | 53분 |
| 3 | 14:2617:19 | 쉼 | 스테이 머뭄 | 5분 | 173분 |
| 4 | 17:3018:44 | 저녁 | 빈해원 | 11분 | 74분 |
| 5 | 18:5519:27 | 머뭄으로 | 스테이 머뭄 | 11분 | 32분 |
**셋째 날** 09:5015:05 (총 5시간 15분 · 이동 26분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:5011:00 | 아침 | 스테이 머뭄 | –분 | 70분 |
| 2 | 11:0711:51 | 오전 | 이성당 | 7분 | 44분 |
| 3 | 11:5612:46 | 점심 | 만남스넥 | 5분 | 50분 |
| 4 | 12:5314:08 | 오후 | 군산 시간여행마을 | 7분 | 75분 |
| 5 | 14:1515:05 | 마무리 | 스테이 머뭄 | 7분 | 50분 |
---
## 섬과 도심을 반씩 도는 2박 3일
2박 3일 · 차를 가져온 손님 — ✅ **검수완료**
> 가운데 날을 섬에 다 씁니다. 첫날과 마지막 날은 걸어서 도심입니다.
**첫째 날** 15:1020:11 (총 5시간 1분 · 이동 41분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:1015:50 | 체크인 | 스테이 머뭄 | –분 | 40분 |
| 2 | 16:0316:33 | 오후 | 구 군산세관 본관 | 13분 | 30분 |
| 3 | 16:3717:27 | 오후 | 군산근대건축관 | 4분 | 50분 |
| 4 | 17:3018:40 | 저녁 | 빈해원 | 3분 | 70분 |
| 5 | 18:4519:25 | 밤 산책 | 군산 내항 | 5분 | 40분 |
| 6 | 19:4120:11 | 머뭄으로 | 스테이 머뭄 | 16분 | 30분 |
**둘째 날** 07:2020:37 (총 13시간 17분 · 이동 209분 · 정거장 7)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 07:2008:20 | 아침 | 스테이 머뭄 | –분 | 60분 |
| 2 | 09:4412:14 | 오전 | 고군산군도 선유도 | 84분 | 150분 |
| 3 | 12:3413:24 | 오후 | 장자도 | 20분 | 50분 |
| 4 | 14:5215:47 | 늦은 점심 | 국제반점 | 88분 | 55분 |
| 5 | 15:5418:42 | 쉼 | 스테이 머뭄 | 7분 | 168분 |
| 6 | 18:4720:02 | 저녁 | 명월갈비 | 5분 | 75분 |
| 7 | 20:0720:37 | 머뭄으로 | 스테이 머뭄 | 5분 | 30분 |
**셋째 날** 09:2013:46 (총 4시간 26분 · 이동 19분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:2010:37 | 아침 | 스테이 머뭄 | –분 | 77분 |
| 2 | 10:4111:26 | 오전 | 초원사진관 | 4분 | 45분 |
| 3 | 11:3012:20 | 점심 | 일흥옥 | 4분 | 50분 |
| 4 | 12:2412:59 | 오후 | 이성당 | 4분 | 35분 |
| 5 | 13:0613:46 | 마무리 | 스테이 머뭄 | 7분 | 40분 |
---
## 골목을 세 번 나눠 걷는 2박 3일
2박 3일 · 차 없이 오는 손님 — ✅ **검수완료**
> 원도심을 세 덩이로 나눠 하루에 하나씩 걷습니다. 같은 길을 두 번 걷지 않습니다.
**첫째 날** 15:0020:11 (총 5시간 11분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:49 | 체크인 | 스테이 머뭄 | –분 | 49분 |
| 2 | 15:5216:37 | 오후 | 히로쓰 가옥 | 3분 | 45분 |
| 3 | 16:4117:26 | 오후 | 초원사진관 | 4분 | 45분 |
| 4 | 17:3018:25 | 저녁 | 일흥옥 | 4분 | 55분 |
| 5 | 18:3819:22 | 밤 산책 | 군산 내항 | 13분 | 44분 |
| 6 | 19:3820:11 | 머뭄으로 | 스테이 머뭄 | 16분 | 33분 |
**둘째 날** 09:1019:30 (총 10시간 20분 · 이동 49분 · 정거장 8)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:1010:16 | 아침 | 스테이 머뭄 | –분 | 66분 |
| 2 | 10:2712:06 | 오전 | 군산근대역사박물관 | 11분 | 99분 |
| 3 | 12:1213:07 | 점심 | 한일옥 | 6분 | 55분 |
| 4 | 13:1114:01 | 오후 | 군산근대건축관 | 4분 | 50분 |
| 5 | 14:1114:33 | 오후 | 해망굴 | 10분 | 22분 |
| 6 | 14:4117:25 | 쉼 | 스테이 머뭄 | 8분 | 164분 |
| 7 | 17:3018:52 | 저녁 | 명월갈비 | 5분 | 82분 |
| 8 | 18:5719:30 | 머뭄으로 | 스테이 머뭄 | 5분 | 33분 |
**셋째 날** 08:5014:18 (총 5시간 28분 · 이동 26분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:5010:38 | 아침 | 스테이 머뭄 | –분 | 108분 |
| 2 | 10:4611:26 | 오전 | 우체통거리 | 8분 | 40분 |
| 3 | 11:3012:14 | 점심 | 만남스넥 | 4분 | 44분 |
| 4 | 12:2113:27 | 오후 | 군산 시간여행마을 | 7분 | 66분 |
| 5 | 13:3414:18 | 마무리 | 스테이 머뭄 | 7분 | 44분 |
---
## 먹으러 오는 2박 3일
2박 3일 · 맛집을 도는 손님 — ✅ **검수완료**
> 끼니가 중심입니다. 사이에 걸을 자리를 넣어 배를 비웁니다.
**첫째 날** 15:3020:56 (총 5시간 26분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:3016:16 | 체크인 | 스테이 머뭄 | –분 | 46분 |
| 2 | 16:2017:00 | 오후 | 물밀소 | 4분 | 40분 |
| 3 | 17:0617:40 | 오후 | 초원사진관 | 6분 | 34분 |
| 4 | 17:4319:09 | 저녁 | 명월갈비 | 3분 | 86분 |
| 5 | 19:2020:06 | 밤 산책 | 군산 내항 | 11분 | 46분 |
| 6 | 20:2220:56 | 머뭄으로 | 스테이 머뭄 | 16분 | 34분 |
**둘째 날** 10:2019:35 (총 9시간 15분 · 이동 50분 · 정거장 8)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 10:2011:29 | 아침 | 스테이 머뭄 | –분 | 69분 |
| 2 | 11:3612:45 | 오전 | 군산 시간여행마을 | 7분 | 69분 |
| 3 | 12:5113:48 | 점심 | 일흥옥 | 6분 | 57분 |
| 4 | 13:5214:32 | 오후 | 이성당 | 4분 | 40분 |
| 5 | 14:3515:04 | 오후 | 우체통거리 | 3분 | 29분 |
| 6 | 15:1217:19 | 쉼 | 스테이 머뭄 | 8분 | 127분 |
| 7 | 17:3018:50 | 저녁 | 빈해원 | 11분 | 80분 |
| 8 | 19:0119:35 | 머뭄으로 | 스테이 머뭄 | 11분 | 34분 |
**셋째 날** 08:4015:18 (총 6시간 38분 · 이동 32분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:4010:24 | 아침 | 스테이 머뭄 | –분 | 104분 |
| 2 | 10:3011:20 | 오전 | 동국사 | 6분 | 50분 |
| 3 | 11:3012:33 | 점심 | 국제반점 | 10분 | 63분 |
| 4 | 12:3814:21 | 오후 | 군산근대역사박물관 | 5분 | 103분 |
| 5 | 14:3215:18 | 마무리 | 스테이 머뭄 | 11분 | 46분 |
---
## 아무 데도 안 가는 2박 3일
2박 3일 · 쉬려고만 오는 손님 — ✅ **검수완료**
> 가운데 날은 대문 밖으로 두 번만 나갑니다. 나머지는 마당과 카페 공간에서 보냅니다.
**첫째 날** 15:0021:00 (총 6시간 0분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:50 | 체크인 | 스테이 머뭄 | –분 | 50분 |
| 2 | 15:5316:38 | 오후 | 히로쓰 가옥 | 3분 | 45분 |
| 3 | 16:4217:27 | 오후 | 초원사진관 | 4분 | 45분 |
| 4 | 17:3019:06 | 저녁 | 도란 | 3분 | 96분 |
| 5 | 19:2020:08 | 밤 산책 | 군산 내항 | 14분 | 48분 |
| 6 | 20:2421:00 | 머뭄으로 | 스테이 머뭄 | 16분 | 36분 |
**둘째 날** 09:3019:03 (총 9시간 33분 · 이동 22분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:3013:22 | 머뭄에서 쉬는 날 | 스테이 머뭄 | –분 | 232분 |
| 2 | 13:2814:12 | 점심 | 만남스넥 | 6분 | 44분 |
| 3 | 14:1817:25 | 쉼 | 스테이 머뭄 | 6분 | 187분 |
| 4 | 17:3018:25 | 저녁 | 일흥옥 | 5분 | 55분 |
| 5 | 18:3019:03 | 머뭄으로 | 스테이 머뭄 | 5분 | 33분 |
**셋째 날** 09:0014:34 (총 5시간 34분 · 이동 27분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:0010:38 | 아침 | 스테이 머뭄 | –분 | 98분 |
| 2 | 10:4411:30 | 오전 | 동국사 | 6분 | 46분 |
| 3 | 11:3312:19 | 점심 | 물밀소 | 3분 | 46분 |
| 4 | 12:2813:33 | 오후 | 월명호수 | 9분 | 65분 |
| 5 | 13:4214:34 | 마무리 | 스테이 머뭄 | 9분 | 52분 |
---
## 사진만 찍는 2박 3일
2박 3일 · 사진을 찍는 손님 — ✅ **검수완료**
> 시간대에 맞춰 자리를 배치했습니다. 철길마을은 오전, 부잔교는 해 질 때입니다.
**첫째 날** 15:5020:03 (총 4시간 13분 · 이동 49분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:5016:22 | 체크인 | 스테이 머뭄 | –분 | 32분 |
| 2 | 16:2616:50 | 오후 | 초원사진관 | 4분 | 24분 |
| 3 | 16:5817:26 | 오후 | 동국사 | 8분 | 28분 |
| 4 | 17:3318:37 | 저녁 | 도란 | 7분 | 64분 |
| 5 | 18:5119:23 | 밤 산책 | 군산 내항 | 14분 | 32분 |
| 6 | 19:3920:03 | 머뭄으로 | 스테이 머뭄 | 16분 | 24분 |
**둘째 날** 09:4018:46 (총 9시간 6분 · 이동 81분 · 정거장 8)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4010:28 | 아침 | 스테이 머뭄 | –분 | 48분 |
| 2 | 10:4011:20 | 오전 | 경암동 철길마을 | 12분 | 40분 |
| 3 | 11:3112:14 | 점심 | 만남스넥 | 11분 | 43분 |
| 4 | 12:2913:14 | 오후 | 째보선창 | 15분 | 45분 |
| 5 | 13:3514:05 | 오후 | 해망굴 | 21분 | 30분 |
| 6 | 14:1317:23 | 쉼 | 스테이 머뭄 | 8분 | 190분 |
| 7 | 17:3018:15 | 저녁 | 국제반점 | 7분 | 45분 |
| 8 | 18:2218:46 | 머뭄으로 | 스테이 머뭄 | 7분 | 24분 |
**셋째 날** 08:5013:35 (총 4시간 45분 · 이동 29분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:5010:38 | 아침 | 스테이 머뭄 | –분 | 108분 |
| 2 | 10:4611:26 | 오전 | 우체통거리 | 8분 | 40분 |
| 3 | 11:3012:10 | 점심 | 일흥옥 | 4분 | 40분 |
| 4 | 12:1812:54 | 오후 | 군산근대미술관 | 8분 | 36분 |
| 5 | 13:0313:35 | 마무리 | 스테이 머뭄 | 9분 | 32분 |
---
## 비가 와도 되는 2박 3일
2박 3일 · 비 예보를 보고 오는 손님 — ✅ **검수완료**
> 사흘 내리 비가 와도 도는 순서가 바뀌지 않습니다. 실내와 처마 밑만 잇습니다.
**첫째 날** 15:0020:55 (총 5시간 55분 · 이동 40분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:40 | 체크인 | 스테이 머뭄 | –분 | 40분 |
| 2 | 15:5117:21 | 오후 | 군산근대역사박물관 | 11분 | 90분 |
| 3 | 17:2418:09 | 오후 | 군산근대미술관 | 3분 | 45분 |
| 4 | 18:1419:24 | 저녁 | 빈해원 | 5분 | 70분 |
| 5 | 19:2920:09 | 밤 산책 | 군산 내항 | 5분 | 40분 |
| 6 | 20:2520:55 | 머뭄으로 | 스테이 머뭄 | 16분 | 30분 |
**둘째 날** 10:1019:48 (총 9시간 38분 · 이동 62분 · 정거장 8)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 10:1011:22 | 아침 | 스테이 머뭄 | –분 | 72분 |
| 2 | 11:3212:26 | 오전 | 군산근대건축관 | 10분 | 54분 |
| 3 | 12:3413:34 | 점심 | 일흥옥 | 8분 | 60분 |
| 4 | 13:4915:01 | 오후 | 째보선창 근처 카페 | 15분 | 72분 |
| 5 | 15:0915:57 | 오후 | 동국사다온 | 8분 | 48분 |
| 6 | 16:0817:32 | 쉼 | 스테이 머뭄 | 11분 | 84분 |
| 7 | 17:3719:07 | 저녁 | 명월갈비 | 5분 | 90분 |
| 8 | 19:1219:48 | 머뭄으로 | 스테이 머뭄 | 5분 | 36분 |
**셋째 날** 09:4015:27 (총 5시간 47분 · 이동 45분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4011:00 | 아침 | 스테이 머뭄 | –분 | 80분 |
| 2 | 11:1812:30 | 오전 | 채만식문학관 | 18분 | 72분 |
| 3 | 12:4713:47 | 점심 | 한일옥 | 17분 | 60분 |
| 4 | 13:5014:32 | 오후 | 이성당 | 3분 | 42분 |
| 5 | 14:3915:27 | 마무리 | 스테이 머뭄 | 7분 | 48분 |
---
## 늦게 시작하는 2박 3일
2박 3일 · 아침이 힘든 손님 — ✅ **검수완료**
> 가운데 날을 열한 시에 엽니다. 오전을 비우고 저녁을 늦게까지 씁니다.
**첫째 날** 16:0020:52 (총 4시간 52분 · 이동 47분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 16:0016:40 | 체크인 | 스테이 머뭄 | –분 | 40분 |
| 2 | 16:4317:13 | 오후 | 히로쓰 가옥 | 3분 | 30분 |
| 3 | 17:2117:46 | 오후 | 우체통거리 | 8분 | 25분 |
| 4 | 17:5219:12 | 저녁 | 도란 | 6분 | 80분 |
| 5 | 19:2620:06 | 밤 산책 | 군산 내항 | 14분 | 40분 |
| 6 | 20:2220:52 | 머뭄으로 | 스테이 머뭄 | 16분 | 30분 |
**둘째 날** 10:3019:21 (총 8시간 51분 · 이동 55분 · 정거장 7)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 10:3011:30 | 아침 | 스테이 머뭄 | –분 | 60분 |
| 2 | 11:3512:25 | 점심 | 일흥옥 | 5분 | 50분 |
| 3 | 12:3514:05 | 오후 | 군산근대역사박물관 | 10분 | 90분 |
| 4 | 14:1514:35 | 오후 | 해망굴 | 10분 | 20분 |
| 5 | 14:4317:19 | 쉼 | 스테이 머뭄 | 8분 | 156분 |
| 6 | 17:3018:40 | 저녁 | 빈해원 | 11분 | 70분 |
| 7 | 18:5119:21 | 머뭄으로 | 스테이 머뭄 | 11분 | 30분 |
**셋째 날** 10:1013:47 (총 3시간 37분 · 이동 22분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 10:1011:00 | 아침 | 스테이 머뭄 | –분 | 50분 |
| 2 | 11:0711:42 | 오전 | 이성당 | 7분 | 35분 |
| 3 | 11:4712:27 | 점심 | 만남스넥 | 5분 | 40분 |
| 4 | 12:3313:03 | 오후 | 초원사진관 | 6분 | 30분 |
| 5 | 13:0713:47 | 마무리 | 스테이 머뭄 | 4분 | 40분 |
---
## 섬에서 하루를 다 쓰는 2박 3일
2박 3일 · 차를 가져온 손님 — ✅ **검수완료**
> 가운데 날은 아침에 나가 저녁에 들어옵니다. 섬에서 하루를 통째로 씁니다.
**첫째 날** 15:0020:03 (총 5시간 3분 · 이동 67분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:38 | 체크인 | 스테이 머뭄 | –분 | 38분 |
| 2 | 15:5416:30 | 오후 | 군산 내항 부잔교 | 16분 | 36분 |
| 3 | 16:4717:17 | 오후 | 해망굴 | 17분 | 30분 |
| 4 | 17:3018:36 | 저녁 | 빈해원 | 13분 | 66분 |
| 5 | 18:4119:19 | 밤 산책 | 군산 내항 | 5분 | 38분 |
| 6 | 19:3520:03 | 머뭄으로 | 스테이 머뭄 | 16분 | 28분 |
**둘째 날** 07:3020:21 (총 12시간 51분 · 이동 207분 · 정거장 7)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 07:3008:27 | 아침 | 스테이 머뭄 | –분 | 57분 |
| 2 | 09:5112:13 | 오전 | 고군산군도 선유도 | 84분 | 142분 |
| 3 | 12:3313:21 | 오후 | 장자도 | 20분 | 48분 |
| 4 | 14:4915:37 | 늦은 점심 | 한일옥 | 88분 | 48분 |
| 5 | 15:4218:32 | 쉼 | 스테이 머뭄 | 5분 | 170분 |
| 6 | 18:3719:48 | 저녁 | 명월갈비 | 5분 | 71분 |
| 7 | 19:5320:21 | 머뭄으로 | 스테이 머뭄 | 5분 | 28분 |
**셋째 날** 09:4014:20 (총 4시간 40분 · 이동 42분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4010:51 | 아침 | 스테이 머뭄 | –분 | 71분 |
| 2 | 11:0111:44 | 오전 | 군산근대건축관 | 10분 | 43분 |
| 3 | 11:5312:31 | 점심 | 만남스넥 | 9분 | 38분 |
| 4 | 12:4213:30 | 오후 | 경암동 철길마을 | 11분 | 48분 |
| 5 | 13:4214:20 | 마무리 | 스테이 머뭄 | 12분 | 38분 |
---
## 소설 『탁류』를 따라 걷는 2박 3일
2박 3일 · 채만식을 읽어 본 손님 — ✅ **검수완료**
> 소설의 순서대로 사흘을 나눴습니다. 선창에서 시작해 문학관에서 끝냅니다.
**첫째 날** 15:0020:13 (총 5시간 13분 · 이동 66분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 15:0015:44 | 체크인 | 스테이 머뭄 | –분 | 44분 |
| 2 | 16:0316:36 | 오후 | 째보선창 | 19분 | 33분 |
| 3 | 16:4117:19 | 오후 | 군산 내항 부잔교 | 5분 | 38분 |
| 4 | 17:3218:27 | 저녁 | 일흥옥 | 13분 | 55분 |
| 5 | 18:4019:24 | 밤 산책 | 군산 내항 | 13분 | 44분 |
| 6 | 19:4020:13 | 머뭄으로 | 스테이 머뭄 | 16분 | 33분 |
**둘째 날** 09:3019:31 (총 10시간 1분 · 이동 32분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:3013:21 | 머뭄에서 쉬는 날 | 스테이 머뭄 | –분 | 231분 |
| 2 | 13:2614:21 | 점심 | 한일옥 | 5분 | 55분 |
| 3 | 14:2617:19 | 쉼 | 스테이 머뭄 | 5분 | 173분 |
| 4 | 17:3018:47 | 저녁 | 빈해원 | 11분 | 77분 |
| 5 | 18:5819:31 | 머뭄으로 | 스테이 머뭄 | 11분 | 33분 |
**셋째 날** 08:3014:12 (총 5시간 42분 · 이동 23분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 08:3009:52 | 아침 | 스테이 머뭄 | –분 | 82분 |
| 2 | 10:0311:42 | 오전 | 군산근대역사박물관 | 11분 | 99분 |
| 3 | 11:4712:48 | 점심 | 국제반점 | 5분 | 61분 |
| 4 | 12:5113:24 | 오후 | 초원사진관 | 3분 | 33분 |
| 5 | 13:2814:12 | 마무리 | 스테이 머뭄 | 4분 | 44분 |
---
## 철길마을과 항구를 같이 보는 2박 3일
2박 3일 · 사진을 찍는 손님 — ✅ **검수완료**
> 기찻길과 물길을 하루씩 나눠 봅니다. 마지막 날은 건물만 봅니다.
**첫째 날** 16:0020:32 (총 4시간 32분 · 이동 51분 · 정거장 6)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 16:0016:36 | 체크인 | 스테이 머뭄 | –분 | 36분 |
| 2 | 16:4817:33 | 오후 | 경암동 철길마을 | 12분 | 45분 |
| 3 | 17:4418:11 | 오후 | 초원사진관 | 11분 | 27분 |
| 4 | 18:1419:04 | 저녁 | 국제반점 | 3분 | 50분 |
| 5 | 19:1319:49 | 밤 산책 | 군산 내항 | 9분 | 36분 |
| 6 | 20:0520:32 | 머뭄으로 | 스테이 머뭄 | 16분 | 27분 |
**둘째 날** 09:4019:10 (총 9시간 30분 · 이동 79분 · 정거장 8)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:4010:34 | 아침 | 스테이 머뭄 | –분 | 54분 |
| 2 | 10:5011:22 | 오전 | 군산 내항 부잔교 | 16분 | 32분 |
| 3 | 11:3312:18 | 점심 | 한일옥 | 11분 | 45분 |
| 4 | 12:3113:16 | 오후 | 째보선창 | 13분 | 45분 |
| 5 | 13:3714:07 | 오후 | 해망굴 | 21분 | 30분 |
| 6 | 14:1517:25 | 쉼 | 스테이 머뭄 | 8분 | 190분 |
| 7 | 17:3018:38 | 저녁 | 명월갈비 | 5분 | 68분 |
| 8 | 18:4319:10 | 머뭄으로 | 스테이 머뭄 | 5분 | 27분 |
**셋째 날** 09:3013:48 (총 4시간 18분 · 이동 42분 · 정거장 5)
| | 시각 | 자리 | 장소 | 이동 | 체류 |
|---|---|---|---|---|---|
| 1 | 09:3010:38 | 아침 | 스테이 머뭄 | –분 | 68분 |
| 2 | 10:5111:18 | 오전 | 구 군산세관 본관 | 13분 | 27분 |
| 3 | 11:3012:15 | 점심 | 일흥옥 | 12분 | 45분 |
| 4 | 12:2313:03 | 오후 | 군산근대미술관 | 8분 | 40분 |
| 5 | 13:1213:48 | 마무리 | 스테이 머뭄 | 9분 | 36분 |

View File

@ -0,0 +1,181 @@
"""구워진 payload 의 일정 21개를 표로 뽑고, 규칙 14종이 **안 보는** 논리까지 검수한다.
따로 있나 build_itinerary.py audit() "만들 때" 지키는 규칙이다.
스크립트는 **만들어진 결과** 사람이 읽는 표로 펴고, 비율·간격처럼
규칙에 없던 것을 센다. 사장님이 화면에서 찾아내신 종류가 전부 여기 있다.
"""
import json, re, sys
from pathlib import Path
SP = Path(__file__).resolve().parent
html = (SP / "build" / "index.html").read_text(encoding="utf-8")
payload = json.loads(re.search(r"window\.__SITE_PAYLOAD__\s*=\s*(\{.*?\});?\s*</script>", html, re.S).group(1))
sec = next(s for s in payload["theme"]["sections"] if s["id"] == "itinerary")
items = json.loads(sec["data"])["items"]
STAY = "스테이 머뭄"
MEAL_SLOTS = {"점심", "늦은 점심", "저녁"}
def hm(m): return f"{m // 60:02d}:{m % 60:02d}"
def plan(day):
"""렌더러(shared planDay)와 같은 계산. 21시 넘는 칸은 렌더러가 버린다."""
clock = int(day["startTime"][:2]) * 60 + int(day["startTime"][3:])
rows, dropped = [], 0
for s in day["stops"]:
move = max(0, s.get("moveMinutes", 0))
stay = max(1, s.get("minutes", 60))
arrive = clock + move
if arrive + stay > 21 * 60:
dropped += 1
continue
rows.append({"name": s["name"], "slot": s["name"].split(" · ")[0],
"place": s["name"].split(" · ")[-1], "move": move, "stay": stay,
"from": arrive, "to": arrive + stay})
clock = arrive + stay
return rows, dropped
def check(item):
"""규칙 14종이 안 보는 논리. (코드, 설명) 목록을 돌려준다."""
bad = []
name = item["name"]
seen_places = []
for day in item["days"]:
rows, dropped = plan(day)
label = day["label"]
if dropped:
bad.append(("L0", f"{label}: 21시를 넘겨 화면에서 버려지는 칸 {dropped}"))
if not rows:
bad.append(("L0", f"{label}: 칸이 없다"))
continue
outs = [r for r in rows if r["place"] != STAY]
# L1 체류 ≥ 편도 이동 — 가는 데 든 시간보다 짧게 머물면 다녀온 의미가 없다.
# ★ 끼니는 뺀다. 밥집은 목적지가 아니라 **돌아오는 길에 들르는 자리**다 —
# 섬에서 85분 달려와 55분 먹는 것은 이상하지 않고, 섬에 30분 있는 것이 이상하다.
# (2026-09-11 사장님 지적의 실제 대상은 선유도였고, 선유도는 150분이다.)
for r in outs:
if r["slot"] in MEAL_SLOTS:
continue
if r["stay"] < r["move"]:
bad.append(("L1", f"{label} {r['place']}: 이동 {r['move']}분인데 체류 {r['stay']}"))
# L2 끼니 — 둘째 날부터는 점심과 저녁이 다 있어야 한다(마지막 날은 저녁 없이 떠난다)
meals = [r for r in rows if r["slot"] in MEAL_SLOTS]
is_first = label == item["days"][0]["label"]
is_last = label == item["days"][-1]["label"]
if not meals:
bad.append(("L2", f"{label}: 끼니가 하나도 없다"))
elif not is_first and not is_last:
slots = {r["slot"] for r in meals}
if not (slots & {"점심", "늦은 점심"}) or "저녁" not in slots:
bad.append(("L2", f"{label}: 점심/저녁 중 하나가 없다 ({sorted(slots)})"))
# L3 끼니 간격 — 점심과 저녁이 3시간 미만이면 배가 안 꺼진다
lunch = next((r for r in meals if r["slot"] in {"점심", "늦은 점심"}), None)
dinner = next((r for r in meals if r["slot"] == "저녁"), None)
if lunch and dinner and dinner["from"] - lunch["to"] < 180:
bad.append(("L3", f"{label}: 점심 끝나고 저녁까지 {dinner['from'] - lunch['to']}"))
# L4 하루 이동 비율 — 절반을 길에서 쓰면 그건 관광이 아니라 운전이다
span = rows[-1]["to"] - rows[0]["from"]
move_sum = sum(r["move"] for r in rows)
if span and move_sum / span > 0.40:
bad.append(("L4", f"{label}: 하루 {span}분 중 이동 {move_sum}분 ({move_sum / span:.0%})"))
# L5 너무 짧은 정거장 — 15분은 들렀다 가는 것도 아니다
for r in outs:
if r["stay"] < 15:
bad.append(("L5", f"{label} {r['place']}: 체류 {r['stay']}"))
# L6 하루 길이 — 14시간을 넘으면 손님이 못 따라온다
if span > 14 * 60:
bad.append(("L6", f"{label}: 하루가 {span // 60}시간 {span % 60}"))
# L7 첫날 입실 15:00 이후 · 마지막 날 퇴실 11:00 전
if is_first and rows[0]["place"] == STAY and rows[0]["from"] < 15 * 60:
bad.append(("L7", f"{label}: 입실이 {hm(rows[0]['from'])}"))
if is_last and rows[0]["place"] == STAY and rows[0]["to"] > 11 * 60:
bad.append(("L7", f"{label}: 퇴실이 {hm(rows[0]['to'])}"))
# L8 시작·끝이 숙소인가
if rows[0]["place"] != STAY:
bad.append(("L8", f"{label}: 첫 칸이 {rows[0]['place']}"))
if rows[-1]["place"] != STAY:
bad.append(("L8", f"{label}: 마지막 칸이 {rows[-1]['place']}"))
# L9 같은 자리 연속
for i in range(1, len(rows)):
if rows[i]["place"] == rows[i - 1]["place"]:
bad.append(("L9", f"{label}: {rows[i]['place']} 가 연달아"))
seen_places += [r["place"] for r in outs]
# L10 테마 안에서 같은 곳 두 번
dup = {p for p in seen_places if seen_places.count(p) > 1}
if dup:
bad.append(("L10", f"테마 안에서 반복: {', '.join(sorted(dup))}"))
# L11 테마 이름·대상과 내용 — '걸어서'/'차 없이' 인데 편도 25분 넘는 이동이 있나
walkish = any(k in name + item.get("audience", "") for k in ("걸어서", "차 없이", "뚜벅"))
if walkish:
for day in item["days"]:
rows, _ = plan(day)
far = [r for r in rows if r["move"] > 25]
if far:
bad.append(("L11", f"걷는 테마인데 {far[0]['place']} 이동 {far[0]['move']}"))
return bad
lines = ["# `/s/stay` 여행 일정 전수 검수표", "",
f"생성 `python3 audit_schedule.py` · 테마 {len(items)}개 · "
f"{sum(len(i['days']) for i in items)}일 · "
f"{sum(len(d['stops']) for i in items for d in i['days'])}정거장", "",
"표는 **구워진 payload 를 렌더러와 같은 방식으로 계산한 값**이다(화면에 뜨는 것과 같다).",
"규칙 14종(만들 때 거는 것)은 `build_itinerary.py` `audit()` 가 이미 통과시켰고,",
"이 표는 그 규칙이 **안 보는 논리**를 따로 센다.", "",
"| 코드 | 검수 항목 |", "|---|---|",
"| L0 | 21시를 넘겨 화면에서 버려지는 칸이 없다 |",
"| L1 | **체류 ≥ 편도 이동** — 볼거리는 가는 데 든 시간보다 오래 머문다 (끼니 제외 — 밥집은 돌아오는 길에 들르는 자리다) |",
"| L2 | 가운데 날은 점심과 저녁이 둘 다 있다 |",
"| L3 | 점심 끝나고 저녁까지 3시간 이상 |",
"| L4 | 하루의 40% 넘게 길에서 쓰지 않는다 |",
"| L5 | 바깥 정거장 체류 15분 이상 |",
"| L6 | 하루가 14시간을 넘지 않는다 |",
"| L7 | 입실 15:00 이후 · 퇴실 11:00 전 |",
"| L8 | 하루의 첫 칸·마지막 칸이 숙소 |",
"| L9 | 같은 자리가 연달아 서지 않는다 |",
"| L10 | 한 테마 안에서 같은 곳을 두 번 가지 않는다 |",
"| L11 | 걷는 테마에 편도 25분 넘는 이동이 없다 |", ""]
fails = []
for item in items:
bad = check(item)
mark = "✅ **검수완료**" if not bad else "⚠️ **확인필요**"
lines += ["---", "", f"## {item['name']}", "",
f"{item['duration']} · {item.get('audience', '')}{mark}", "",
f"> {item.get('why', '')}", ""]
for day in item["days"]:
rows, _ = plan(day)
span = rows[-1]["to"] - rows[0]["from"]
move_sum = sum(r["move"] for r in rows)
lines += [f"**{day['label']}** {hm(rows[0]['from'])}{hm(rows[-1]['to'])} "
f"(총 {span // 60}시간 {span % 60}분 · 이동 {move_sum}분 · 정거장 {len(rows)})", "",
"| | 시각 | 자리 | 장소 | 이동 | 체류 |", "|---|---|---|---|---|---|"]
for n, r in enumerate(rows, 1):
lines.append(f"| {n} | {hm(r['from'])}{hm(r['to'])} | {r['slot']} | {r['place']} | "
f"{r['move'] or ''}분 | {r['stay']}분 |")
lines.append("")
if bad:
fails.append((item["name"], bad))
lines += ["**확인이 필요한 것**", ""]
lines += [f"- `{code}` {msg}" for code, msg in bad]
lines.append("")
head = [f"## 결과 — {len(items) - len(fails)}/{len(items)} 검수완료", ""]
if fails:
head += ["| 테마 | 걸린 항목 |", "|---|---|"]
head += [f"| {n} | {', '.join(sorted({c for c, _ in b}))} |" for n, b in fails]
else:
head += ["**전부 통과.** 12개 항목 위반 0건."]
head.append("")
lines = lines[:8] + head + lines[8:]
(SP / "SCHEDULE.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"SCHEDULE.md · 검수완료 {len(items) - len(fails)}/{len(items)}")
for n, b in fails:
print(f" ⚠️ {n}")
for code, msg in b:
print(f" {code} {msg}")

View File

@ -161,6 +161,12 @@ WINDOW = {
"밤 산책": (18 * 60 + 30, 20 * 60),
}
DAY_ENDS_BY = 21 * 60
# ★ 끼니 사이 최소 간격 (2026-09-11 검수).
# 섬 코스에서 늦은 점심이 15:47 에 끝나고 저녁이 17:30 이었다 — 103분이다.
# 창(窓)만 지키면 통과한다: 늦은 점심은 15:00 까지, 저녁은 17:30 부터라 둘 다 합법인데
# 손님은 배가 안 꺼진 채 두 번째 상을 받는다. 창 밖에 이 규칙이 따로 필요하다.
MEAL_GAP = 180
MEAL_SLOTS = {"점심", "늦은 점심", "저녁"}
# 퇴실 시각. payload 의 check_out_time 과 같아야 한다 — 시간표가 규정을 어기면
# 사장님이 손님에게 설명할 수 없는 일정이 된다.
CHECK_OUT_BY = 11 * 60
@ -233,6 +239,17 @@ def _note(slot: str, place: str, kind: str) -> str | None:
return PLACES[place][4]
def _window_of(slot: str, last_meal_end: int | None):
"""그 자리의 도착 창. 끼니는 **앞 끼니가 끝난 뒤 MEAL_GAP** 이 지나야 연다."""
window = WINDOW.get(slot)
if not window:
return None
early, late = window
if slot in MEAL_SLOTS and last_meal_end is not None:
early = max(early, last_meal_end + MEAL_GAP)
return (early, late) if early <= late else None
def plan_day(kind: str, places: list[str], label: str, start: int, pace: float):
"""하루 하나를 시각까지 계산한다. 창을 못 맞추면 None.
@ -265,13 +282,16 @@ def plan_day(kind: str, places: list[str], label: str, start: int, pace: float):
clock = start
prev = BASE
last_meal_end = None
for index, row in enumerate(rows):
coords = (PLACES[row["place"]][0], PLACES[row["place"]][1])
# 하루의 1번은 머뭄이다 — 이미 그 자리에 있으니 이동시간이 없다.
row["move"] = 0 if index == 0 else move_minutes(prev, coords)
arrive = clock + row["move"]
window = WINDOW.get(row["slot"])
window = _window_of(row["slot"], last_meal_end)
if window is None and row["slot"] in WINDOW:
return None # 앞 끼니와 겹쳐 창이 닫혔다 — 이 조합은 포기한다
if window:
early, late = window
if arrive < early:
@ -301,6 +321,8 @@ def plan_day(kind: str, places: list[str], label: str, start: int, pace: float):
return plan_day_fixed(rows, start)
clock = arrive + row["stay"]
if row["slot"] in MEAL_SLOTS:
last_meal_end = clock
prev = coords
if clock > DAY_ENDS_BY:
@ -312,14 +334,17 @@ def plan_day_fixed(rows: list[dict], start: int):
"""체류시간을 고친 뒤 처음부터 다시 훑는다(앞 칸을 바꿨으니 뒤 시각이 전부 달라진다)."""
clock = start
prev = BASE
last_meal_end = None
for index, row in enumerate(rows):
coords = (PLACES[row["place"]][0], PLACES[row["place"]][1])
row["move"] = 0 if index == 0 else move_minutes(prev, coords)
arrive = clock + row["move"]
window = WINDOW.get(row["slot"])
if window and not (window[0] <= arrive <= window[1]):
window = _window_of(row["slot"], last_meal_end)
if row["slot"] in WINDOW and (window is None or not (window[0] <= arrive <= window[1])):
return None
clock = arrive + row["stay"]
if row["slot"] in MEAL_SLOTS:
last_meal_end = clock
prev = coords
if clock > DAY_ENDS_BY:
return None
@ -589,6 +614,28 @@ def audit(built: list[dict]) -> list[str]:
if clock > DAY_ENDS_BY:
flag(item, day, f"{clock // 60}:{clock % 60:02d} 종료 — 21시 초과")
# ⑮ 끼니 사이 최소 간격 (2026-09-11 검수에서 걸린 것)
# 창만 지키면 통과한다 — 늦은 점심 15:47 종료, 저녁 17:30 시작이 둘 다 합법이었다.
# 손님은 배가 안 꺼진 채 두 번째 상을 받는다.
walk = _minutes(day["startTime"])
last_meal = None
for sl, stop in zip(slots, day["stops"]):
walk += stop["moveMinutes"]
if sl in FOOD_SLOTS:
if last_meal is not None and walk - last_meal < MEAL_GAP:
flag(item, day, f"앞 끼니 끝나고 {walk - last_meal}분 만에 {sl}")
last_meal = walk + stop["minutes"]
walk += stop["minutes"]
# ⑯ 볼거리는 **가는 시간보다 오래 머문다**
# 끼니는 뺀다 — 밥집은 목적지가 아니라 돌아오는 길에 들르는 자리다.
# (섬에서 85분 달려와 55분 먹는 것은 이상하지 않다. 섬에 30분 있으면 이상하다.)
for sl, pl, stop in zip(slots, places, day["stops"]):
if pl == STAY or sl in FOOD_SLOTS:
continue
if stop["minutes"] < stop["moveMinutes"]:
flag(item, day, f"{pl}: 이동 {stop['moveMinutes']}분인데 체류 {stop['minutes']}")
# ⑨ 같은 날 같은 식당 두 번
meals = [p for sl, p in zip(slots, places) if sl in FOOD_SLOTS]
if len(meals) != len(set(meals)):
@ -631,4 +678,4 @@ for item in items:
f"{clock // 60:02d}:{clock % 60:02d} {len(day['stops'])}")
DST.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
print(f"\n테마 {len(items)}개 · 규칙 14종 위반 0건 · payload {DST.stat().st_size:,}B")
print(f"\n테마 {len(items)}개 · 규칙 16종 위반 0건 · payload {DST.stat().st_size:,}B")

File diff suppressed because one or more lines are too long