커플의 장소 기억을 함께 모으고, 나누고, 발견하는 글로벌 데이트 지도 앱
카카오톡 챗봇에 인스타 릴스를 공유하는 것만으로 AI가 장소를 자동 추출해
Mapbox 3D 지구본 위에 핀을 꽂아줍니다.
발견(REEL) · 설렘(WISH) · 추억(MEMORY) 세 가지 태그로 데이트 기록을 아카이빙하세요.
| 장소 검색으로 핀 추가 | 챗봇 릴스 링크 → 앱 지도에 핀 반영 |
|---|---|
![]() |
![]() |
- 하단 검색 탭에서 장소명을 검색하고 발견·설렘·추억 태그를 선택해 핀을 등록합니다.
- 카카오톡 챗봇에 인스타 릴스 링크를 보내면 AI가 장소를 자동 추출하고, 링크 전송 후 1분 내 메모를 입력하면 핀에 메모가 함께 저장됩니다.
| 지도 줌인·줌아웃 & 3D 지구본 |
|---|
![]() |
- 줌 아웃 시 Mapbox 3D 지구본 모드로 전환되며, 핀이 밀집된 영역은 클러스터로 묶입니다. 클러스터를 탭하면 해당 영역으로 자동 줌인됩니다.
| 핀 수정 & 삭제 | 핀 공유 카드 생성 |
|---|---|
![]() |
![]() |
- 핀 팝업의 더보기(⋮)에서 장소명·메모·태그 수정과 삭제가 가능합니다.
- 공유 아이콘을 탭하면 Mapbox 배경 위에 핀 정보가 담긴 4:5 카드 이미지가 생성되어 클립보드에 복사되거나 저장됩니다.
| 위치 기반 룰렛 | 방문 감지 — 네 다녀왔어요 |
|---|---|
![]() |
![]() |
- 하단 "어디갈까?" 버튼을 탭하면 현재 위치 10km 이내의 발견·설렘 핀 중 하나를 랜덤 추천합니다.
- 현재 위치 100m 이내에 저장된 핀이 감지되면 방문 토스트가 표시되며, "네 다녀왔어요"를 선택하면 해당 핀이 추억 태그로 전환됩니다.
카카오톡 채널 챗봇에 인스타그램 릴스 링크를 붙여넣으면, AI가 장소 정보를 자동 추출해 지도에 핀을 등록합니다.
- AI 장소 추출 — Gemini (
gemini-flash-latest)가 인스타 캡션에서 장소명을 자동 파싱 - 국내/해외 통합 검색 — 카카오 Local API(국내 우선) → Google Places API(해외 폴백) 자동 전환
- 2초 룰 메모 자동 연결 — 릴스 링크 공유 직후 2초 내에 보낸 텍스트가 핀 메모로 자동 저장
- 장소 선택 카드 — 후보 장소가 여러 개일 때 카카오톡 리스트 카드로 직접 선택
- 레이트 리밋 — Bucket4j로 분당 10회 제한, 카카오 5초 타임아웃 내 전체 파이프라인 처리
Mapbox GL JS 기반의 3D 지구본 지도 위에 커플의 핀이 시각화됩니다.
- 3D 지구본 모드 — 줌 아웃 시 자동으로 3D 지구로 전환
- 파스텔 핀 마커 — REEL(연보라) · WISH(민트) · MEMORY(핑크) 3종 커스텀 SVG 마커
- Supercluster 클러스터링 — 핀 밀집 영역에서 자동 묶음 표시, 클릭 시 해당 영역 줌인
- AMOU 스타일 말풍선 팝업 — 핀 클릭 시 장소명 · 주소 · 메모 · 릴스 링크 표시
- 핀 공유 카드 — 말풍선 공유 아이콘 클릭 → Mapbox Static 배경 4:5 Canvas 카드 생성 후 클립보드 복사 또는 이미지 저장
장소의 의미를 세 가지 태그로 구분해 지도 맥락을 명확하게 표현합니다.
| 태그 | 표시명 | 의미 | 등록 경로 | 색상 |
|---|---|---|---|---|
REEL |
발견 | 릴스에서 발견한 장소 | 카카오톡 챗봇 (자동) | 연보라 #C5B4E3 |
WISH |
설렘 | 가보고 싶은 장소 | 웹 직접 등록 | 민트 #A8E6CF |
MEMORY |
추억 | 함께 다녀온 의미 있는 장소 | 웹 직접 등록 | 핑크 #FFB3C6 |
"오늘 어디 갈까?" — 쌓아온 핀 중에서 지금 위치 기준으로 랜덤 추천합니다.
- 추천 반경 — 현재 위치 기준 10km 이내 장소 추천
- Haversine 거리 계산 — PostGIS 없이 Java 레벨에서 처리 (50핀 규모 최적)
- 후보 풀 — REEL + WISH(아직 안 가본 곳) 위주 추천, MEMORY는 기본 제외
- 랜덤성 보장 — 5회 연속 동일 핀 추천 비율 ≤ 20%
초대 링크 한 번으로 커플의 공유 지도를 만들 수 있습니다.
- 초대 링크 기반 그룹 생성 — 24시간 유효 토큰으로 파트너 초대
- 핀/메모 그룹 격리 — 그룹 단위로 데이터 완전 분리 공유
- N인 확장 가능 설계 — MVP는 2인 커플,
Group-GroupMember구조로 향후 N인 확장 지원 - 중복 방지 — 같은 릴스 URL이 같은 그룹에 두 번 등록되지 않음
파트너가 새 핀을 등록하면 알림으로 확인할 수 있습니다.
- 자동 감지 — 앱 활성화(
visibilitychange+focus+ mount) 시 알림 목록 자동 갱신 - 알림 유형 —
CHATBOT_PINS(릴스 자동 등록) ·MANUAL_PIN(웹 직접 등록) - 패널 UX — 벨 아이콘 빨간 점 → 패널 열기 → 핀 클릭 시 지도 flyTo 이동
- 트랜잭션 격리 — 알림 실패가 핀 저장에 영향을 주지 않도록
@Transactional분리
별도 회원가입 없이 카카오 계정으로 즉시 시작합니다.
- 카카오 OAuth2 — 별도 회원가입 절차 없음
- JWT 쿠키 인증 — Access Token(1h) + Refresh Token(14일), HttpOnly Cookie
- 챗봇 연동 코드 — 웹에서 6자리 코드 발급(TTL 10분) → 카카오톡 챗봇에 입력해 계정 연동
1인 운영 환경에서 외부 API 장애를 사전에 감지합니다.
- MDC RequestId — 요청별 고유 ID 부여, Slack 알림에서 로그 역추적 1-step 가능
- 임계값 기반 Slack 알림 — Gemini 서버 에러율 10% · Instagram 차단율 50% 초과 시 자동 경보 (1시간 윈도우, 5분 쿨다운)
- Google Places 한도 추적 — 일일 호출 95% 도달 시 사전 경고
- 일별 로그 회전 — Logback 90일 보관, gzip 압축
- Micrometer 메트릭 — Prometheus + Grafana 대시보드 (로컬 모니터링 스택)
| 항목 | 버전 / 내용 |
|---|---|
| Framework | Next.js 16.2.6 (App Router) |
| UI | React 19.2.4 + Tailwind CSS 4 |
| 언어 | TypeScript 5 |
| 지도 | Mapbox GL JS 3.8.0 |
| 클러스터링 | Supercluster 8.0.1 |
| 폰트 | Pretendard (self-host), Gowun Batang, Noto Serif KR |
| 테스트 | Vitest + React Testing Library |
| 배포 | Vercel |
| 항목 | 버전 / 내용 |
|---|---|
| 언어 | Java 21 (Eclipse Temurin) |
| Framework | Spring Boot 3.4.4 |
| 빌드 | Gradle 8.13 (Kotlin DSL, 멀티모듈) |
| DB | PostgreSQL 17 (Neon 관리형) |
| ORM | Spring Data JPA + QueryDSL |
| 캐시 | Caffeine (로컬 인메모리) — ADR-0002 |
| 인증 | Spring Security + JJWT 0.12 |
| 레이트 리밋 | Bucket4j |
| 마이그레이션 | Flyway (V001~V007) |
| 테스트 | JUnit 5 + Testcontainers + WireMock |
| 배포 | AWS EC2 t3.micro (서울 리전) |
| 서비스 | 용도 |
|---|---|
| Kakao OAuth2 | 소셜 로그인 |
| Kakao i 오픈빌더 | 챗봇 Skill Webhook |
| Kakao Local API | 국내 장소 좌표 검색 |
| Google Places API | 해외 장소 검색 (카카오 폴백) |
Google Gemini (gemini-flash-latest) |
인스타 캡션 → 장소명 AI 추출 |
| Mapbox GL JS | 3D 지도 렌더링 |
| Slack Webhook | 운영 알림 (에러, 임계값 초과) |
| 항목 | 내용 |
|---|---|
| CI/CD | GitHub Actions |
| 컨테이너 | Docker (eclipse-temurin:21-jre-alpine) |
| 이미지 저장소 | GitHub Container Registry (ghcr.io) |
| DB | Neon PostgreSQL 17 (싱가포르 리전) |
| DNS / CDN | Cloudflare |
| Reverse Proxy | Nginx (EC2, 80 → 8080) |
| 모니터링 | Micrometer → Prometheus + Grafana |
- Java 21
- Node.js 20+
- Docker Desktop
# 1. DB 컨테이너 실행
cd backend/docker
docker-compose -f infra-compose.yml up -d
# → PostgreSQL 17 on localhost:5432
# 2. 환경변수 설정 (backend/.env)
# 3. 백엔드 실행
cd backend
./gradlew :apps:wherewego-api:bootRun
# → http://localhost:8080
# → Swagger: http://localhost:8080/swagger-ui.htmlcd frontend
npm install
npm run dev
# → http://localhost:3000cd backend/docker
docker-compose -f monitoring-compose.yml up -d
# → Prometheus: http://localhost:9090
# → Grafana: http://localhost:3001| 변수명 | 설명 |
|---|---|
DATASOURCE_URL |
PostgreSQL JDBC URL |
DATASOURCE_USERNAME |
DB 사용자명 |
DATASOURCE_PASSWORD |
DB 비밀번호 |
JWT_SECRET |
JWT 서명 시크릿 |
KAKAO_CLIENT_ID |
카카오 앱 키 |
KAKAO_CLIENT_SECRET |
카카오 앱 시크릿 |
KAKAO_REDIRECT_URI |
OAuth2 콜백 URI |
KAKAO_SKILL_SECRET |
챗봇 Skill Secret (44자, = 누락 주의) |
GOOGLE_PLACES_API_KEY |
Google Places API 키 |
GOOGLE_GEMINI_API_KEY |
Gemini API 키 |
| 변수명 | 설명 |
|---|---|
NEXT_PUBLIC_MAPBOX_TOKEN |
Mapbox 공개 토큰 |
NEXT_PUBLIC_MAPBOX_STYLE_URL |
Mapbox 커스텀 스타일 URL |
BACKEND_BASE_URL |
백엔드 API 주소 (서버 컴포넌트 전용) |
wherewego/
├── frontend/ # Next.js 16 (App Router)
│ ├── app/ # 페이지 라우트
│ ├── components/ # 공통 UI 컴포넌트
│ └── lib/
│ ├── design/tokens.ts # 색상 · 폰트 디자인 토큰
│ ├── pin/markers.tsx # REEL / WISH / MEMORY SVG 마커
│ └── share/ # Canvas 핀 공유 카드 생성
├── backend/ # Spring Boot 3 (Gradle 멀티모듈)
│ ├── apps/wherewego-api/ # 메인 API 서버
│ │ └── domain/
│ │ ├── auth/ # 카카오 OAuth2 + JWT
│ │ ├── group/ # 그룹 생성 / 초대
│ │ ├── pin/ # 핀 CRUD + 중복 방지
│ │ ├── chatbot/ # Kakao Skill Webhook
│ │ ├── place/ # 인스타 스크래핑 + AI 추출
│ │ ├── memo/ # 메모 (2초 룰)
│ │ ├── tag/ # REEL / WISH / MEMORY
│ │ ├── recommendation/ # 위치 기반 룰렛 (Haversine)
│ │ └── notification/ # 인앱 알림
│ ├── modules/jpa/ # BaseEntity, JPA 공통 설정
│ └── supports/
│ ├── logging/ # Logback + 파일 롤링 + Slack 알림
│ └── monitoring/ # Micrometer Prometheus
├── context/ # 도메인 컨텍스트 문서
├── docs/ # ADR, 아키텍처 문서
└── .github/workflows/ # CI/CD (deploy.yml)
- 프로젝트 전체 정리
- 시스템 아키텍처
- 기술 스택 상세
- 인프라 구축 가이드
- 챗봇 설정 가이드
- ERD
- ADR-0001 Redis/Kafka 검토
- ADR-0002 Redis → Caffeine 전환
- 도메인 컨텍스트
1인 개발 — rnqhstmd






