트립픽 개발 기록 · 1/2
제주에서 길을 잃다 — 트립픽은 왜 '추천'이 아니라 '동선'을 풀었나
1인 개발 회고 시리즈 1장. 비 오는 제주의 오후 2시라는 한 장면이 어떻게 '날씨 × 위치 × 시간 × 장소 특성'을 동시에 푸는 4-변수 최적화 문제로 환원되었는지, 그리고 그 정의가 이후 모든 기술 선택을 어떻게 좁혔는지 정리합니다.
이 글은 전자책 「혼자 만든 트립픽」 1장을 기술 블로그 톤으로 다시 풀어 쓴 글입니다. 책은 회고·내러티브 중심, 이 시리즈는 의사결정의 기술적 근거를 더 깊이 다룹니다.
제주 여행을 가본 분들은 알 거예요. 출발 전엔 누구나 완벽한 동선을 짭니다. 오전엔 바닷가 카페, 점심엔 흑돼지, 오후엔 오름, 저녁엔 노을 명소. 지도 앱에 핀을 찍고, 블로그를 스무 개쯤 읽고, 나름의 최적 경로를 만들죠.
그리고 도착한 날 아침, 비가 옵니다.
그 순간 계획표는 종이 쪼가리가 됩니다. 오름은 미끄럽고, 바닷가 카페는 통유리에 빗물만 흐르고요. 급하게 "제주 비올 때 갈 만한 곳"을 검색하지만, 나오는 건 광고로 뒤덮인 목록뿐. 그 목록은 내가 지금 어디 있는지, 남은 시간이 얼마인지, 다음 일정과 얼마나 떨어져 있는지를 모릅니다.
저도 그런 하루가 또렷이 기억나요. 친구와 성산 일출봉과 우도를 보러 간 날이었습니다. 우도에 들어가 섬을 한 바퀴 돌고, 일출봉에 오르는 계획. 그런데 날씨가 발목을 잡아 우도엔 입도조차 못 했고, 일출봉이 보이기만 하는 식당에서 밥과 디저트만 먹다 끝났어요. 그날의 손실은 시간만이 아니라 "내가 산 비행기표·렌터카·숙소"의 일부이기도 했습니다.
트립픽은 이 한 장면에서 역산해서 만들어졌습니다.
문제를 재정의하기 — "추천"에서 "동선"으로
처음엔 흔한 생각을 했습니다. 맛집 추천 앱을 또 만들어서 뭐 하나. 추천 서비스는 이미 넘쳐나거든요.
그런데 제주에서 반나절을 날려본 뒤 깨달았어요. 사람들이 진짜 어려워하는 건 "어디가 좋아?"가 아니라 "이 날씨에, 이 시간에, 이 위치에서, 다음으로 어디를 가야 해?" 라는 거였습니다.
이 차이는 결정적이에요.
| 문제 형식 | 입력 | 출력 | 해결 도구 |
|---|---|---|---|
| 추천 | 사용자 선호도 | 장소 목록 (랭킹) | 콘텐츠 큐레이션, 평점 |
| 동선 | 시점·위치·제약 | 시간순 일정 (순서·간격) | 제약 최적화·라우팅 |
좋은 장소 열 곳을 던져주는 건 쉽습니다. 하지만 비 오는 오후 2시에, 지금 있는 곳에서 30분 안에 닿는, 실내이면서, 저녁 식당과 멀어지지 않는 곳 하나를 골라주는 건 전혀 다른 문제예요. 이건 사람의 추천이 아니라 계산이 필요한 일입니다.
4-변수 동시 최적화로 환원하기
문제를 깔끔하게 정의하면 풀 도구가 보입니다. 트립픽이 푸는 건 다음 네 가지를 동시에 만족시키는 일정이에요.
일정(t₁, t₂, ..., tₙ) = 최적화(
weather: W(t) ← 시간대별 강수 확률, 기상청 단기예보
location: L(t) ← 이전 장소에서의 이동 시간
schedule: S(t) ← 영업시간, 식사 시간대, 총 가용 시간
context: C(p) ← 실내/야외, 카테고리, 권역
)이 네 변수 중 하나만 빠져도 답이 흔들립니다.
- W를 빼면: 추천 리스트와 똑같아짐 (비 오는데 야외 명소가 1순위에 들어옴)
- L을 빼면: 한라산 동쪽 끝 카페 다음에 서쪽 끝 식당이 추천됨
- S를 빼면: 11시에 도착했더니 12시 오픈하는 가게가 첫 일정으로 잡힘
- C를 빼면: 카페만 5곳 연달아 추천돼서 점심을 못 먹음
그래서 트립픽의 한 줄 정의는 이렇게 정해졌어요.
제주 여행 코스 자동 최적화 — 날씨와 이동거리를 분석해 비/맑음에 따라 실내·야외 일정을 자동으로 추천한다.
이 정의가 이후 모든 기술 선택을 좁혔습니다. 예를 들어:
- 날씨 데이터: 어차피 시간대별 강수 확률이 필요하므로 → 기상청 단기예보 API 고정 (3장 참고 예정)
- 거리 데이터: 실시간 교통은 과스펙 → 지도 API의 정적 거리행렬 캐싱으로 충분 (8장 예정)
- 장소 데이터: 전국이 아니라 제주 한정이라 사전 수집 가능 → 1,849곳 미리 적재 (4장 예정)
- 모델 호출: 코스 자체는 알고리즘으로 풀고, LLM은 설명문 생성에만 → 비용 1/100 (8장 예정)
문제 정의를 좁혔기 때문에 "이 데이터 / 이 인프라가 필요하다"가 자동으로 도출됐습니다. 1인 개발의 가장 큰 적은 결정 피로인데, 좋은 문제 정의 하나가 결정 100개를 대신 내려줍니다.
왜 하필 제주였나 — 시장을 좁히는 게 무기인 이유
솔직한 동기 하나, 시장적 동기 하나가 겹쳤어요.
솔직한 동기: 제주에 대한 낭만. 산과 바다가 한 화면에 어우러지는 경치를 좋아했고, "내가 만들면서 즐거운 것"에서 출발한다는 원칙(3장에서 다룰 예정)의 첫 적용 대상이 제주였습니다.
시장적 동기: 제주는 위 4-변수 문제가 가장 격렬한 시장이에요.
- 섬이라 이동 시간이 일정에 직접 박힘 (L의 영향력 ↑)
- 산간·해안의 날씨 변동이 시시각각 다름 (W의 영향력 ↑)
- 여행 밀도가 높아 체류 시간이 짧음 (S의 제약 ↑)
- 부속 섬·오름·동굴 같은 장소 특성이 풍부 (C의 차별성 ↑)
같은 알고리즘을 서울에 돌리면 평균 이동 시간이 짧고 날씨 영향이 작아 "굳이?"가 됩니다. 제주는 같은 엔진의 체감 가치가 가장 큰 무대예요.
1인 개발자에게 시장을 좁히는 건 약점이 아니라 무기입니다. 전국을 다 담으려다 어디서도 안 먹히는 것보다, 한 지역에서 "여기선 트립픽이 제일 낫다"를 만드는 게 먼저예요.
좁혔기 때문에 가능했던 디테일도 많아요. 제주 장소 1,849곳을 미리 수집해 둘 수 있었고(4장 예정), 추자도·우도 같은 부속 섬은 당일치기 동선에서 제외하는 식의 현지 특화 규칙을 코드에 넣을 수 있었어요. 전국 서비스였다면 엄두도 못 냈을 디테일입니다.
// 부속 섬 처리 — 페리 운항 시간·소요시간이 일반 도로 거리와 완전히 다름.
// 당일치기 동선에선 후보에서 제외, 1박 2일 이상에서만 허용.
const ISLANDS_REQUIRING_FERRY = new Set(["우도", "마라도", "가파도", "비양도"]);
function isCandidate(place: Place, plan: TripPlan): boolean {
if (ISLANDS_REQUIRING_FERRY.has(place.island)) {
return plan.totalDays >= 2;
}
return true;
}전국 서비스로 시작했다면 이 규칙은 "엣지 케이스"로 묻혔을 거예요. 제주에 집중했기에 핵심 케이스 가 됐습니다.
한 사람의 불편에서 시작한다는 것
거창한 시장 조사로 시작한 게 아닙니다. 내가 겪은 반나절의 손실, 그 짜증이 출발점이었어요. 좋은 제품이 늘 그렇듯, 문제는 통계가 아니라 경험에서 먼저 옵니다.
"나만 불편한 거 아닐까?"라는 의심은 끝까지 따라다녔어요. 그 의심을 어떻게 다뤘는지는 3장 "시장을 보는 눈" 에서 이야기할게요. 다만 분명한 건, 트립픽의 모든 기술적 선택 — 날씨 API를 붙이고, 이동 시간을 계산하고, 코스를 자동으로 설명하게 만든 것 — 이 전부 "비 오는 제주의 오후 2시" 라는 한 장면에서 역산되어 나왔다는 점이에요.
다음 장 미리보기
다음 장(2장 "혼자 시작한다는 것")에서는 1인 창업의 결심과 두려움, 그리고 "혼자 할 수 있는 범위로 문제를 좁히는" 사고 과정을 다룹니다.
이번 장에서 정의한 4-변수 문제 — 이걸 혼자 푸는 게 가능할까요? 가능한 범위가 어디까지일까요? 그 한계선이 곧 트립픽 MVP의 경계가 됩니다.
💭 그때의 나에게: 너는 "이런 거 누가 안 만들었겠어?" 하고 한참 망설였지. 근데 안 만들어진 게 아니라, 동선까지 책임지는 건 아무도 제대로 안 한 거였어. 불편을 가볍게 여기지 마. 네가 흘려보낸 반나절이 곧 제품의 첫 문장이야.