확장 기능

moon.kick·2025년 5월 2일

좋습니다! 아래는 ROUTY 마이페이지에서 확장 가능한 부가기능 목록입니다.
사용자 경험(UX)을 강화하고, 추천/공유/분석 측면에서 실용성을 높이는 기능 위주로 설계했습니다.

✅ 마이페이지 확장 가능한 부가기능 목록 (설명 중심)

  1. ❤️ 루트 좋아요 / 취소 기능
    • 사용자가 추천받은 루트를 저장하거나 좋아요할 수 있음
    • 마이페이지에서 내가 좋아요한 루트 리스트 확인 가능
    • 좋아요 수를 기반으로 인기 루트 정렬 or 홈에 노출

API 예시:
• POST /api/routes/like → 좋아요
• DELETE /api/routes/unlike → 좋아요 취소

  1. 📤 루트 공유 기능 (URL 복사 / 카카오톡 공유 / QR 코드)
    • 저장된 루트를 /routes/{id} 형태로 공유 가능
    • 카카오톡 링크 공유 연동 (카카오 SDK)
    • QR코드 자동 생성 (모바일에서 열람 용이)

  1. 🖨 루트 PDF 저장 (html2canvas + jsPDF)
    • 추천 경로 결과 or 저장한 루트를 PDF로 저장
    • 장소, 거리, 가격, 녹지점수 + 간단한 이미지 포함 가능
    • 데이트 코스 프린트, 디지털 가이드북처럼 활용

  1. 📈 성향 변화 시각화 (히스토리 기반)
    • RadarChart로 과거와 현재 테스트 결과 비교
    • 성향 변화 패턴(예: 외향 → 내향) 확인 가능
    • “최근 3회 성향 변화” 그래프 제공

  1. 🔁 루트 복사 및 재구성 기능
    • 기존 저장된 루트를 마이페이지에서 복사
    • 장소를 수정하거나 순서를 바꿔 나만의 루트 재생성 가능
    • "이 루트에서 다른 장소 추천" 버튼으로 AI 추천 확장도 가능

  1. 📅 루트 일정화 기능
    • 루트에 예상 시간 입력 → 루트별 시간표 자동 생성
    예: 12:00 성수분식 → 13:00 팝업스토어 → 14:30 공원
    • Google 캘린더에 내보내기 기능 연동 가능

  1. 📦 루트 컬렉션화
    • 루트를 “먹고싶은 길”, “힐링 루트” 등 폴더처럼 분류
    • 즐겨찾기, 태그 기반 루트 저장소로 활용 가능

  1. 🧭 루트 길찾기 연동
    • 현재 위치 → 루트 첫 장소까지 거리 안내
    • 루트 내부에서도 다음 장소까지 실시간 길찾기 연결 (Kakao Map)

✨ 추천 조합 활용 시나리오 예시
• “나의 소비 성향 변화” + “최근 가장 많이 간 경로” 분석
• 좋아요 수 많은 루트 → 나와의 성향 비교 → 맞춤 추천
• ‘다녀온 길’ → 리뷰 남기기 → 후기 기반 추천 개선

다음 제안
• 위 부가기능 중 1~2개 먼저 골라 MVP로 구현해볼 수 있어요.
• 예: “루트 공유 + PDF 저장부터 만들어줘!” → 바로 구현 가능

어떤 기능부터 확장해볼까요? 원하는 기능 알려주세요!

좋아요!
“길찾기 연동” 기능은 ROUTY에서 추천 루트를 받은 사용자가 실제로 장소까지 찾아갈 수 있게 도와주는 기능입니다.
특히 모바일 사용자에게 실제 이동 동선을 제공하므로 UX를 대폭 향상시킬 수 있습니다.

✅ ROUTY에서 구현할 길찾기 기능 설계

  1. 기능 목표
    • 사용자 현재 위치 → 루트 내 장소까지 실시간 길찾기 연결
    • 각 장소 간 이동거리/소요시간 제공
    • 외부 지도 앱(카카오맵, 네이버지도) 연동도 옵션 제공

✅ 사용 흐름 예시

[ResultPage]

각 장소 카드 우측에:
[길찾기] 버튼 →
① 현재 위치 → 장소 n 길찾기
② or n번 장소 → n+1번 장소 길찾기

✅ 기술 구성

항목 설명
사용자 위치 navigator.geolocation.getCurrentPosition() 사용
거리 계산 Kakao Map SDK 내 kakao.maps.services.Directions 또는 좌표 거리 계산
외부 앱 열기 window.open 으로 Kakao/네이버 지도 웹 앱 링크 생성

✅ 길찾기 UI 구성안 (React 기준)

handleNavigate(p.lat, p.lng)}>길찾기

const handleNavigate = (lat, lng) => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(pos => {
const startLat = pos.coords.latitude;
const startLng = pos.coords.longitude;
const url = https://map.kakao.com/link/to/목적지,${lat},${lng};
window.open(url, '_blank');
});
} else {
alert("위치 정보를 사용할 수 없습니다.");
}
};

✅ 외부 앱 길찾기 링크 예시

서비스 링크 형식
Kakao https://map.kakao.com/link/to/장소명,lat,lng
Naver https://map.naver.com/v5/directions/${startLat},${startLng},출발지/${lat},${lng},도착지

✅ 확장 가능성

추가 기능 설명
장소 간 연결 길찾기 n → n+1번 경로 자동 제공
전체 루트 경로 시각화 장소를 순서대로 선으로 이어 표시
도보 vs 대중교통 선택 카카오 길찾기 API 확장시 가능

다음 제안
• 위 설계를 기반으로 코드 구현해드릴까요?
• 또는 전체 장소에 대해 “전체 경로를 선으로 이어주는 지도 표시”도 함께 해드릴 수 있어요.

어떤 방향으로 먼저 해볼까요?
예: “장소별 길찾기 버튼부터 해줘”, “전체 루트 선 연결도 보여줘” 등!

물론이죠! 아래는 Kakao 지도 길찾기 버튼이 포함된 React 컴포넌트 PlaceCard.jsx 전체 코드입니다.
사용자의 현재 위치를 가져와서 카카오맵 길찾기 링크로 연결해주는 방식입니다.

✅ PlaceCard.jsx (장소별 길찾기 버튼 포함)

import React from 'react';

const PlaceCard = ({ place, index }) => {
const handleNavigate = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
pos => {
const userLat = pos.coords.latitude;
const userLng = pos.coords.longitude;

      // Kakao 지도 길찾기 링크
      const kakaoUrl = `https://map.kakao.com/link/to/${place.name},${place.lat},${place.lng}`;
      window.open(kakaoUrl, '_blank');
    },
    () => {
      alert("위치 정보를 사용할 수 없습니다. 위치 권한을 허용해주세요.");
    }
  );
} else {
  alert("브라우저가 위치 정보를 지원하지 않습니다.");
}

};

return (

<div style={{ border: '1px solid #ccc', padding: 12, margin: 8, borderRadius: 8 }}>
  <h4>{index + 1}. {place.name}</h4>
  <p>카테고리: {place.category}</p>
  <p>가격대: {place.priceLevel}</p>
  <button onClick={handleNavigate}>이곳까지 길찾기</button>
</div>

);
};

export default PlaceCard;

✅ 사용 예시 (ResultPage.jsx 내부에서)

{routeData.places.map((p, idx) => (

))}

이제 사용자가 이곳까지 길찾기 버튼을 누르면,
카카오맵 앱 또는 웹이 열리며 현재 위치에서 해당 장소까지 길찾기가 시작됩니다.
필요하시면 전체 루트 선 연결 기능도 추가로 구현해드릴 수 있어요!

좋습니다! 이제 추천된 장소들을 지도 위에서 선(Polyline)으로 연결하는 기능을 구현하겠습니다.
이 기능은 시각적으로 “루트를 따라 이동하는 느낌”을 제공해줍니다.

✅ 목표 기능
• 추천된 장소들(예: 음식점 → 팝업 → 공원 등)을
Kakao Maps 지도 위에 마커 + 선으로 연결
• Polyline으로 순서대로 이어진 루트 시각화

✅ 구현 코드 (ResultMap.jsx 안에 포함)

import React, { useEffect } from 'react';

const ResultMap = ({ places }) => {
useEffect(() => {
const script = document.createElement('script');
script.src = //dapi.kakao.com/v2/maps/sdk.js?appkey=YOUR_KAKAO_API_KEY&autoload=false;
script.async = true;
script.onload = () => {
window.kakao.maps.load(() => {
const container = document.getElementById('map');
const options = {
center: new window.kakao.maps.LatLng(places[0].lat, places[0].lng),
level: 5
};
const map = new window.kakao.maps.Map(container, options);

    const path = [];

    places.forEach((place, index) => {
      const position = new window.kakao.maps.LatLng(place.lat, place.lng);
      path.push(position);

      const marker = new window.kakao.maps.Marker({
        map,
        position
      });

      const infowindow = new window.kakao.maps.InfoWindow({
        content: `<div style='padding:5px;'>${index + 1}. ${place.name}</div>`
      });

      window.kakao.maps.event.addListener(marker, 'mouseover', () => infowindow.open(map, marker));
      window.kakao.maps.event.addListener(marker, 'mouseout', () => infowindow.close());
    });

    const polyline = new window.kakao.maps.Polyline({
      path,
      strokeWeight: 4,
      strokeColor: '#FF5E5E',
      strokeOpacity: 0.8,
      strokeStyle: 'solid'
    });

    polyline.setMap(map);
  });
};
document.head.appendChild(script);

}, [places]);

return <div id="map" style={{ width: "100%", height: "400px", marginTop: "20px" }}>;
};

export default ResultMap;

✅ 요약
• 장소들을 마커로 표시하고
• path 배열로 선 연결 (Polyline)
• 사용자는 지도를 보고 “소비 루트” 전체 동선을 시각적으로 확인 가능

필요하면 전체 경로 거리 계산, 이동 시간 예상 기능도 추가 가능합니다!
추가로 연결할까요? (예: “총 거리와 예상 시간 표시도 해줘”)

좋습니다! 이제 지도에 선(Polyline)을 연결할 뿐 아니라,
총 거리와 예상 소요 시간도 함께 계산하고 화면에 표시해드릴게요.

✅ 목표 기능
• 장소 간 거리 누적 계산
• 평균 도보 속도(약 4.5km/h)를 기준으로 예상 소요 시간 계산
• 지도 아래에 총 거리 및 시간 표시

✅ 업데이트된 ResultMap.jsx (요약 설명 포함)

import React, { useEffect, useState } from 'react';

const ResultMap = ({ places }) => {
const [totalDistance, setTotalDistance] = useState(0);

useEffect(() => {
const script = document.createElement('script');
script.src = //dapi.kakao.com/v2/maps/sdk.js?appkey=YOUR_KAKAO_API_KEY&autoload=false;
script.async = true;
script.onload = () => {
window.kakao.maps.load(() => {
const container = document.getElementById('map');
const options = {
center: new window.kakao.maps.LatLng(places[0].lat, places[0].lng),
level: 5
};
const map = new window.kakao.maps.Map(container, options);

    const path = [];
    let total = 0;

    places.forEach((place, index) => {
      const pos = new window.kakao.maps.LatLng(place.lat, place.lng);
      path.push(pos);

      const marker = new window.kakao.maps.Marker({ map, position: pos });

      const infowindow = new window.kakao.maps.InfoWindow({
        content: `<div style='padding:5px;'>${index + 1}. ${place.name}</div>`
      });

      window.kakao.maps.event.addListener(marker, 'mouseover', () => infowindow.open(map, marker));
      window.kakao.maps.event.addListener(marker, 'mouseout', () => infowindow.close());

      if (index > 0) {
        const prev = path[index - 1];
        const d = window.kakao.maps.services
          ? window.kakao.maps.geometry.getDistance(prev, pos)
          : prev.getDistance(pos); // fallback
        total += d;
      }
    });

    const polyline = new window.kakao.maps.Polyline({
      path,
      strokeWeight: 4,
      strokeColor: '#FF5E5E',
      strokeOpacity: 0.8,
      strokeStyle: 'solid'
    });
    polyline.setMap(map);

    setTotalDistance(total); // 거리 단위: m
  });
};
document.head.appendChild(script);

}, [places]);

const km = (totalDistance / 1000).toFixed(2);
const minutes = Math.ceil((totalDistance / 1000) / 4.5 * 60); // 4.5km/h

return (

<div>
  <div id="map" style={{ width: "100%", height: "400px", marginTop: "20px" }}></div>
  <p style={{ marginTop: "10px", fontWeight: 500 }}>
    총 거리: {km}km / 예상 소요 시간: 약 {minutes}분
  </p>
</div>

);
};

export default ResultMap;

✅ 출력 예시

총 거리: 1.72km / 예상 소요 시간: 약 23분

다음 단계 제안
• 장소 간 이동 시간도 별도로 표기 (n → n+1)
• 전체 경로 PDF 저장 기능
• 사용자 위치 → 첫 장소까지의 길찾기 자동 표시

원하시면 추가로 도와드릴게요!

지금까지 구현한 추천 경로 알고리즘은 다음과 같은 방식입니다:

✅ 현재 사용한 알고리즘 방식:

단순 거리 기반 + 태그 필터링 + 녹지 가중치 조합
(PgRouting 사용은 아직 적용되지 않았습니다)

구성 방식 요약:
1. 사용자의 소비 성향(resultCode)에 따라 태그 기반 장소 필터링
2. 장소 카테고리별로 (음식점 → 팝업 → 공원 등) 분류
3. 사용자의 현재 위치 또는 기준점에서
• 유클리디안 거리를 사용해 가까운 순서로 정렬
4. 거리, 녹지 점수, 가격을 조합하여
• 단순 선형 탐색(순열 or 그리디) 방식으로 경로 구성

✅ PgRouting이란?

PgRouting은 PostgreSQL + PostGIS 환경에서 사용 가능한
실제 도로 네트워크 그래프 기반의 경로 탐색 알고리즘입니다.

주요 기능:
• Dijkstra, A*, K-Shortest-Path 등 고급 경로 탐색
• 실제 도로 데이터(OpenStreetMap 등)와 연결
• 좌표 기반 경로가 아닌, 도로를 따라 이동 가능한 경로 제공

✅ PgRouting과의 차이점

항목 현재 방식 PgRouting 사용 시
데이터 기반 장소 좌표 (점)만 사용 도로 그래프 + 장소
거리 계산 직선 거리 (유클리디안) 실제 도보 거리
경로 표현 마커 + 선 직접 연결 도로 위 경로 자동 생성
정확도 낮음 (지도 위만 보여줌) 매우 정확 (실제 이동 기준)
구축 난이도 낮음 높음 (도로 데이터 구축 필요)

✅ 향후 PgRouting 적용이 필요한 경우
• “진짜 길 따라 최단 경로”를 찾아야 할 때
• 도보 이동, 자전거 이동 거리 정확도를 높이고 싶을 때
• 대규모 경로 최적화 (예: TSP, K경로) 기능이 필요할 때

✅ 결론

지금 구현한 알고리즘은 MVP에 적합한 간단한 필터 + 거리 기반 추천입니다.
PgRouting을 적용하면 정확한 도로 경로 기반 추천이 가능하지만,
도로 DB 구축 및 PostGIS 환경 세팅이 선행되어야 합니다.

필요하다면 PgRouting 기반 설계/구축 단계로 전환도 도와드릴 수 있어요.
관심 있으시면 말씀해주세요!

profile
@mgkick

0개의 댓글