# 영종도 에어비앤비 주간 리서치 스킬 (Firecrawl MCP)
---
name: airbnb-research
description: 매주 영종도 커플 숙소 시장을 리서치하여 리뷰 수집 → 문제 분석 → 오퍼 설계 → 바이럴 전략 → 경쟁사 분석을 자동화하고, 결과를 MD 파일과 React 컴포넌트로 저장하는 스킬. "에어비앤비 리서치 해줘", "영종도 숙소 분석 해줘", "airbnb 리서치", "airbnb.tsx 업데이트" 같은 요청 시 사용.
---
## 0. Firecrawl MCP 사전 확인 (필수)
**실행 전 반드시 확인:**
Firecrawl MCP가 연결되어 있지 않으면 스크래핑이 불가능합니다.
```
확인 방법: /mcp 명령으로 firecrawl 상태 확인
연결 안 된 경우: /mcp 로 reconnect 후 재시도
```
Firecrawl 도구를 호출하기 전에 `ToolSearch`로 스키마를 로드하세요:
```
ToolSearch query: "select:mcp__firecrawl__firecrawl_search,mcp__firecrawl__firecrawl_scrape,mcp__firecrawl__firecrawl_map"
```
도구 호출이 실패하거나 응답이 없으면 — **즉시 중단하고 사용자에게 `/mcp` 로 Firecrawl을 reconnect하도록 안내하세요.** 절대 mock 데이터를 사용하지 마세요.
---
## 1. 실행 순서 개요
```
STEP 1 → Airbnb 리스팅 검색 (firecrawl_search × 3 병렬)
STEP 2 → 상위 숙소 5곳 리뷰 스크래핑 (firecrawl_scrape × 5 순차)
STEP 3 → 중간 저장: docs/airbnb-yeongjonge-YYYY-MM-DD.md
STEP 4 → 문제 분석: 긴급도 + WTP 점수화
STEP 5 → 고전환 오퍼 5개 설계
STEP 6 → 바이럴 콘텐츠 전략 (훅 20개 + SPICE 구조)
STEP 7 → 경쟁사 5개 분석 + 시장 장악 전략
STEP 8 → 전체 세션 MD 저장: docs/session-YYYY-MM-DD.md
STEP 9 → React 컴포넌트 생성: src/components/Trends/airbnb.tsx
```
---
## 2. STEP 1 — Airbnb 리스팅 검색
**병렬로 3개 검색 실행:**
```
Query 1: "영종도 커플 오션뷰 숙소 에어비앤비" site:airbnb.co.kr
Query 2: "인천 중구 2인 스테이 오션뷰 airbnb" site:airbnb.co.kr
Query 3: "영종도 호캉스 커플 베스트 숙소 후기"
```
`firecrawl_search` 파라미터:
```json
{
"query": "...",
"limit": 8,
"lang": "ko",
"country": "kr"
}
```
상위 결과에서 `/rooms/` 경로를 포함한 URL 5개를 선별합니다.
커플 특화, 오션뷰, 2인 키워드가 포함된 리스팅을 우선합니다.
---
## 3. STEP 2 — 리뷰 스크래핑 (숙소 5곳)
각 숙소 URL에 대해 `firecrawl_scrape` 실행:
```json
{
"url": "https://www.airbnb.co.kr/rooms/XXXXXXXXX",
"formats": ["markdown"],
"actions": [{"type": "wait", "milliseconds": 5000}],
"proxy": "stealth",
"headers": {
"Accept-Language": "ko-KR,ko;q=0.9",
"X-Forwarded-For": "211.36.140.1"
}
}
```
**JSON 형식이 리뷰를 반환하지 않는 경우**: `formats: ["markdown"]`으로 전환하여 페이지 전체 텍스트에서 리뷰를 추출합니다. Airbnb는 SPA이므로 `waitFor: 5000`이 필수입니다.
각 숙소에서 추출할 정보:
- 숙소명, 평점, 후기 수, 유형, URL
- 실제 후기 텍스트 최소 5개 (별점 3~5점 혼합)
- 키워드 요약 (칭찬 / 불만 / 기대 초과 / 재방문 의향)
---
## 4. STEP 3 — 중간 저장: 리뷰 MD 파일
**파일 경로:** `docs/airbnb-yeongjonge-YYYY-MM-DD.md`
형식은 아래를 따릅니다:
```markdown
# 영종도 에어비앤비 커플 오션스테이 리뷰 — YYYY-MM-DD
> 검색어: 인천 / 영종도 / 중구 / 오션스테이 / 커플 / 2인
---
## 1. [숙소명]
- **URL**: https://www.airbnb.co.kr/rooms/XXXXXXXXX
- **평점**: ⭐X.XX | **후기 수**: N개 | **유형**: 아파트/원룸/투룸
- **태그**: #커플 #오션뷰 #...
### 리뷰
| 후기자 | 별점 | 내용 |
|--------|------|------|
| 이름 | ⭐5 | "후기 내용..." |
| ... | ... | ... |
**키워드 요약:** 칭찬: `뷰`, `청결` / 불만: `방음`, `청소의무` / 기대 초과: `호스트 친절` / 재방문: O
---
```
**숙소 5곳 완료 후 즉시 파일을 저장합니다. (Write 도구 사용)**
마지막에 종합 인사이트 테이블 추가:
```markdown
## 종합 인사이트
| 항목 | 내용 |
|------|------|
| 평균 평점 | X.XX |
| 가장 많은 칭찬 | ... |
| 가장 많은 불만 | ... |
| 업계 공통 문제 | ... |
| 기회 포인트 | ... |
```
---
## 5. STEP 4 — 문제 분석
리뷰 MD를 바탕으로 숙소 문제 TOP 10을 도출합니다.
**점수화 기준:**
| 기호 | 의미 |
|------|------|
| 🔴 | 리뷰에서 실제 불평 등장 |
| 🚀 | 빠르게 커지는 니즈 (OTT, 시간 유연성 등) |
| 긴급도 | 투숙 중 즉각 불쾌감 (1~10) |
| WTP | 해결 시 기꺼이 돈 낼 의향 (1~10) |
**출력 형식:**
```markdown
| # | 문제 | 긴급도 | WTP | 신호 |
|---|------|:------:|:---:|------|
| 1 | ... | 9 | 9 | 🔴 🚀 |
...
```
우선순위 매트릭스도 포함:
```
긴급도 높음 + WTP 높음 → 즉시 해결 가치
긴급도 보통 + WTP 높음 → 선점 기회
실제 별점 깎는 문제 → 리스크 관리 필요
```
---
## 6. STEP 5 — 고전환 오퍼 5개
긴급도 × WTP가 높은 상위 5개 문제에 대해 각각:
```markdown
### OFFER N — "[오퍼 이름]"
**문제: ...** (긴급 X / WTP X)
**🎯 이상적인 고객**
| 항목 | 정의 |
|------|------|
| 인구통계 | 나이, 직업, 여행 목적 |
| 심리 | "..." (내면의 말) |
| 핵심 욕구 | ... |
**💎 가치 제안**
헤드라인 + 2~3줄 설명
**💰 가격 전략**
| 티어 | 내용 | 가격 |
|------|------|------|
**🛡️ 보상 + 리스크 제거**
- 조건 → 보상
**🏆 경쟁사보다 나은 이유**
| | 에어비앤비 | 호텔 | 이 오퍼 |
|--|--|--|--|
```
---
## 7. STEP 6 — 바이럴 콘텐츠 전략
### 고전환 훅 20개
감정 유형별로 분류:
- 🔴 공포 (Fear) — 4개
- 💢 분노 (Outrage) — 4개
- 🧠 호기심 (Curiosity) — 4개
- 👑 지위 (Status) — 3개
- 💔 공감 (Empathy) — 3개
- ⚡ 반전 (Reframe) — 2개
### 감정 트리거 맵
```
감정 → 트리거 메시지 → 반응 행동 (저장/공유/클릭/댓글)
```
### SPICE 바이럴 구조
S(Stop) → P(Pain) → I(Insight) → C(Claim) → E(Engage) 형식으로 3개 예시 작성.
### 플랫폼별 전략
인스타그램 / 틱톡 / 네이버 블로그 / 카카오 오픈채팅 / 유튜브 쇼츠
### 콘텐츠 반복 캘린더
요일별 감정 유형 배분 (월~일)
---
## 8. STEP 7 — 경쟁사 5개 분석
Firecrawl로 경쟁사 현황을 검색합니다 (병렬 3개):
```
Query A: "인스파이어 엔터테인먼트 리조트 영종도 커플 후기 2025"
Query B: "파라다이스시티 인천 커플 호캉스 후기"
Query C: "야놀자 여기어때 영종도 오션뷰 숙소 추천"
```
각 경쟁사 분석 형식:
```markdown
### 경쟁사 N — [이름]
| 항목 | 내용 |
|------|------|
| 잘하는 것 | ... |
| 약한 부분 | ... |
| 놓치고 있는 고객층 | ... |
| 포지셔닝 공백 | ... |
```
포지셔닝 맵 (가격 축 × 커플 큐레이션 축) 텍스트로 시각화.
**시장 장악 5단계 전략:**
1. 포지셔닝 선점
2. 유통 채널 구축
3. 호스트 파트너십
4. 콘텐츠 장악
5. 가격 전략
12개월 로드맵 포함.
---
## 9. STEP 8 — 전체 세션 MD 저장
**파일 경로:** `docs/session-YYYY-MM-DD.md`
```markdown
# 세션 기록 — YYYY-MM-DD
> 주제: 영종도 에어비앤비 리뷰 수집 → 문제 분석 → 오퍼 설계 → 바이럴 전략 → 경쟁사 분석
---
## Q1. 영종도 에어비앤비 리뷰 수집
[수집 숙소 테이블 + 참조 파일 경로]
## Q2. 숙소 문제 분석 및 점수화
[문제 매트릭스 전체]
## Q3. 고전환 오퍼 5개
[오퍼 1~5 전체]
## Q4. 바이럴 콘텐츠 전략
[훅 20개 + 감정 트리거 + SPICE + 캘린더]
## Q5. 경쟁사 5개 분석 및 시장 장악 전략
[경쟁사 분석 전체 + 로드맵]
---
*생성일: YYYY-MM-DD | 도구: Claude + Firecrawl MCP | 데이터: airbnb.co.kr 실시간 스크래핑*
```
**Write 도구로 즉시 저장합니다.**
---
## 10. STEP 9 — React 컴포넌트 생성
**출력 파일:** `src/components/Trends/airbnb.tsx` (덮어쓰기)
기본 export 이름: `AirbnbResearch`
```ts
// App.tsx import:
import AirbnbResearch from "./components/Trends/airbnb";
```
### Fashion.tsx 스타일 지침
`Fashion.tsx`와 동일한 시각적 언어를 사용합니다:
- **배경**: `bg-white min-h-screen font-sans text-slate-900`
- **히어로**: 검은 배경 + 오션뷰 이미지 오버레이 + 세리프 이탤릭 대형 제목
- **카드**: `rounded-xl`, hover shadow, `group-hover:scale-105` 이미지 줌
- **섹션 제목**: `text-5xl font-serif mb-2 border-b pb-4`
- **배지**: 각 섹션별 색상 — 문제: `bg-red-100 text-red-700`, 오퍼: `bg-blue-100 text-blue-700`, 바이럴: `bg-purple-100 text-purple-700`
- **하단**: 키워드 태그 + 스타일링 팁 박스 (`bg-slate-50 p-12 rounded-3xl`)
- **라이트박스**: ESC + 클릭 닫기 (외부 라이브러리 없음)
### 컴포넌트 섹션 구조
```tsx
import React from 'react';
type LightboxState = { src: string; title: string; tag: string } | null;
// ── 데이터 ──────────────────────────────────────────────
const listings = [
{
name: "숙소명",
rating: 4.97,
reviewCount: 243,
type: "아파트 투룸",
url: "https://www.airbnb.co.kr/rooms/...",
image: "https://...", // 숙소 대표 이미지 URL
tags: ["#커플데이트", "#오션뷰"],
summary: "2~3문장 숙소 특징 요약",
topComplaint: "가장 많은 불만 키워드",
topPraise: "가장 많은 칭찬 키워드",
},
// ... 5곳
];
const problemMatrix = [
{
rank: 1,
problem: "체크아웃 청소 의무 과다",
urgency: 9,
wtp: 9,
flags: ["🔴", "🚀"],
quote: "\"청소비 내고 나서 설거지까지 해야 함\"",
},
// ... 10개
];
const offers = [
{
title: "No-Chore Checkout",
problem: "체크아웃 청소 의무 과다",
urgency: 9,
wtp: 9,
headline: "청소는 우리가, 마지막 아침은 당신이",
description: "퇴실 전 설거지, 분리수거, 수건 정리 일절 필요 없음.",
tiers: [
{ name: "기본", desc: "청소비 포함", price: "예약 시 포함" },
{ name: "노-초어", desc: "청소 의무 면제 + 1h 레이트 체크아웃", price: "+₩15,000" },
{ name: "프리미엄", desc: "노-초어 + 2h 레이트 + 조식", price: "+₩39,000" },
],
guarantee: "퇴실 후 추가 청구 없음 보장",
tags: ["#NoChore", "#레이트체크아웃"],
},
// ... 5개
];
const viralHooks = [
{ emotion: "공포", text: "영종도 에어비앤비 예약 전, 이것 하나만 확인하세요.", color: "red" },
{ emotion: "분노", text: "청소비 4만원 내고, 퇴실 전 쓰레기 분리수거까지 해야 합니다.", color: "orange" },
// ... 20개
];
const competitors = [
{
name: "에어비앤비 플랫폼",
strength: "최다 선택지, 후기 시스템",
weakness: "품질 보장 없음, 커플 큐레이션 부재",
missingSegment: "기념일 커플 — 선택 피로 세그먼트",
gap: "커플 전용 큐레이션 채널",
priceRange: "₩8~20만",
},
// ... 5개
];
// ── 컴포넌트 ──────────────────────────────────────────────
const AirbnbResearch: React.FC = () => {
const [lightbox, setLightbox] = React.useState<LightboxState>(null);
const [activeTab, setActiveTab] = React.useState<'listings' | 'problems' | 'offers' | 'viral' | 'competitors'>('listings');
React.useEffect(() => {
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') setLightbox(null); };
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, []);
return (
<div className="bg-white min-h-screen font-sans text-slate-900">
{/* Hero */}
<header className="relative h-[80vh] flex items-center justify-center overflow-hidden bg-black">
<img
src="{{HERO_IMAGE — 오션뷰 숙소 대표 이미지}}"
className="absolute inset-0 w-full h-full object-cover opacity-50"
alt="영종도 오션뷰"
/>
<div className="relative z-10 text-center px-4">
<p className="text-white text-xs tracking-[0.5em] uppercase opacity-60 mb-4">영종도 커플 호캉스 · {TODAY_DATE}</p>
<h1 className="text-white text-6xl md:text-9xl font-serif italic mb-4">Market Report</h1>
<p className="text-white text-xl tracking-[0.3em] uppercase opacity-80">Airbnb Intelligence</p>
</div>
</header>
{/* Tab Navigation */}
<nav className="sticky top-0 z-40 bg-white border-b border-slate-200 shadow-sm">
<div className="max-w-7xl mx-auto px-6 flex gap-1 overflow-x-auto py-3">
{[
{ key: 'listings', label: '🏠 숙소 리뷰' },
{ key: 'problems', label: '🔴 문제 분석' },
{ key: 'offers', label: '💎 고전환 오퍼' },
{ key: 'viral', label: '⚡ 바이럴 전략' },
{ key: 'competitors', label: '🏆 경쟁사 분석' },
].map(tab => (
<button
key={tab.key}
onClick={() => setActiveTab(tab.key as typeof activeTab)}
className={`px-4 py-2 rounded-lg text-sm font-medium whitespace-nowrap transition-colors ${
activeTab === tab.key
? 'bg-slate-900 text-white'
: 'text-slate-600 hover:bg-slate-100'
}`}
>
{tab.label}
</button>
))}
</div>
</nav>
<main className="max-w-7xl mx-auto px-6 py-16">
{/* ── TAB: 숙소 리뷰 ── */}
{activeTab === 'listings' && (
<section>
<h2 className="text-5xl font-serif mb-2 border-b pb-4">🏠 영종도 커플 오션스테이</h2>
<p className="text-slate-500 text-sm tracking-widest uppercase mb-10">Airbnb 실시간 리뷰 수집 · {TODAY_DATE}</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
{listings.map((item, i) => (
<div
key={i}
className="group cursor-zoom-in overflow-hidden rounded-xl bg-slate-50 hover:shadow-xl transition-shadow duration-300"
onClick={() => setLightbox({ src: item.image, title: item.name, tag: item.tags[0] })}
>
<div className="overflow-hidden h-48">
<img src={item.image} alt={item.name}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
</div>
<div className="p-5">
<div className="flex items-center justify-between mb-2">
<span className="text-amber-500 font-bold">⭐{item.rating}</span>
<span className="text-slate-400 text-xs">{item.reviewCount}개 후기</span>
</div>
<h4 className="font-serif text-lg mb-1 leading-snug">{item.name}</h4>
<p className="text-slate-500 text-xs mb-3">{item.type}</p>
<p className="text-slate-600 text-sm leading-relaxed mb-3">{item.summary}</p>
<div className="flex flex-wrap gap-1 mb-3">
{item.tags.map((tag, j) => (
<span key={j} className="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full">{tag}</span>
))}
</div>
<div className="text-xs text-slate-500 space-y-1">
<div>👍 {item.topPraise}</div>
<div>👎 {item.topComplaint}</div>
</div>
</div>
</div>
))}
</div>
</section>
)}
{/* ── TAB: 문제 분석 ── */}
{activeTab === 'problems' && (
<section>
<h2 className="text-5xl font-serif mb-2 border-b pb-4">🔴 숙소 문제 매트릭스</h2>
<p className="text-slate-500 text-sm tracking-widest uppercase mb-10">긴급도 × WTP 점수화 · 리뷰 기반</p>
<div className="space-y-4">
{problemMatrix.map((item, i) => (
<div key={i} className="flex items-start gap-4 p-5 rounded-xl bg-slate-50 hover:bg-slate-100 transition-colors">
<span className="text-2xl font-bold text-slate-300 w-8 flex-shrink-0">#{item.rank}</span>
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<h4 className="font-serif text-lg">{item.problem}</h4>
{item.flags.map((f, j) => <span key={j} className="text-base">{f}</span>)}
</div>
<p className="text-slate-500 text-sm italic mb-2">{item.quote}</p>
<div className="flex gap-4">
<div className="text-sm">
<span className="text-slate-400">긴급도 </span>
<span className="font-bold text-red-600">{item.urgency}/10</span>
</div>
<div className="text-sm">
<span className="text-slate-400">WTP </span>
<span className="font-bold text-emerald-600">{item.wtp}/10</span>
</div>
</div>
</div>
<div className="flex-shrink-0 text-right">
<div
className="w-16 h-16 rounded-full flex items-center justify-center text-white font-bold text-lg"
style={{ background: `hsl(${Math.round((item.urgency + item.wtp) / 2) * 6}, 70%, 45%)` }}
>
{item.urgency + item.wtp}
</div>
</div>
</div>
))}
</div>
</section>
)}
{/* ── TAB: 고전환 오퍼 ── */}
{activeTab === 'offers' && (
<section>
<h2 className="text-5xl font-serif mb-2 border-b pb-4">💎 고전환 오퍼 설계</h2>
<p className="text-slate-500 text-sm tracking-widest uppercase mb-10">Top 5 문제 · 이상적 고객 정의 · 보장 포함</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{offers.map((offer, i) => (
<div key={i} className="rounded-xl border border-slate-200 overflow-hidden hover:shadow-lg transition-shadow">
<div className="bg-slate-900 text-white p-5">
<p className="text-slate-400 text-xs tracking-widest uppercase mb-1">OFFER {i + 1} · 긴급 {offer.urgency} / WTP {offer.wtp}</p>
<h4 className="font-serif text-2xl italic mb-1">{offer.title}</h4>
<p className="text-slate-300 text-sm">{offer.headline}</p>
</div>
<div className="p-5 space-y-4">
<p className="text-slate-600 text-sm leading-relaxed">{offer.description}</p>
<div>
<p className="text-xs text-slate-400 uppercase tracking-widest mb-2">가격 티어</p>
<div className="space-y-2">
{offer.tiers.map((tier, j) => (
<div key={j} className="flex justify-between items-center text-sm">
<div>
<span className="font-medium">{tier.name}</span>
<span className="text-slate-500 ml-2">{tier.desc}</span>
</div>
<span className="font-bold text-blue-700">{tier.price}</span>
</div>
))}
</div>
</div>
<div className="bg-emerald-50 rounded-lg p-3">
<p className="text-xs text-emerald-700 font-medium">🛡️ {offer.guarantee}</p>
</div>
<div className="flex flex-wrap gap-1">
{offer.tags.map((tag, j) => (
<span key={j} className="text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded-full">{tag}</span>
))}
</div>
</div>
</div>
))}
</div>
</section>
)}
{/* ── TAB: 바이럴 전략 ── */}
{activeTab === 'viral' && (
<section>
<h2 className="text-5xl font-serif mb-2 border-b pb-4">⚡ 바이럴 콘텐츠 전략</h2>
<p className="text-slate-500 text-sm tracking-widest uppercase mb-10">고전환 훅 20개 · SPICE 구조 · 플랫폼별 전략</p>
<div className="columns-1 md:columns-2 gap-6 space-y-4">
{viralHooks.map((hook, i) => {
const colorMap: Record<string, string> = {
red: 'bg-red-50 border-red-200 text-red-800',
orange: 'bg-orange-50 border-orange-200 text-orange-800',
purple: 'bg-purple-50 border-purple-200 text-purple-800',
blue: 'bg-blue-50 border-blue-200 text-blue-800',
pink: 'bg-pink-50 border-pink-200 text-pink-800',
amber: 'bg-amber-50 border-amber-200 text-amber-800',
};
return (
<div key={i} className={`break-inside-avoid p-4 rounded-xl border mb-4 ${colorMap[hook.color] || colorMap.blue}`}>
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-bold opacity-60 uppercase tracking-widest">#{String(i + 1).padStart(2, '0')}</span>
<span className="text-xs font-medium opacity-70">{hook.emotion}</span>
</div>
<p className="text-sm font-medium leading-relaxed">"{hook.text}"</p>
</div>
);
})}
</div>
</section>
)}
{/* ── TAB: 경쟁사 분석 ── */}
{activeTab === 'competitors' && (
<section>
<h2 className="text-5xl font-serif mb-2 border-b pb-4">🏆 경쟁사 5개 분석</h2>
<p className="text-slate-500 text-sm tracking-widest uppercase mb-10">포지셔닝 공백 · 시장 장악 전략</p>
<div className="space-y-6">
{competitors.map((comp, i) => (
<div key={i} className="p-6 rounded-xl bg-slate-50 hover:bg-slate-100 transition-colors">
<div className="flex items-start justify-between mb-4">
<div>
<span className="text-slate-400 text-xs font-bold uppercase tracking-widest">경쟁사 {i + 1}</span>
<h4 className="font-serif text-2xl mt-1">{comp.name}</h4>
</div>
<span className="text-sm text-slate-500 bg-white px-3 py-1 rounded-full border">{comp.priceRange}</span>
</div>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 text-sm">
<div>
<p className="text-xs text-slate-400 uppercase tracking-wider mb-1">잘하는 것</p>
<p className="text-slate-700 leading-relaxed">{comp.strength}</p>
</div>
<div>
<p className="text-xs text-slate-400 uppercase tracking-wider mb-1">약한 부분</p>
<p className="text-slate-700 leading-relaxed">{comp.weakness}</p>
</div>
<div>
<p className="text-xs text-slate-400 uppercase tracking-wider mb-1">놓치는 고객층</p>
<p className="text-slate-700 leading-relaxed">{comp.missingSegment}</p>
</div>
<div>
<p className="text-xs text-red-400 uppercase tracking-wider mb-1">포지셔닝 공백 ★</p>
<p className="text-red-700 font-medium leading-relaxed">{comp.gap}</p>
</div>
</div>
</div>
))}
</div>
</section>
)}
{/* Bottom Summary */}
<section className="mt-24 bg-slate-50 p-12 rounded-3xl">
<div className="grid md:grid-cols-2 gap-12">
<div>
<h4 className="text-2xl font-serif mb-6 underline underline-offset-4">핵심 기회 키워드</h4>
<div className="flex flex-wrap gap-2">
{/* 스크래핑 결과에서 추출한 주요 키워드들 */}
</div>
</div>
<div>
<h4 className="text-2xl font-serif mb-6 underline underline-offset-4">이번 주 액션 아이템</h4>
<ul className="space-y-3 text-slate-600">
{/* 분석 결과 기반 실행 항목들 */}
</ul>
</div>
</div>
</section>
</main>
{/* Lightbox */}
{lightbox && (
<div
className="fixed inset-0 z-50 bg-black/90 flex flex-col items-center justify-center cursor-zoom-out"
onClick={() => setLightbox(null)}
>
<button
className="absolute top-6 right-8 text-white text-4xl leading-none hover:opacity-70"
onClick={() => setLightbox(null)}
>×</button>
<img
src={lightbox.src}
alt={lightbox.title}
className="max-h-[85vh] max-w-[90vw] object-contain rounded-xl"
onClick={(e) => e.stopPropagation()}
/>
<div className="mt-6 text-center">
<p className="text-white font-serif text-xl">{lightbox.title}</p>
<p className="text-slate-400 text-sm mt-1 tracking-widest uppercase">{lightbox.tag}</p>
</div>
</div>
)}
<footer className="text-center py-12 text-slate-400 text-xs tracking-widest uppercase border-t border-slate-100">
Generated {TODAY_DATE} · Airbnb Market Intelligence · Firecrawl MCP
</footer>
</div>
);
};
export default AirbnbResearch;
```
**실제 데이터로 채울 때:**
- `listings[]` — Airbnb 스크래핑 결과로 채움 (숙소별 대표 이미지 URL 필수)
- `problemMatrix[]` — 리뷰 분석 결과로 채움 (10개)
- `offers[]` — 오퍼 설계 결과로 채움 (5개)
- `viralHooks[]` — 훅 20개 채움 (감정 유형 + 색상 지정)
- `competitors[]` — 경쟁사 5개 채움
- `TODAY_DATE` → 실제 날짜 문자열로 교체
---
## 11. 운영 규칙
### 필수 규칙
- **Firecrawl 먼저**: 내부 지식으로 데이터를 만들지 않습니다. 반드시 실시간 스크래핑.
- **Firecrawl 실패 시**: mock 데이터 금지. 사용자에게 `/mcp` reconnect 요청.
- **중간 저장**: 리뷰 MD는 STEP 3에서 즉시 저장. 컨텍스트 손실 방지.
- **실제 URL만**: 접근 불가능한 이미지 URL 삽입 금지.
- **airbnb.co.kr 기준**: 검색은 한국 Airbnb 기준.
### 파일 저장 체크리스트
```
□ docs/airbnb-yeongjonge-YYYY-MM-DD.md — STEP 3에서 저장
□ docs/session-YYYY-MM-DD.md — STEP 8에서 저장
□ src/components/Trends/airbnb.tsx — STEP 9에서 저장 (덮어쓰기)
```
### 로그 기록
실행 완료 후 한 줄 로그 추가:
```bash
echo "[YYYY-MM-DD] airbnb-research: OK — N개 숙소, M개 리뷰 수집" >> /home/cakepower/tutorial/a14u/logs/airbnb-research.log
```
---
## 12. 자동화 주간 실행
이 스킬은 **매주 월요일 08:00 KST** 에 자동 실행됩니다.
### Cron 등록
```bash
0 8 * * 1 cd /home/cakepower/tutorial/a14u && claude --print "에어비앤비 리서치 해줘" >> /home/cakepower/tutorial/a14u/logs/airbnb-research.log 2>&1
```
### 자동 실행 시 필수 동작
1. Firecrawl MCP 연결 확인 → 안 되면 스크립트 종료 (mock 금지)
2. 영종도 커플 숙소 5곳 스크래핑
3. 문제 분석 → 오퍼 → 바이럴 → 경쟁사 분석 순서로 실행
4. MD 파일 2개 저장 (리뷰 + 세션)
5. `src/components/Trends/airbnb.tsx` 덮어쓰기
6. 로그 1줄 기록
7. `npm run build` 또는 git commit **자동 실행 금지**
### 로그 위치
```
/home/cakepower/tutorial/a14u/logs/airbnb-research.log
```
### Cron 등록 확인
```bash
crontab -l | grep airbnb-research
```