매장 찾기는 지점이 여러 개인 사업이라면 결국 필요해지는 작은 기능입니다. 우편번호를 지도 위의 짧은 매장 순위 목록으로 바꿔 주는 '가장 가까운 매장 찾기' 입력창 말이죠. 밖에서 보면 사소해 보이고, 해피 패스는 실제로 단순합니다. 하지만 잘 만든 매장 찾기는 조용히 세 가지 일을 잘 해냅니다. 지저분한 위치 입력을 이해하고, 진짜 근접성으로 지점을 정렬하고, 사람이 바로 행동할 수 있는 지도로 결과를 렌더링하는 것이죠.
이 가이드는 매장 찾기가 실제로 어떻게 동작하는지, 지도 API로 만드는 네 단계는 무엇인지, 그리고 데모와 실제 출시할 만한 것을 가르는 디테일이 무엇인지 다룹니다. 이 글의 모든 지도는 MapAtlas API 자체로 렌더링했습니다.
매장 찾기가 실제로 하는 일
스타일링을 걷어내면 매장 찾기는 세 단계짜리 파이프라인입니다.
- 방문자의 입력을 지오코딩합니다. '1012 Amsterdam'이든, 'SW1A 1AA'든, 공유된 GPS 위치든 전부 하나의 위도와 경도가 되어야 합니다.
- 주변 매장을 정렬합니다. 그 좌표와 여러분의 지점 위치 목록을 놓고, 합리적인 반경 안에서 가장 가까운 것들을 찾습니다.
- 결과를 렌더링합니다. 정렬된 매장을 마커로 지도에 올리고, 각각에 주소, 영업시간, 길찾기 링크를 붙입니다.
아래 지도가 바로 그 세 번째 단계이고, MapAtlas 타일로 렌더링했습니다. 암스테르담 도심의 여섯 개 지점이 방문자로부터의 거리순으로 핀 표시되어 있죠. 여기서는 슈퍼마켓이지만, 마커가 POI 데이터셋에서 오든 여러분의 매장 목록에서 오든 지도는 똑같습니다.

색상 순서가 곧 순위입니다. 방문자는 지도 중심에서 검색했고, 마커는 가까운 순서대로 놓인 최근접 지점들입니다.
1단계: 방문자의 입력을 지오코딩하기
방문자는 우편번호나 도시, 또는 전체 주소를 입력하고, 여러분에게 필요한 건 좌표입니다. 이게 포워드 지오코딩입니다.
// Turn what the visitor types into a coordinate (autocomplete geocoding)
const res = await fetch(
`https://gateway.mapmetrics-atlas.net/autocomplete/` +
`?token=${API_TOKEN}&text=${encodeURIComponent(query)}` +
`&focus.point.lat=52.37&focus.point.lon=4.89` // bias toward your service area
);
const { features } = await res.json();
const [lon, lat] = features[0].geometry.coordinates; // [lon, lat]
const label = features[0].properties.label; // "Damrak, Amsterdam, North Holland, Netherlands"
여기서 챙길 디테일이 두 가지 있습니다. 'Cambridge'가 의도한 쪽으로 해석되도록 서비스 지역 근처의 focus.point를 넘기세요. 그리고 방문자가 타이핑 대신 기기 GPS를 공유하는 경우를 처리하세요. 그때는 이미 좌표가 있으니 이 단계를 통째로 건너뜁니다.
2단계: 매장을 거리순으로 정렬하기
이제 방문자의 좌표가 생겼습니다. 매장 자체는 여러분의 데이터입니다. 각각 위도와 경도를 가진 지점 목록이 데이터베이스에 들어 있죠. 정렬은 직선(haversine) 거리 계산이고, API 호출은 필요 없습니다.
// Your branches, each with a lat/lon. Rank by distance from the visitor.
const ranked = stores
.map(s => ({ ...s, distance_m: haversine(lat, lon, s.lat, s.lon) }))
.sort((a, b) => a.distance_m - b.distance_m)
.slice(0, 6);
기본적인 매장 찾기에 필요한 건 이게 전부입니다. 지점이 많은 네트워크라면 요청마다 모든 지점과의 거리를 재지 않도록 먼저 방문자 주변 bounding box로 필터링한 다음, 살아남은 것들을 정렬하면 됩니다. 출력은 가장 가까운 지점들의 짧은 목록이고, 각각 distance_m을 가집니다.
3단계: 거리로 정렬한 뒤 이동 시간으로 다듬기
직선거리는 올바른 기본값입니다. 빠르고, 추가 호출이 필요 없고, 촘촘한 네트워크에서는 대체로 맞습니다. 하지만 직선거리로 가장 가까운 매장이 늘 가장 빨리 닿는 매장은 아닙니다. 강 건너 400미터 떨어진 매장이 가장 가까운 다리까지 10분을 돌아가는 길일 수 있으니까요.
'가장 가까운'이 정말로 '가장 빨리 도착하는'을 뜻하는 매장 찾기를 원한다면, 상위 후보 몇 개만 directions나 matrix 호출로 실제 이동 시간에 따라 다시 정렬하세요.
// Re-rank the closest stores by real drive time (MapAtlas Matrix API)
const res = await fetch(`https://gateway.mapmetrics-atlas.net/matrix/?token=${API_TOKEN}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sources: [{ lat, lon }],
targets: top3.map(s => ({ lat: s.lat, lon: s.lon })),
costing: 'auto', // 'auto' | 'bicycle' | 'pedestrian'
}),
});
const { sources_to_targets } = await res.json();
const row = sources_to_targets[0]; // one entry per target, each with .time (seconds)
const byTime = top3
.map((s, i) => ({ ...s, time: row[i].time }))
.sort((a, b) => a.time - b.time);
이건 가장 가까운 후보 몇 개에만 하는 일이라, 매장마다 한 번씩이 아니라 저렴한 단일 호출로 유지됩니다.
4단계: 매장을 지도에 렌더링하기
마지막 단계는 지도 그 자체입니다. 정렬된 매장마다 마커를 찍고, 주소와 영업시간이 담긴 팝업을 붙이고, 모든 결과가 보이도록 뷰를 잡으세요. 타일, 지오코딩, 검색을 한 제공자에서 주는 지도 API를 쓰면 매장 찾기 전체가 처음부터 끝까지 한 벤더, 한 좌표계가 됩니다. 이 글 앞부분의 지도도 그 위에 만들어진 것이고요.
각 마커의 팝업에는 방문자가 행동에 옮기는 데 필요한 핵심을 담으세요. 이름, 주소, 거리, 영업시간, 그리고 좌표를 라우팅 엔진에 넘기는 '길찾기' 링크입니다.
데모와 프로덕션을 가르는 디테일
결과가 없을 때. 지점이 하나도 없는 지역에서 누군가 검색합니다. 반경을 자동으로 넓힐지, 아무리 멀어도 가장 가까운 매장 하나를 보여줄지, 아니면 '50km 안에 매장이 없습니다'라고 솔직히 말할지 미리 정해 두세요.
영업시간. 문을 닫은 매장을 가장 가까운 선택지로 보여주는 매장 찾기는 답답합니다. 영업시간으로 필터링하거나 플래그를 달아서 '지금 영업 중'을 일급 옵션으로 만드세요.
모호한 입력. 'Cambridge'는 잉글랜드에도 매사추세츠에도 있고, 'Springfield'는 수십 군데 있습니다. 지오코딩 단계의 국가 바이어싱이 대부분을 없애 주고, 입력 중 자동완성을 제공하면 나머지가 사라집니다.
모바일 GPS와 동의. 모바일에서 가장 강력한 경험은 '내 위치 사용' 버튼이지만, 기기 GPS를 읽는 건 위치 데이터이고 동의가 필요합니다. 먼저 물어보고, 방문자가 거절하면 텍스트 입력으로 폴백하세요.
프라이버시. 방문자의 위치는 그 사람과 연결되는 순간 개인정보입니다. 요청 시점에만 지오코딩하고, 원시 좌표 저장을 피하고, EU 기반 API를 써서 위치가 EEA를 벗어나지 않게 하세요. 전체 그림은 GDPR 준수 지도 가이드를 참고하세요.
MapAtlas로 매장 찾기 만들기
MapAtlas는 하나의 API, 하나의 좌표계로 파이프라인 전체를 제공합니다. Geocoding API는 국가 바이어싱과 함께 우편번호와 도시를 좌표로 바꿔 주고, 여러분은 그 좌표에 대해 자체 지점 목록을 정렬합니다. Directions와 Matrix API가 상위 후보를 실제 이동 시간으로 다시 정렬하고, Dynamic Maps 타일이 결과를 렌더링합니다. 이 글에서 보여준 그대로죠. 모든 게 기본적으로 EU 안에서 돌아가기 때문에 방문자의 위치는 EEA에 머물고, 매장 찾기는 추가 작업 없이 GDPR을 준수합니다.
모든 엔드포인트의 전체 요청 및 응답 포맷은 MapAtlas API 문서에 있습니다. 자체 지점만이 아니라 방문자 주변의 관심 지점까지 찾아 주는 매장 찾기를 원한다면 Search API도 볼 만합니다.
매장 찾기는 작은 기능이지만 그 안에는 조용한 판단이 잔뜩 들어 있습니다. 모호한 입력을 이해하는 것, 진짜 근접성으로 정렬하는 것, 그리고 위치가 개인정보라는 사실을 존중하는 것. 이 세 가지를 제대로 잡으면 '가장 가까운 매장 찾기' 입력창은 더 이상 나중에 붙이는 기능이 아니라, 사이트에서 가장 많이 쓰이는 것 중 하나가 됩니다.
자주 묻는 질문
매장 찾기란 무엇인가요?
매장 찾기는 리테일이나 서비스 웹사이트에 있는 '내 주변 매장 찾기' 기능입니다. 방문자가 우편번호나 도시를 입력하거나 위치를 공유하면, 거리순으로 정렬된 가장 가까운 지점들이 반환되고 각 지점이 주소, 영업시간, 경로 링크와 함께 지도에 핀으로 표시됩니다. 내부적으로는 세 단계입니다. 입력을 좌표로 지오코딩하고, 보유한 매장 목록을 대상으로 주변 검색을 돌리고, 결과를 지도에 렌더링하는 것이죠.
매장 찾기 기능은 어떻게 만드나요?
네 단계로 만듭니다. 첫째, 지오코딩 API로 방문자의 입력(우편번호나 도시)을 위도와 경도로 변환합니다. 둘째, 매장 좌표를 대상으로 반경 쿼리나 최근접 이웃 쿼리를 돌려 가장 가까운 지점들을 얻습니다. 셋째, 그 결과를 거리순으로, 선택적으로 이동 시간순으로 정렬합니다. 넷째, 정렬된 매장을 팝업이 달린 마커로 지도에 렌더링합니다. 지오코딩, 주변 검색, 지도 타일을 한 제공자에서 모두 제공하는 지도 API를 쓰면 여러 서비스를 이어 붙이지 않고도 네 단계를 전부 처리할 수 있습니다.
매장 찾기 API가 꼭 필요한가요?
필요한 건 지오코딩, 지도 타일, 그리고 보통은 이동 시간 기반 정렬입니다. 매장 목록 자체는 여러분의 데이터죠. 적은 수의 매장을 코드에 하드코딩하고 직선거리를 직접 계산해도 됩니다. 하지만 우편번호 검색, 이동 시간 정렬, 렌더링된 지도가 필요해지는 순간, 지오코딩과 matrix와 지도 렌더링을 한 제공자에서 묶어 주는 API가 세 벤더를 연결하고 좌표 포맷을 맞추는 수고를 덜어 줍니다.
매장 찾기는 가장 가까운 매장을 어떻게 정렬하나요?
가장 단순한 정렬은 방문자 좌표에서 각 매장까지의 직선(대권) 거리를 오름차순으로 놓는 것입니다. 빠르고, 매장이 촘촘한 도심 네트워크에서는 대체로 이걸로 충분합니다. 경험을 더 좋게 하려면 상위 후보만 골라 directions나 matrix API로 실제 이동 시간에 따라 다시 정렬하세요. 강, 고속도로, 일방통행이 끼면 직선거리로 가장 가까운 매장이 늘 가장 빨리 닿는 매장은 아니니까요.
매장 찾기는 GDPR을 준수할 수 있나요?
가능하고, 방문자가 EU 안에 있다면 반드시 준수해야 합니다. 매장 찾기는 위치를 처리하는데, 위치는 사용자와 연결되는 순간 개인정보가 됩니다. 준수를 유지하려면 방문자 좌표를 저장하지 말고 요청 시점에만 지오코딩하고, EU 기반 지도 API를 써서 위치가 EEA를 벗어나지 않게 하고, 기기 GPS를 읽기 전에 동의를 받으세요. MapAtlas는 기본적으로 위치 쿼리를 EU 안에서 처리합니다.

