멀캠 맛 지도 - 풀스택 개발 회고
슬랙 속 맛집 정보를 지도 위로 보여주는 프로젝트
왜 만들었나?
매일 점심시간마다 "오늘 뭐 먹지?"라는 고민을 반복했습니다.
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를 활용했습니다.
깃허브와 이슈 번호를 매칭해서 추적을 손쉽게 할 수 있도록 했습니다.
사용자 흐름 설계
- 사용자가 슬랙에 음식점 정보를 입력
- 서버는 일정 시간마다 슬랙 채널을 읽고 파싱
- 새로운 가게가 등록되면 지도에서 마커 표시
- 클릭 시 상세 정보 확인 + 별점 및 댓글 작성 가능
배운 점
- Slack 메시지를 파싱하는 실전 데이터 수집 경험
- Vue + Pinia 구조를 실제 서비스에 적용해본 경험
- 프론트-백 분리 배포, Docker, HTTPS 적용 등 인프라 운영 실습
- 빠른 MVP 구현의 중요성과 트레이드오프 감각
회고 요약
복잡하게 만들기보다 진짜 쓰일 수 있는 MVP를 빠르게 만든 경험이었다.
실제 사용자들의 피드백을 통해 내가 만든 서비스가 "사용될 수 있는 도구"가 될 수 있음을 느꼈다.