[만날각] 목적 기반 공정한 중간 만남 장소 추천 서비스

과정
풀스택
노출 페이지
대표 이미지
대표이미지
서비스 한 줄 소개
회차
5 more properties

ManalGak (만날각)

목적 기반 공정한 중간 만남 장소 추천 서비스 여러 참여자의 출발지를 고려해 가장 공정한 중간 지점과 장소를 추천합니다.

프로젝트 개요

프로젝트명: ManalGak (만날각)
개발 기간: 2026년 1월 ~ 2026년 2월 (약 4주)
팀명: MagicDev
팀 구성: 백엔드 3명, 프론트엔드 2명 (총 5명)
GitHub: https://github.com/CHOSSEANG/ManalGak-magicDev
시연 영상

프로젝트 배경

문제 정의

여러 명이 약속을 잡을 때 항상 반복되는 질문이 있습니다. “어디서 만날까?”
겉으로는 단순한 질문처럼 보이지만, 실제로는 다음과 같은 문제들이 존재합니다.
중간 지점 찾기의 어려움: 수동으로 지도 앱을 번갈아가며 검색해야 하는 번거로움이 있고, 단순 평균으로 계산하면 지구의 곡률을 고려하지 못해 부정확한 결과가 나옵니다.
이동 시간의 불균형: 특정 인원에게만 유리한 장소가 선정되는 경우가 많습니다. 어떤 사람은 20분이면 도착하지만, 다른 사람은 90분이 걸리는 불공평한 상황이 발생합니다.
장소 선택의 번거로움: 중간 지점을 찾아도 주변 맛집이나 카페를 다시 검색해야 하는 이중 수고가 필요합니다.
의견 취합의 어려움: 메신저 투표 기능은 한계가 있어 의견이 메시지에 묻히거나 결정이 지연되는 문제가 있습니다.

해결 방안

ManalGak은 이러한 문제들을 기술적으로 해결합니다.
3D 지구 모델 기반 중심점 계산: 단순 평균이 아닌 위경도 좌표계와 지구 곡률을 고려한 정확한 기하학적 중심점을 계산합니다.
이동 시간 데이터 시각화: 모든 참여자의 이동 시간을 분석하여 표준편차를 최소화한 공정한 장소를 추천합니다.
목적 맞춤 원스톱 추천: 중간 지점 선정 후 Kakao Local API를 활용해 목적(회식/데이트 등)에 맞는 장소를 즉시 추천합니다.
실시간 WebSocket 투표: STOMP 프로토콜 기반으로 실시간 반영되는 투표 시스템을 제공하여 빠르고 명확한 의사결정을 지원합니다.

핵심 가치

ManalGak은 4가지 핵심 가치를 바탕으로 설계되었습니다.
공정성: 참여자 간 이동시간 편차를 최소화하여 누구에게나 공평한 장소를 선정합니다. 한 사람에게만 유리한 장소가 아닌, 모두가 비슷한 시간을 투자하는 진정한 ‘중간’을 찾아줍니다.
정확성: 3D 지구 모델 및 실시간 교통 데이터를 기반으로 정밀한 위치를 계산합니다. 지구의 곡률을 고려한 벡터 연산으로 평면 좌표계의 오차를 제거했습니다.
편의성: 복잡한 중간지점 계산과 장소 검색 과정을 원스톱으로 자동화합니다. 사용자는 출발지만 입력하면 계산부터 추천까지 모든 과정이 자동으로 진행됩니다.
실시간성: WebSocket 기술을 활용하여 투표 현황과 의사결정을 실시간으로 동기화합니다. 모든 참여자가 동시에 같은 화면을 보며 지연 없이 결정할 수 있습니다.

시연 영상

서비스 플로우

사용자 여정 (User Journey)
Step 1: 모임 생성 ↓ Step 2: 참여자 추가 ↓ Step 3: 중간지점 확인 ↓ Step 4: 장소 투표 ↓ Step 5: 결과 공유
Plain Text
복사

상세 플로우

Step 1: 모임 생성

모임 이름과 목적(음식점/카페 등) 선택
참여자 수 설정
고유 링크 생성

Step 2: 참여자 추가

참여자 리스트 작성
Kakao Maps에서 출발지 선택
이동 수단 설정 (대중교통/자동차)

Step 3: 중간지점 확인

3D 벡터 기반 중간 지점 계산
참여자별 이동 시간 시각화
최적 지하철역 표시

Step 4: 최종 결과 및 공유

확정된 장소 정보 (주소, 전화번호)
카카오톡 공유 버튼
링크 복사 기능

시스템 아키텍처

주요 특징

Redis Caching Layer

목적: API 호출 비용 절감 및 응답 속도 개선
전략: 장소/경로 검색 결과를 1시간 TTL로 캐싱
효과: 응답 속도 95% 개선 (1200ms → 60ms)

WebSocket (STOMP)

목적: 실시간 투표 및 상태 동기화
구현: Spring Boot + SockJS + STOMP
효과: 모든 참여자가 지연 없이 투표 결과 확인

External API Integration

구조: Service Layer에서 API 호출 격리
장점: 유지보수성 향상 및 테스트 용이성 확보

ERD (데이터베이스 설계)

주요 엔티티

데이터베이스는 5개의 핵심 테이블로 구성되어 있습니다.
Meeting (모임 정보): 모임의 기본 정보를 저장합니다. 모임 제목, 목적, 생성 시간, 계산된 중간 지점의 위경도 좌표 등을 포함합니다.
Participant (참여자 정보): 각 모임에 참여하는 사용자의 정보를 관리합니다. 참여자 이름, 출발지 주소 및 좌표, 이동 수단 등을 저장합니다.
Station (지하철역 마스터): 자주 조회되는 지하철역 정보를 미리 DB에 저장하여 외부 API 호출을 줄였습니다. 역 이름, 노선, 참여자들의 총 이동시간 등을 관리합니다.
Place (추천 장소): Kakao Local API를 통해 추천된 장소 정보를 캐싱합니다. 장소명, 카테고리, 주소, Kakao Place ID 등을 저장합니다.
Vote (투표 이력): 실시간 투표 시스템의 데이터를 저장합니다. 누가 어떤 장소에 투표했는지, 언제 투표했는지 기록하여 투표 변경 이력도 추적할 수 있습니다.

설계 포인트

모임 & 참여자: Meeting(1) : Participant(N) 관계로 설계하여 한 모임에 여러 참여자가 속할 수 있도록 했습니다. 참여자별로 출발지 좌표와 이동 수단 정보를 포함하여 중간 지점 계산의 기초 데이터로 활용합니다.
투표 시스템: 투표 안건, 선택지, 이력을 분리하여 확장성을 확보했습니다. 사용자가 투표를 변경하더라도 이력이 남아 추후 분석이 가능합니다.
장소 & 지하철역: 외부 API 호출 비용을 절감하기 위해 자주 조회되는 지하철역 정보를 내부 DB에 저장했습니다. 이를 통해 반복적인 역 검색 시 API 호출 없이 즉시 응답할 수 있습니다.

기술 스택

Backend

백엔드는 Spring Boot 기반으로 구축했습니다.
Spring Boot: REST API 서버의 핵심 프레임워크로 사용했습니다. 최신 버전을 도입하여 성능과 보안을 강화했습니다.
JPA (Hibernate): ORM을 통해 객체 지향적인 데이터 접근 계층을 구현했습니다. 복잡한 SQL 작성 없이도 효율적인 데이터 관리가 가능합니다.
MySQL: 관계형 데이터베이스로 모임, 참여자, 투표 등 핵심 데이터를 안정적으로 저장합니다.
Redis: 캐싱 레이어로 외부 API 응답을 1시간 동안 저장하여 응답 속도를 95% 개선했습니다.
Swagger: API 문서를 자동 생성하여 프론트엔드 팀과의 협업을 원활하게 했습니다.

Frontend

프론트엔드는 Next.js 15를 기반으로 웹 애플리케이션을 구현했습니다.
Next.js: App Router를 활용해 직관적인 라우팅을 구현했습니다. SSR로 초기 로딩을 개선했습니다.
React: 컴포넌트 기반 UI를 구성했습니다.
TypeScript: 타입 안정성을 확보하여 런타임 에러를 사전에 방지했습니다.
Tailwind CSS: 빠르고 일관된 스타일링을 구현했습니다.
Zustand: 가볍고 직관적인 전역 상태 관리를 적용했습니다.

Infra & DevOps

안정적인 운영을 위한 인프라를 구축했습니다.
AWS EC2: 애플리케이션 서버 운영
AWS RDS: 관리형 MySQL 운영(백업/스냅샷/복구)
Docker: 개발/운영 환경 일관성 확보 및 배포 자동화 기반
GitHub Actions: develop/main 브랜치 기반 자동 빌드/배포
Nginx: Reverse Proxy 및 80/443 라우팅

External APIs

Kakao Maps API: 지도 표시, 출발지/중간지점 마커 시각화
Kakao Local API: 카테고리 기반 주변 장소 검색
Kakao Mobility API: 자동차 기준 경로/이동시간 산출
Kakao Login API: OAuth 2.0 기반 소셜 로그인
ODsay API: 대중교통 이동 시간 및 경로 정보 제공

핵심 기능

1. 모임 생성 및 참여자 관리

사용자는 간단한 단계로 모임을 생성하고 참여자를 추가할 수 있습니다.
모임 정보 입력: 모임 이름과 목적(회식, 카페, 문화시설, 관광명소)을 선택합니다. 목적에 따라 추천 카테고리가 자동 적용됩니다.
참여자 추가: 참여자 이름을 입력하고 지도에서 출발지를 선택합니다. 주소 검색 또는 지도 클릭으로 위치 지정이 가능합니다.
고유 링크 생성: 모임 생성 시 UUID 기반 고유 링크가 발급되어 공유가 가능합니다.

주요 구현 코드

Frontend - 지도 컴포넌트
// Kakao Maps SDK 활용 <Map center={center}> <CustomOverlayMap position={midPoint} /> {participants.map((p) => ( <MapMarker key={p.id} position={{ lat: p.lat, lng: p.lng }} /> ))} </Map>
Plain Text
복사

2. 3D 지구 모델 기반 중간지점 계산

왜 3D 모델이 필요한가?

위경도 산술 평균은 평면 좌표계 기준이어서 정확하지 않습니다. 지구는 구형이므로 참여자 간 거리가 멀어질수록 실제 지리적 중심과 오차가 발생할 수 있습니다.

3. 최적 지하철역 선택

중간 지점이 강/산 등 접근 불가능한 위치일 수 있어, 실제 만남을 위해 접근성 좋은 지하철역을 최종 선택합니다.
표준편차(이동시간 편차) 최소화 기준으로 최적 역을 선정합니다.

4. 목적 기반 장소 추천

Kakao Local API를 활용해 목적에 맞는 장소를 자동 추천합니다.
목적별 카테고리 자동 매핑 예시:
회식 → 음식점(FD6)
카페/스터디 → 카페(CE7)
문화 → 문화시설(CT1)
관광 → 관광명소(AT4)

5. 실시간 투표 시스템 (WebSocket)

WebSocket(STOMP) 기반으로 투표 결과를 실시간 동기화합니다.
모든 참여자가 동일한 투표 상태를 동시에 확인할 수 있습니다.

6. 결과 공유

고유 링크 생성 및 공유
카카오톡 공유(장소 정보 포함)

기술적 도전과 해결

Challenge 1: API 호출 최적화

참여자 수(N) × 후보 역 수(M)에 따라 API 호출이 폭증하여 Rate Limit 문제가 발생할 수 있습니다.
필터링과 요청 제어(딜레이/재시도), 그리고 캐싱 전략으로 안정적인 응답 속도를 확보했습니다.

Challenge 2: Redis 캐싱 전략

반복되는 장소/경로 요청을 캐싱하여 외부 API 호출을 줄이고, 응답 속도를 개선했습니다.
예시 키: search:{lat}:{lng}:{category}
TTL: 1시간

Challenge 3: Dev/Prod 환경 분리 배포 자동화

GitHub Actions + Docker + GHCR + EC2 기반으로 자동 배포를 구성했습니다.
develop → DEV 서버
main → PROD 서버

Challenge 4: 운영 서버 장애 대응 (502 Bad Gateway)

배포 직후 502 장애 발생, 원인 분석 결과 AWS 보안 정책에 의해 Outbound 80/443이 차단된 것을 확인했습니다.
Next.js 취약점 대응(15.1.9 업그레이드) 및 인스턴스 재구성을 통해 서비스 정상화했습니다.
향후 Private Subnet + ALB 구조로 개선할 계획입니다.

팀 소개 & 역할 분담

Team MagicDev

“기술을 마법처럼 연결한다”는 의미에서 시작된 이름입니다. 각자의 역할을 명확히 나누되, 서로의 영역을 이해하며 협업하는 것을 목표로 했습니다.

팀 구성

Backend (팀장) - 외부 API 연동(Kakao, ODsay) 및 추천 장소 로직 구현, 응답 최적화 및 캐싱 전략 수립
Backend - 중간지점/지하철역 알고리즘 구현, 인프라 구축 및 Docker/CI-CD 담당
Backend - DB 설계 및 인증/보안(JWT), 도메인(모임/투표) 설계 담당
Frontend - 핵심 화면 구현, 상태 관리, API 연동 담당
Frontend - UI/UX 디자인, 지도 컴포넌트 및 모바일 최적화 담당

성과 및 배운 점

구현 완료 기능

3D 중심점 알고리즘(지구 곡률 반영)
이동시간 조회(ODsay + Kakao Mobility)
목적별 장소 추천(Kakao Local API)
실시간 투표(WebSocket - STOMP)
결과 공유(링크 및 카카오톡)

기술적 성과

Kakao API 4종 활용
Deep Dive 기술 스택 전면 적용(Spring Boot, Next.js, Redis)
GitHub Actions + Docker 기반 CI/CD 자동화 구축

향후 개선 계획

보안 강화: Private Subnet + ALB 구조 전환, WAF 도입 검토
성능 최적화: CDN 도입, DB 인덱싱 최적화, API 응답 압축
기능 확장: AI 기반 추천 고도화, 추가 외부 데이터 연동
모니터링: CloudWatch 알림, 에러 추적(Sentry) 등