Community생산성 & 협업github.com

geekjourneyx/travel-guidebook

AI 에이전트 스킬: 병렬 에이전트와 Amap MCP를 활용한 리서치부터 인쇄까지, 아름답게 조판된 여행 가이드북 PDF를 생성합니다.

travel-guidebook란 무엇인가요?

이 스킬은 AI 에이전트(Claude Code, Cursor, Codex 등)가 완전한 형태의 여행 가이드북을 PDF로 생성할 수 있도록 설계된 종합적인 워크플로우입니다. 리서치, 경로 계획, 콘텐츠 작성, HTML 조판, PDF 내보내기 등 여행 가이드북 제작의 전 과정을 6단계(Stage 0-6)로 구성하여 자동화합니다. 특히, 'AI 일러스트레이션 제로, 이모지 제로, 순수 CDN 기반'이라는 디자인 철학 아래 Tabler Icons, 인라인 SVG, Claude의 디자인 미학을 결합하여 전문적인 편집 출판물 수준의 PDF를 생성하는 것이 특징입니다. Amap MCP(고덕 지도)와 통합되어 실제 거리, 소요 시간, 날씨, 주변 POI 데이터를 활용한 정밀한 경로 계획을 지원하며, MCP를 사용할 수 없을 때는 LLM 추정치로 대체하여 항상 가이드북을 생성할 수 있도록 설계되었습니다. 또한, '전담 에이전트 모드'를 통해 깨끗한 컨텍스트에서 일관된 스타일의 HTML을 작성하고, 병렬 리서치 에이전트를 활용하여 정보 수집 속도를 높입니다. 이 스킬은 Node.js, Playwright 환경을 자동으로 감지하고 설정하여 진입 장벽을 낮추었으며, HTML 체크포인트를 두어 사용자가 만족한 후에만 PDF를 내보내도록 하여 품질을 보장합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add geekjourneyx/travel-guidebook

Installed? Explore more 생산성 & 협업 skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Travel Guidebook Maker

리서치부터 완성까지 원스톱 여행 가이드북 생성 엔진 — AI 일러스트레이션 제로, 이모지 제로, 순수 CDN 도입. Tabler Icons + 인라인 SVG 장식 + Claude 디자인 미학을 통해 온도감과 디자인 감각이 있는 여행 가이드 PDF를 만듭니다.

디자인 철학

Monocle의 편집 감각 + DK의 시각적 스토리텔링 + Lonely Planet의 정보 깊이 + Claude의 따뜻한 미학

이것은 차가운 내비게이션 매뉴얼이 아닌, 온도가 있는 여행 동반자입니다. 양피지 같은 따뜻한 바탕 위에, Serif 폰트로 목적지의 이야기를 전하고, 아이콘 시스템으로 기능 정보를 표시하며, 장식 요소로 편집 출판물의 느낌을 연출합니다.

핵심 개념: 타이포그래피가 곧 디자인이다. AI 이미지 생성이나 사진에 의존하지 않고, 폰트 계층, 기능 색상 시스템, 인라인 SVG 장식, CSS 가상 요소를 통해 가이드북 자체가 디자인 감각을 갖추도록 합니다.


전체 프로세스

Stage 0 환경 준비 → Stage 1 요구 사항 확인
→ Stage 2 심층 리서치 [5개의 explore agent 병렬]
→ Stage 3 경로 설계
→ Stage 4 콘텐츠 작성 [전담 general-purpose agent]
→ Stage 5 HTML 전달 및 검사 → Stage 6 PDF 내보내기

Stage 0은 Node.js + Playwright 환경을 자동 감지합니다. Stage 2는 병렬 리서치로 정보 수집 속도를 높입니다. Stage 4는 전담 agent가 깨끗한 컨텍스트에서 HTML을 작성하여 일관성을 보장합니다. Stage 5는 HTML 체크포인트로, 사용자가 만족하면 Stage 6에서 PDF를 내보냅니다.


Stage 0: 환경 준비

가이드북 제작을 시작하기 전에 PDF 내보내기 환경이 준비되었는지 확인합니다.

다음 순서대로 항목을 하나씩 확인하며, 어느 단계에서든 실패하면 중단하고 사용자에게 알립니다.

1. Node.js

node --version
  • ✅ v18.x 이상 → 계속
  • ❌ 명령어 없음 → 중단, 설치 안내: https://nodejs.org/

2. package.json

ls package.json
  • ✅ 존재 → 계속
  • ❌ 없음 → npm init -y

3. Playwright

node -e "require('playwright')"
  • ✅ 오류 없음 → 계속
  • ❌ 오류 발생 → npm install playwright && npx playwright install chromium

4. html2pdf.mjs

scripts/html2pdf.mjs에 번들로 제공되며, Stage 6에서 작업 디렉토리로 복사합니다.

5. Amap Maps MCP (선택적 강화)

Amap MCP 도구 호출을 시도하여 사용 가능성을 확인합니다.

호출 maps_whether("{목적지 도시}")
  • ✅ 날씨 데이터 반환 → AMAP_AVAILABLE = true
  • ❌ 도구 없음 또는 오류 → AMAP_AVAILABLE = false

Amap MCP는 강화 레이어입니다 — 사용할 수 없어도 가이드북은 정상적으로 생성되며, 정확한 데이터만 LLM 추정치로 대체됩니다.

사용자 미구성 시 안내 (한 번만 표시하며, 프로세스를 차단하지 않음):

"💡 Amap Maps MCP가 구성되지 않았습니다. 가이드북은 정상적으로 생성되지만, 거리/교통/날씨 데이터는 추정치를 사용합니다. 정확한 데이터가 필요하면 MCP 구성에 @amap/amap-maps-mcp-server를 추가하세요."

환경 준비 확인

모든 검사를 통과한 후 출력:

"✅ 환경 준비 완료 (Node.js {버전} + Playwright + Chromium{고덕 사용 가능 시: + Amap Maps MCP}). 가이드북 제작을 시작합니다."


Stage 1: 요구 사항 확인

사용자에게 다음 매개변수를 확인합니다 (명령어에서 추론 가능한 것은 묻지 않고, 추론할 수 없는 것만 질문):

확인했습니다. 여행 가이드북을 제작하겠습니다. 다음 정보를 확인해 주세요:

  1. 경로 이름:「{명령어에서 추론}」,맞습니까?
  2. 여행 유형: 자동차 여행 / 도보 여행 / 도시 산책 / 혼합?
  3. 대상 독자: 심층 문화 여행 / 가벼운 휴식 여행 / 모험 도전 여행?
  4. 총 일수: {추론된 일수}일, 맞습니까?
  5. 개인 정보: 표지나 마지막에 개인/팀 정보를 추가해야 합니까?

수정 사항을 바로 답변해 주세요. 문제없으면 바로 시작하겠습니다.

빠른 모드: 사용자가 충분한 정보를 제공한 경우 확인을 건너뛰고 바로 실행합니다.

기본값: 여행 유형=자동차 여행, 대상 독자=심층 문화 여행, 일수=경로에 따라 추론, 개인 정보=없음.

스마트 라우팅

요구 사항 확인 후, 사용자 입력에 따라 시작 Stage 결정:

사용자 제공 내용이동설명
목적지/일수만Stage 2표준 전체 프로세스
기존 일정 파일 (Markdown/텍스트)Stage 3일정 읽어서 구조 추출, 리서치 건너뜀
기존 일정 + "확인됨/리서치 불필요"Stage 4바로 작성 및 조판
기존 HTML 가이드북Stage 5바로 검사, 수정 후 PDF 내보내기 가능

판단 기준: 사용자가 @파일명 참조를 첨부했는지, "일정 확인됨", "리서치 불필요" 등을 명시적으로 언급했는지 확인합니다. 불확실한 경우 기본적으로 전체 프로세스를 따르지만, "리서치를 수행할까요, 아니면 바로 작성을 시작할까요?"라고 능동적으로 물어봅니다.


Stage 2: 심층 리서치 (병렬 Sub-Agent)

여행 가이드북의 리서치는 실용 정보와 문화적 깊이를 동시에 다루어야 합니다. 병렬 explore agent를 사용하여 리서치 속도를 높입니다 — 각 방향마다 독립적인 agent가 동시에 출발하여 서로를 차단하지 않습니다.

병렬 리서치 아키텍처

주 Agent                         explore agent 풀 (병렬)
┌──────────┐                    ┌─────────────────────────┐
│ 5+1 agent  │  ── background ──→│ research-transport       │
│ 구성       │  ── background ──→│ research-attractions     │
│ 프롬프트    │  ── background ──→│ research-food            │
│           │  ── background ──→│ research-culture         │
│           │  ── background ──→│ research-practical       │
│           │  ── background ──→│ research-spatial (고덕)   │
│           │                    └─────────────────────────┘
│ 알림 대기   │  ←── 자동 알림 ───  (각 agent 완료 후)
│ 수집 및 병합 │  ── read_agent ──→  각 agent 결과 획득
│ 보고서 출력  │
└──────────┘

research-spatial은 AMAP_AVAILABLE = true인 경우에만 시작됩니다. 사용할 수 없으면 5개의 agent만 시작합니다.

Agent 분담

task 도구 사용, agent_type: "explore", mode: "background", 5+1개 agent 동시 시작:

Agent 이름리서치 방향검색 키워드 예시 (중영 혼합)
research-transport교통 경로"{출발지}에서{목적지}까지 고속철/자동차 시간 가격", "{destination} transport"
research-attractions핵심 명소"{목적지} 꼭 가봐야 할 명소 입장료 개장 시간 TOP10", "{destination} attractions"
research-food현지 음식"{목적지} 특색 음식 추천 레스토랑 맛집 거리 1인당 가격", "{destination} local food"
research-culture문화 역사"{목적지} 역사 문화典故 민속 방언", "{destination} history culture"
research-practical실용 정보"{목적지} {월} 날씨 예산 안전 주의사항", "{destination} travel tips"

자동차 여행의 경우 7번째 agent research-road 추가 (도로 상태, 주유소, 고도 변화).

Amap 공간 데이터 Agent (AMAP_AVAILABLE = true인 경우)

6번째 agent research-spatial, 전담 Amap 지도 데이터 수집:

당신은 공간 데이터 수집 전문가입니다. Amap Maps MCP 도구를 사용하여 다음 데이터를 수집하세요.

목적지: {목적지}
알려진 명소 목록: {요구 사항 확인에서 추출한 모든 명소 이름}

## 작업 1: 명소 POI 데이터
각 명소에 대해 maps_text_search("{명소명}")을 호출하여 다음을 추출:
- POI ID, 이름, 전체 주소, 위경도, 평점, 영업 시간, 연락처 전화번호

## 작업 2: 주변 발견
각 핵심 명소(매일의 주요 명소)에 대해 maps_around_search 호출:
- 키워드="레스토랑|간식", location={명소 좌표}, radius=1000 → 주변 레스토랑 top 5
- 키워드="편의점|약국", location={명소 좌표}, radius=500 → 긴급 시설

## 작업 3: 일기 예보
maps_whether("{목적지 도시 이름 또는 adcode}")

## 작업 4: 지오코딩
모든 지명에 대해 maps_gep을 호출하여 정확한 좌표를 얻어 Stage 3 경로 계획에 사용

## 출력 형식
### 명소 POI 요약
| 명소 | 주소 | 위경도 | 평점 | 영업 시간 |
|------|------|--------|------|---------|
| ... | ... | ... | ... | ... |

### 주변 발견
#### {명소명} 주변
| 이름 | 유형 | 거리 | 평점 |
|------|------|------|------|
| ... | ... | ... | ... |

### 일기 예보
| 날짜 | 날씨 | 온도 | 풍력 |
|------|------|------|------|
| ... | ... | ... | ... |

자동차 여행의 경우 7번째 agent research-road 추가 (도로 상태, 주유소, 고도 변화).

Agent Prompt 템플릿

각 agent의 프롬프트는 다음 구조를 따릅니다:

당신은 여행 리서치 전문가로, 【{방향}】 리서치를 담당합니다.

## 작업 매개변수
- 목적지: {목적지}
- 출발지: {출발지}
- 날짜: {구체적인 날짜}
- 일수: {N}일
- 여행 유형: {자동차/고속철/혼합}

## 리서치 요구 사항
1. bash를 사용하여 curl 또는 web_fetch를 실행하여 다음 URL을 획득 (각각 시도, 실패 시 건너뜀):
   - {사전 설정된 URL 목록, 3-5개의 관련 웹사이트}
2. 각 정보 출처에서 핵심 데이터 포인트 추출
3. 모든 URL이 실패하면 기존 지식을 바탕으로 정리하고 "⚠️ 모델 지식"이라고 표시

## 출력 형식 (엄격히 준수)
### {방향명}
#### 핵심 발견
- 발견1: {구체적인 데이터} (출처: {URL})
- 발견2: ...

#### 추천 목록
| 이름 | 세부 정보 | 가격 | 비고 |
|------|------|------|------|
| ... | ... | ... | ... |

#### 정보 출처
- {URL1}
- {URL2}

#### 데이터 시효
- 위 정보는 {현재 날짜}에 획득되었습니다. 여행 전에 가격과 개장 시간을 재확인하는 것이 좋습니다.

결과 수집 및 병합

모든 agent 완료 후:

  1. read_agent를 하나씩 호출하여 결과 획득
  2. 통합 리서치 보고서로 병합, 방향별로 챕터 구성
  3. 각 데이터 포인트의 출처 표시 (URL 또는 "모델 지식")
  4. 특정 agent가 실패하면 주 agent가 해당 방향의 LLM 지식으로 보충

대체 전략

시나리오처리 방식
task 도구 사용 불가직렬 모드로 대체: 주 agent가 방향별로 web_fetch 실행
일부 agent 시간 초과/실패주 agent가 LLM 지식으로 실패한 방향 보충
research-spatial 실패거리/시간을 LLM 추정치로 사용, "약" 접두사 표시
완전히 네트워크 불가오프라인 모드: 모두 LLM 지식 기반, "⚠️ 여행 전 확인 권장" 표시

리서치 품질 요구 사항

  • 병렬 모드: 각 agent당 최소 3개의 유효 정보 출처, 총 ≥ 15개
  • 직렬 모드: 총 정보 출처 수 ≥ 20개 (≤3일 단거리: ≥ 10개)
  • 오프라인 모드: 가능한 한 풍부하게, 데이터 시효 불확실성 표시
  • 우선 순위: 공식 관광 웹사이트, 베테랑 여행 블로거, 현지 미디어, 전문 포럼
  • 가격 정보는 시효성을 명시해야 함
  • 핵심 사실은 최소 2개의 독립적인 정보 출처로 교차 검증

Stage 3: 경로 설계

리서치 결과를 기반으로 일별 일정 구조를 생성합니다. Amap 공간 데이터를 사용할 수 있는 경우 실제 경로 계획을 LLM 추정치 대신 사용합니다.

Amap 경로 계획 (AMAP_AVAILABLE = true인 경우)

Stage 2의 research-spatial agent가 모든 명소의 정확한 좌표를 제공했습니다. 이를 기반으로 주 agent가 Amap 경로 계획 API를 호출합니다:

일별 일정의 연속적인 명소 쌍에 대해 여행 유형에 따라 API 선택:

여행 유형   │  API                                  │  설명
──────────┼──────────────────────────────────────┼──────────
자동차 여행  │  maps_direction_driving(A좌표, B좌표)  │  거리/시간/통행료
도시 산책   │  maps_direction_walking (≤3km)         │  도보 거리/시간
           |  maps_direction_transit_integrated (>3km)|  지하철/버스 경로
자전거 구간  │  maps_bicycling                        │  자전거 경로/거리
도시 간 이동 │  maps_direction_transit_integrated      │  기차/버스 경로
모든 모드   │  maps_distance                         │  일일 총 거리 확인

Amap을 사용할 수 없는 경우 LLM 지식으로 거리와 시간을 추정하고, 가이드북에 "약" 접두사로 표시합니다.

Stage 3.1: 일정 가능성 게이트 (Feasibility Gate)

제1원칙: 일정은 물리적 제약 하의 계획이지, 명소의 자유로운 조합이 아닙니다.
일별 일정을 작성하기 전에 다음 검증을 통과해야 합니다 — 통과하지 못하면 강제로 분할하거나 명소를 삭제합니다.

규칙 1: 당일 왕복 가능성 공식

사용 가능한 총 시간 = 출발 시간 ~ 복귀 시간 (일반적으로 12시간, 고원 지역 10시간)

검증 공식:
  출발지 → 명소A (편도 소요 시간) × 2          ← 왕복 교통
  + 각 명소 관람 시간 합계
  + 명소 간 교통 시간 합계
  + 완충 시간 (1시간)
  ≤ 사용 가능한 총 시간

불만족 시 → 반드시 여러 날로 분할하거나 가장 먼 명소 삭제

계산 도구 (우선 순위):

  • AMAP_AVAILABLE = true → maps_direction_driving / maps_distance 호출로 실제 소요 시간 획득
  • AMAP_AVAILABLE = false → LLM 지식으로 추정, 가이드북에 "약" 표시

규칙 2: 도시 간 명소 강제 분리

출발지에서 편도 거리강제 규칙
≤ 80km다른 명소와 같은 날 가능
80–150km같은 날에는 해당 명소만 가능, 다른 목적지 없음
> 150km강제로 독립된 하루로 만들거나, 경유지 숙박安排

전형적인 함정: 라싸 출발, 양줘용춰 (100km)는 단독 당일 여행 가능; 시가체 타쉬룬포 사원/바이쥬 사원 (280km)은 절대 라싸 명소나 양호와 같은 날 묶을 수 없음.

규칙 3: 특수 목적지 제약

고원 지역 (해발 3500m+) :

도착 후 일수허용 활동 범위금지
Day 1호텔 주변 도보, ≤1시간모든 명소 관람
Day 2시내 평탄한 명소, ≤3시간해발 4000m+ 명소
Day 3+정상적인 시내 관람해발 4500m+는 Day 4 이후 권장
Day 4+고해발 지역 방문 가능 (양호 4441m)—
Day 5+매우 높은 해발 시도 가능 (나무초 4718m)여전히 산소 필요

강제 실행: 고원 일정의 Day 1에는 유료 명소를 배치하지 않아야 하며, 위반 시 자동으로 명소를 하루 뒤로 이동합니다.

규칙 4: 생성 후 검증 체크리스트

일별 일정 초안이 생성된 후, 하나씩 확인해야 합니다:

□ 당일 총 거리 (왕복)가 가능한 범위 내에 있는가?
□ 모든 명소가 동일한 합리적인 지역 내에 있는가? (여러 도시를 넘을 수 없음)
□ 암묵적인 "장거리 점프"가 없는가? (예: A→B→C가 겉보기에는 인접해 보이지만 실제로는 우회)
□ 고원 일정: 해발 적응 규칙을 위반하지 않았는가?
□ 차량/자동차 당일 여행: 충분한 관광/체류 시간이 있는가 (≥2시간)?
□ 귀환 시간이 충분히 남아 있는가? (어두워지기 전에 복귀)

항목 중 하나라도 통과하지 못하면 → 빨간색 경고, 해당 일정을 다시 계획한 후에만 Stage 4로 진행 가능합니다.


리듬 디자인

  • 긴장과 이완: 장거리 운전일 + 심층 관람일 교체
  • 클라이맥스 디자인: 가장 핵심적인 목적지는 일정 중간 (Day 3-5)에 배치
  • 완충 시간: 3-4일마다 "자유일" 또는 "휴식일" 편성
  • 감정 곡선: 출발 흥분 → 적응기 → 클라이맥스 → 여운 → 이별 아쉬움

일별 일정 구조

Day X: [출발지] → [도착지]
├─ 거리: XXkm (Amap 실측 / LLM 추정)
├─ 예상 소요 시간: X시간 (관람 시간 포함)
├─ 교통 방안 (Amap 사용 가능 시):
│   ├─ 명소A→명소B: 도보 12분 / 0.9km
│   ├─ 명소B→명소C: 지하철 2호선 3정거장 / 15분
│   └─ 명소C→호텔: 버스 537번 / 25분
├─ 날씨 (Amap 사용 가능 시): ☁️ 구름 26°C
├─ 오늘의 하이라이트: 한 줄 요약
├─ 필수 정차 지점: 2-3개 선별 (Amap 평점 포함)
├─ 주변 발견 (Amap 사용 가능 시): 명소 주변 고평점 레스토랑/카페
├─ 음식 추천: 1-2개
├─ 숙박 추천: 1-2개
└─ 팁: 날씨 조언 + 실제 교통 조언 포함

"Amap 사용 가능 시"로 표시된 항목은 AMAP_AVAILABLE = false인 경우 생략하거나 LLM 추정치로 대체합니다.

사용자 확인

일정 구조를 표시하여 확인 또는 수정을 받고, 확인 후 Stage 4로 진행합니다.

빠른 모드: 사용자가 "바로 작성, 확인 불필요"를 요청한 경우 건너뜁니다.


Stage 4: 콘텐츠 작성 및 조판

이것은 가이드북의 핵심 단계입니다 — 리서치와 구조를 디자인이 뛰어난 HTML 가이드북으로 변환합니다.

실행 모드 선택

사용 가능한 도구에 따라 최적의 모드를 자동 선택합니다:

조건모드설명
task 도구 사용 가능전담 Agent 모드 (권장)1개의 general-purpose agent를 시작하여 깨끗한 컨텍스트에서 모든 HTML 작성
task 사용 불가주 Agent 직집 모드주 agent가 heredoc으로 분할 작성 (전통적인 방식)

전담 Agent 모드 (권장)

핵심 장점: HTML 작성 agent는 깨끗한 컨텍스트를 가짐 — 리서치 과정, 대화 기록, 경로 논의의 노이즈 없음. 첫 줄부터 마지막 줄까지 스타일이 완전히 통일됨.

1개의 general-purpose agent (mode: "background")를 시작하고, 다음 내용을 프롬프트에 완전히 전달합니다:

당신은 여행 가이드북 HTML 작성 전문가입니다. 완전한 단일 파일 HTML 가이드북을 생성하세요.

## 가이드북 매개변수
- 경로 이름: {이름}
- 파일 이름: {이름}_guidebook.html
- 여행 날짜: {날짜}
- 일수: {N}일
- 여행 유형: {유형}

## CSS 규격 (references/layout-css.md 내용을 완전히 복사)
{layout-css.md 전체}

## 챕터 템플릿 (references/chapter-templates.md 내용을 완전히 복사)
{chapter-templates.md 전체}

## 리서치 데이터 (Stage 2 병합 보고서)
{리서치 보고서 전체}

## 경로 구조 (Stage 3 확인 버전)
{일별 일정 구조}

## 작성 스타일
세 가지 요구 사항 기반:
- 방향 (Where) — 정확하고 명확하게: 지명, 방향, 거리/시간 정확
- 결정 (What) — 사용자를 대신하여 필터링: 매일 2-3개의 필수 정차 지점
- 감정 (Why) — 의미 부여: 역사 이야기와 현지인의 시각을 통합

## 기술 요구 사항
1. heredoc을 사용하여 분할 작성 (cat > 첫 번째, cat >> 이후), 작은따옴표 << 'HTMLEOF'
2. ¥은 &#165;로, —은 &#8212;로, →은 &#8594;로, °은 &#176;로 대체
3. 각 배치 작성 후 wc -c로 파일 증가 확인
4. 총 배치 수 3-5회, 논리적 단락으로 분할
5. 모든 CSS는 <style>에 내장, 모든 SVG는 인라인, 외부 이미지 없음
6. 마지막 배치에는 반드시 </body></html> 닫는 태그 포함

주 agent가 기다리는 동안: 다른 가벼운 작업을 수행하거나 사용자에게 "HTML을 생성 중입니다. 약 2-3분 소요됩니다."라고 알릴 수 있습니다.

Agent 완료 후:

  1. read_agent로 결과를 획득하고 HTML 파일이 생성되었는지 확인
  2. wc -c로 파일 크기 검증 (5일 일정 시 50-80KB)
  3. Stage 5로 진행

주 Agent 직집 모드 (대체)

task 도구를 사용할 수 없는 경우, 주 agent가 직접 heredoc을 사용하여 분할 작성합니다.

챕터 구조

가이드북은 다섯 부분 구조를 채택합니다. references/chapter-templates.md를 읽어 각 챕터의 완전한 HTML 템플릿을 확인하세요:

  1. 출발 전: 표지 / 여행 개요 / 준비 사항
  2. 일별 일정: Day-by-Day (핵심 본체) — 일정 카드, 경로 설명, 필수 정차 지점, 음식, 숙박, 팁, 메모 공간
  3. 목적지 심층: 2-3개의 중요한 목적지에 대한 심층 소개
  4. 실용 부록: 긴급 연락처, 유용한 언어, 비용 내역, 추천 플레이리스트
  5. 뒷표지: 여행 명언 + 개인 정보 + 여행 소감 공간

조판 규격

가이드북 시각 디자인은 Claude의 따뜻한 색조 미학을 계승합니다. references/layout-css.md를 읽어 완전한 CSS 규격을 확인하세요. 다음을 포함합니다:

  • 외부 리소스 (Google Fonts + Tabler Icons CDN만)
  • 페이지 레이아웃 (A4, max-width 680px)
  • 폰트 시스템 (Noto Serif SC / Noto Sans SC / JetBrains Mono)
  • 색상 구성 (Parchment 양피지 바탕 + Terracotta 적토색 + 기능 색상 시스템)
  • 장식 요소 (나침반, 구분선, DAY 배지, 카드 모서리 표식, 첫 글자 장식)
  • 페이지 나누기 제어 (표지 단독, Day 새 페이지, 카드 분할 금지)
  • 인쇄 적응 (따뜻한 색조 배경 유지)

작성 스타일

세 가지 요구 사항 기반 작성:

  • 방향 (Where) — 정확하고 명확하게: 지명, 방향, 거리/시간은 반드시 정확해야 하며, 구체적인 설명 사용 ("왼쪽", "앞으로 200미터")
  • 결정 (What) — 사용자를 대신하여 필터링: 각 목적지마다 2-3개의 필수 정차 지점만 추천, "필수/선택/시간이 있으면 가볼 만함"으로 우선 순위 표시
  • 감정 (Why) — 의미 부여: 각 장소에 대해 "왜 가볼 만한지" 설명, 역사 이야기와 현지인의 시각을 통합, 문학적 언어로 풍경 묘사

감정 강화 작성 (고덕 데이터 기반)

Amap 공간 데이터를 사용할 수 있을 때, 다음 네 가지 감정 강화 모드를 적용:

1. 거리 서사 — 정확한 거리를 감각적인 경험으로 변환:

  • ≤500m → "몇 분 거리" +途中에 볼/냄새/들을 수 있는 것
  • 500m-2km → "산책 거리" +沿途 풍경 설명
  • >2km → 교통 조언 + 창밖 풍경
  • 예시: "황학루 남문을 나와 왼쪽으로 돌아 Wuluo Road를 따라 600미터 — 노래 한 곡 정도의 시간 — 후부샹에 도착합니다."

2. 주변惊喜 — 고덕이 발견한 고평점 POI 제시 (LLM이 모를 수 있는 새 가게/작은 가게):

  • "💡 여행 발견" 카드로 제시
  • 포함: 이름, 거리, 평점, 추천 이유 한 줄

3. 시간 인식 — 날씨 + 거리 + 시간대 = 구체적인 경험 조언:

  • 예시: "오늘 26°C 구름 — 창장 대교를 걷기에 완벽한 날씨입니다. 교량 길이 1.6km, 느긋하게 걸으면 약 22분 소요. 16:00에 출발하여 다리 중앙에 도착할 무렵 일몰을 맞이하는 것을 추천합니다."

4. 안심감 — 일일 팁에 주변 편의 시설 포함:

  • 예시: "오늘 숙소에서 200m 이내에 FamilyMart 편의점 (24시간), 가장 가까운 약국은 400m 떨어진 Wuluo Road에 있습니다."

Amap을 사용할 수 없는 경우, 이 네 가지 모드는 자동으로 생략됩니다 — 가이드북은 여전히 완전한 문화 서사와 LLM 추정 데이터를 가지고 있습니다.

HTML 생성 (heredoc 분할 전략)

완전한 단일 HTML 파일 생성, 모든 CSS는 <style>에 내장, 모든 SVG 장식은 인라인, 외부 이미지 없음.

다음 heredoc 전략은 전담 Agent의 내부 실행과 주 Agent 직집 대체 모드 모두에 적용됩니다.

대용량 파일 쓰기 전략

가이드북 HTML은 일반적으로 50-80KB (5일 일정 약 30페이지)로, write/create 도구의 단일 상한을 초과합니다. heredoc 분할 추가 전략 사용:

# 1차: HTML head + 전체 CSS (<style> 태그)
cat > {파일명}_guidebook.html << 'HTMLEOF'
<!DOCTYPE html>
<html lang="ko">
<head>...</head>
<style>/* 모든 CSS, references/layout-css.md 참조 */</style>
<body>
HTMLEOF

# 2차: 표지 + 개요 + 준비 사항
cat >> {파일명}_guidebook.html << 'HTMLEOF'
<div class="cover">...</div>
<div class="overview">...</div>
<div class="preparation">...</div>
HTMLEOF

# 3-N차: 일별 일정 (하루에 한 번 또는 이틀에 한 번)
cat >> {파일명}_guidebook.html << 'HTMLEOF'
<div class="day-chapter">...</div>
HTMLEOF

# 마지막 차: 심층 여행 + 부록 + 뒷표지 + 닫는 태그
cat >> {파일명}_guidebook.html << 'HTMLEOF'
<div class="deep-dive">...</div>
<div class="appendix">...</div>
<div class="back-cover">...</div>
</body></html>
HTMLEOF

핵심 주의사항:

  • 작은따옴표 heredoc (<< 'HTMLEOF')을 사용하여 셸 변수 확장 방지
  • ¥ 기호는 heredoc에서 &#165;로 대체하여 인코딩 문제 방지
  • 각 배치 작성 후 wc -c로 파일이 정상적으로 증가하는지 확인
  • 총 배치 수는 3-5회로 제어하고 논리적 단락으로 분할 (HTML 태그 중간에서 끊지 않음)

Stage 5: HTML 전달 및 검사

전달 내용

  1. HTML 파일: {경로명}_guidebook.html (단일 파일, 외부 의존성 없음)
  2. 작업 보고서: 제작 과정 기록 (템플릿은 references/report-template.md 참조)

HTML 체크포인트

HTML 완료 후, 사용자가 먼저 확인하도록 해야 하며, 바로 PDF로 넘어갈 수 없습니다:

"HTML 가이드북이 생성되었습니다: {파일명}_guidebook.html. 브라우저에서 열어 내용과 조판을 확인해 주세요. 만족스러우면 알려 주시면 PDF를 내보내겠습니다. 수정이 필요하면 어디를 바꿔야 할지 알려 주세요."

  • 사용자가 "OK / 만족 / PDF 내보내기" → Stage 6으로 진행
  • 사용자가 "xxx 수정" → Stage 4로 돌아가 수정 후 다시 확인 요청

Stage 6: PDF 내보내기

사용자가 Stage 5에서 HTML에 만족한다고 확인한 후에만 실행 가능합니다.

실행 단계

1. 내보내기 스크립트 준비

작업 디렉토리에 html2pdf.mjs가 있는지 확인합니다. 찾는 방법:

# 현재 디렉토리 우선 확인
ls html2pdf.mjs 2>/dev/null || \
  # skill 디렉토리에서 번들된 스크립트 찾기
  find ~/.agents/skills/travel-guidebook -name "html2pdf.mjs" 2>/dev/null | head -1 | xargs -I{} cp {} ./html2pdf.mjs || \
  find . -path "*/travel-guidebook/scripts/html2pdf.mjs" 2>/dev/null | head -1 | xargs -I{} cp {} ./html2pdf.mjs

여전히 찾을 수 없는 경우, 다음 최소 스크립트로 생성합니다:

// html2pdf.mjs — Playwright A4 PDF export
import { chromium } from 'playwright';
import { resolve } from 'path';
const html = resolve(process.argv[2]);
const pdf = html.replace(/\.html$/, '.pdf');
const b = await chromium.launch();
const p = await b.newPage();
await p.goto('file://' + html, { waitUntil: 'networkidle' });
await p.waitForTimeout(2000);
await p.pdf({ path: pdf, format: 'A4', margin: { top: '2cm', right: '1.8cm', bottom: '2.5cm', left: '1.8cm' }, printBackground: true });
await b.close();
console.log('PDF saved:', pdf);

2. 내보내기 실행

node html2pdf.mjs {파일명}_guidebook.html

3. 검증 및 전달

PDF 존재 여부와 크기를 확인하고 사용자에게 열어보도록 안내:

"✅ PDF 가이드북이 내보내졌습니다: {파일명}_guidebook.pdf ({페이지수}페이지, {파일크기})."

PDF 매개변수

매개변수값설명
용지A4표준 인쇄 크기
위쪽 여백2cm
아래쪽 여백2.5cm페이지 번호 공간 확보
좌우 여백1.8cm
바닥글중앙 페이지 번호9pt JetBrains Mono
대기 전략networkidle + 2sCDN 리소스 로딩 보장
배경printBackground: true양피지 따뜻한 색상 텍스처 유지

대체 방안

Playwright 실패 시 브라우저 수동 인쇄 유도: Chrome/Edge에서 HTML 열기 → Cmd/Ctrl+P → 다른 이름으로 PDF 저장

관련 스킬