Vue

멀캠 맛 지도 - 풀스택 개발 회고

코드짜는쿤스트 2025. 6. 5. 11:52

슬랙 속 맛집 정보를 지도 위로 보여주는 프로젝트

왜 만들었나?

매일 점심시간마다 "오늘 뭐 먹지?"라는 고민을 반복했습니다.

 

Slack 채널엔 부트캠프에 구성원들이 추천한 맛집 정보가 쌓여있지만 막상 찾으려고 하면 지난 대화 속에 묻혀버리게 됩니다.

"슬랙 속 맛집 정보를 자동으로 수집해서 지도에 띄우면 어떨까?"

라는 생각과 함께 서비스를 개발했습니다.

 

슬랙 메시지를 기반으로 맛집 정보를 크롤링하고 이를 지도에서 직관적으로 확인할 수 있도록 만든 사이드 프로젝트입니다.


어떤 기술을 썼나?

  • Frontend : Vue 3, Vite, Pinia, Axios
  • Backend : Spring Boot, MySQL
  • Deployment : AWS EC2, Docker, Nginx, Vercel
  • Communication : Jira, Slack
  • Etc : Slack Webhook, GitHub Actions, Naver API

아키텍쳐


핵심 기능

  • 사용자가 슬랙 메시지를 보낸 것을 이벤트 처리하여 음식점 정보를 자동 수집
  • 지도에서 마커 형태로 식당 위치 시각화 및 클러스터링
  • 마커 클릭 시 대표 이미지, 별점, 댓글 표시
  • 로그인 여부에 따라 댓글 작성 제한

만들면서 겪은 고민

🤔 슬랙 메시지를 어떻게 가져올까?

Slack에는 bot을 활용할 수 있는 API를 제공해줍니다.

 

https://slack.com/intl/ko-kr/help/articles/202026038-Slackbot-%EC%86%8C%EA%B0%9C]

 

Slackbot 소개

Slackbot은 도우미와 메신저 역할을 수행하며, 직장 동료와 함께하는 다이렉트 메시지(DM)나 채널에서 여러 가지 일을 돕습니다. Slackbot은 다음과 같은 BAD+B...

slack.com

 

이걸 활용해서 bot에게 채팅 가져오는 권한과 같은 기능을 주고 채팅 방과 저의 서비스를 연동해서 가져오도록 하였습니다.

🤔 지도의 클러스터링은 어떻게 구현해야 할까?

지도는 Naver Map을 사용했습니다.

 

사용자가 등록한 식당이 많아지면 마커가 겹쳐 UX가 저하됩니다.

 

이를 해결하기 위해 줌 레벨에 따라 마커를 묶는 클러스터링 기법을 적용했고,

 

네이버 지도는 기본 API에 클러스터링 기능이 없기 때문에 marker-tools.js를 활용했습니다.

 

이 도구를 통해 사용자 위치 기준으로 자연스러운 밀도 표현이 가능해졌습니다.

 

https://github.com/navermaps/marker-tools.js/tree/master/marker-clustering

 

marker-tools.js/marker-clustering at master · navermaps/marker-tools.js

NAVER Maps JavaScript API v3를 이용한 유틸성 마커 예제입니다. Contribute to navermaps/marker-tools.js development by creating an account on GitHub.

github.com

 

이곳에 있는 파일을 다운로드 받아 전체 경로의 libs/markerclustering.js에 저장을 해서 사용했습니다.

더보기

코드 보기

export function createMarkerClustering(map, markers) {
    return new window.MarkerClustering({
        minClusterSize: 2,
        maxZoom: 18,
        map,
        markers,
        disableClickZoom: false,
        gridSize: 100,
        stylingFunction: function (clusterMarker, count) {
            const size = Math.min(60, 30 + count);
            const content = `
                <div style="
                    width: ${size}px;
                    height: ${size}px;
                    border-radius: 50%;
                    background: white;
                    border: 3px solid #1890ff;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    font-weight: bold;
                    font-size: 16px;
                    color: #1890ff;
                    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
                ">${count}</div>
                `;

            clusterMarker.setIcon({
                content,
                size: new naver.maps.Size(size, size),
                anchor: new naver.maps.Point(size / 2, size / 2),
            });
        },
    });
}

 

아래와 같이 클러스터링 된 숫자로 표시를 했습니다.

🤔 오픈소스로 운영함에 있어서 key값들을 어떻게 관리해야할까?

협업을 하면서도 신경을 많이 썼던 부분입니다.

 

Slack Bot API, Naver Map API 등 민감한 키들은 오픈소스에서 쉽게 노출될 위험이 있어, 이를 어떻게 안전하게 관리할지 고민이 필요했습니다.

 

API 키는 .env로 분리하여 Git에 커밋하지 않도록 관리했고

 

배포 자동화를 위해 GitHub Actions에서는 Settings > Secrets and variables > Actions에 민감 정보를 저장했습니다.

 

Docker 빌드 시 --build-arg를 통해 전달하고, ARG → ENV 구조로 안전하게 주입하여 이미지나 로그에 키가 노출되지 않도록 설계했습니다.

🤔 사용자들이 모바일로 접근하는 경우가 많아서 반응형으로 어떻게 처리할 수 있을까?

웹 페이지에서는 다음과 같이 보이게 됩니다.

 

정보를 보여줄 때 모바일 화면에서는 너비가 줄어들게 되므로 사용자 경험을 해치기 때문에 

 

네이버 지도 웹 & 네이버 지도 앱의 UI와 비슷한 형태로 아래에서 올라오도록 반응형으로 구현했습니다.

 

 

 

🤔 팀원의 작업 상황을 파악하기 위해서 어떤 툴을 사용해야 할까?

Notion으로 템플릿을 만들어서 하는 방법도 있었지만 프로젝트 특성상 혼자서 FE/BE를 둘 다 개발을 했고  팀원에게 할 일을 주는 형태였습니다.

 

이를 위해 코드리뷰도 동시에 진행이 되어야 해서 Jira를 활용했습니다.

 

깃허브와 이슈 번호를 매칭해서 추적을 손쉽게 할 수 있도록 했습니다.


사용자 흐름 설계

  1. 사용자가 슬랙에 음식점 정보를 입력
  2. 서버는 일정 시간마다 슬랙 채널을 읽고 파싱
  3. 새로운 가게가 등록되면 지도에서 마커 표시
  4. 클릭 시 상세 정보 확인 + 별점 및 댓글 작성 가능

배운 점

  • Slack 메시지를 파싱하는 실전 데이터 수집 경험
  • Vue + Pinia 구조를 실제 서비스에 적용해본 경험
  • 프론트-백 분리 배포, Docker, HTTPS 적용 등 인프라 운영 실습
  • 빠른 MVP 구현의 중요성과 트레이드오프 감각

회고 요약

복잡하게 만들기보다 진짜 쓰일 수 있는 MVP를 빠르게 만든 경험이었다.

실제 사용자들의 피드백을 통해 내가 만든 서비스가 "사용될 수 있는 도구"가 될 수 있음을 느꼈다.