카카오맵 위에 히트맵 기능을 디벨롭하면서 고민하고 시도해 보았던 과정을 기록하고자 작성하였습니다.
문제 상황
- next 프로젝트로 카카오 맵 지도를 확대 축소 할때마다 축적 비율이 달라지는데 현재 코드에서는 비율의 변화에 따른 크기조절이 적용되어있지 않았어서 해당 부분을 디벨롭 해달라는 요청을 받았습니다.
축적 : 지도를 만들 때 어떤 곳을 실제보다 축소한정도
🧐 기존 문제 원인 분석
- 👉 기존 코드는 히트맵 크기를 고정값으로 해두어 축적 변화에 따라 히트맵의 크기가 변하지 않았었습니다.
- 확대 축소 정도를 반영해주면 해결될 것 같다고 생각했습니다.
📌 1차 시도 카카오맵의 줌 레벨 활용
- 카카오맵은
1~14 수준의 줌 레벨을 제공해주어 반경에 곱하여 해결하였었습니다.
🧐 1차 시도에서 원인 분석
- 👉 하지만
zoomLevel(확대/축소 정도)을 곱하여 단순하게 크기를 조정하는 방식에는 문제가 있었습니다.
시각적으로만 확대/축소되는 방식일 뿐, 실제 지도 축척에 따라 거리값을 계산하지 않아 실제 반경과 맞지 않는다는 것이었습니다.
- 저는 카카오맵에서 축적 관련해 해당 부분을 제공해주 찾아보았습니다.
📌 카카오맵의 줌 레벨과 축척분석
- 카카오맵은
1~14 수준의 줌 레벨을 제공하며, 각 레벨별 축척을 분석하였습니다.
- 20m, 30m, 50m, 100m, 250m, 500m, 1000m, 2000m, 4000m, 8000m, 16000m, 32000m, 64000m, 128000m
- 하지만 제가 원하는 기능은 없었고 다른 방법을 찾아보게 되었습니다.
당시 생각
- 카오맵에서 1px당 실제 거리를 제공해주지 않을까? (근데 없음)
- 화면 하단에 축적바 있는데 그걸로 뭔가를 해결할 수 있지 않을까?(축적바길이도 계속 변하고 관련해서 무언가를 제공해주지 않음)
- 그렇게 머리를 싸매던중... 이 블로그를 통해서를 통해서 문제를 해결 가능하게 되었습니다.
문제 부수기
물론이지 건우!
지금 말한 내용은 매우 정확한데, 문장이 조금 더 자연스럽게 흐르도록 다듬어볼게.
📌 픽셀당 실제 거리 계
- 처음에는 화면의 1px 거리를 피타고라스를 사용해서 가볍게 하려했는데 생각해보니 위도와 경도를 기준으로 피타고라스의 정리를 사용해 두 지점 사이의 거리를 계산하면 문제가 된다는걸 알게됬습니다.
- 그 이유는 지구가 평면이 아닌 구형(곡면) 구조이기 때문에, 위도·경도 좌표를 평면 거리로 간주하면 거리에 큰 오차가 발생 해버리는 문제였습니다.
- 📌 예시: 비행기가 두 도시 사이를 최단 거리로 이동할 때, 일반적인 지도 위 직선이 아니라 지구 곡률을 따라 비스듬히 이동하는 경로가 실제 최단 경로다.
- 두 지점 간의 실제 거리는 3차원 곡면 위의 호(arc) 형태이며, 이는 2차원 평면에서 직선 거리로 단순하게 계산하면 지구 곡률의 영향을 받아 부정확한 계산 결과가 나와버리는 문제였습니다.
- 저희 서비스 특성상 대한민국 시위는 서울에서만 주로 열리고 거리가 짧을 경우에는 오차가 거의 없을거라는것은 알고있어서 문제가 되지 않을거라고는 알고있었지만 더 공부해보고 싶어서 그렇게하지 않았습니다.
그러면 어떻게 계산하여야 하나?
하버사인(Haversine) 공식 적용
- 하버사인 공식은 구면 거리 계산에 적합하며, 지구 곡률을 고려하여 두 위경도 좌표 사이의 거리를 구할 수 있었습니다.
공식
θ=rd
hav(θ)=sin2(2θ)=21−cos(θ)
d=r⋅archav(h)=2r⋅arcsin(h)
h=sin2(2φ2−φ1)+cos(φ1)cos(φ2)sin2(2λ2−λ1)
d=2r⋅arcsin(sin2(2φ2−φ1)+cos(φ1)cos(φ2)sin2(2λ2−λ1))
- r : 지구 반지름 (6371km = 6,371,000m)
- φ : 위도 (Latitude)
- λ : 경도 (Longitude)
- h는 그냥 계산을위한 중간 단계값
계산

1차 최종 결론 (1px당 실제 거리 계산)
- 카카오맵의 너비를 위도·경도를 모두 이용해서 계산하지 않고, 경도 차이만 사용하기로 결정
- 이유:
- 위도(x), 경도(y)의 실제 거리가 다르지만, 현재 서비스에서 y축(위도) 기준 1px당 실제 거리를 구하기 어려웠다.
- 현재 카카오맵의 높이(
height: calc(100dvh - 14vh))는 헤더·푸터를 제외한 실제 높이를 정확히 알기 어렵다.
- 따라서, 경도 차이만을 기준으로 1px당 실제 거리를 계산하는 것이 합리적이라고 판단했다.
1픽셀당 거리 계산
const calculateRealDistanceOnePixel = (x1: number, y1: number, x2: number, y2: number) => {
const R = 6371000;
const toRadian = Math.PI / 180;
const lat1 = x1 * toRadian;
const lon1 = y1 * toRadian;
const lat2 = x2 * toRadian;
const lon2 = y2 * toRadian;
return (
2 *
R *
Math.asin(
Math.sqrt(
Math.sin((lat2 - lat1) / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin((lon2 - lon1) / 2) ** 2
)
)
);
};
2차 최종 결론
최종 계산 방법
- 카카오 맵이 화면에서 차지하는 실제 픽셀을 구한다.
- 카카오 맵에서 제공하는 현재 화면에 나타난 북동쪽 좌표와 남서쪽 좌표를 가져온다.
- 두 좌표를 가지고 (경도는 같게 두어) 하버사인 공식을 사용해서 두 좌표 거리를 계산한다.
- 최대한 실제 거리와 비슷하게 하고싶음 처음 이 방법을 적용했을때는 북동쪽 좌표 또는 남서쪽 좌표의 경도를 가지고 하였는데 2가지 더 좋은 방법이 생각났다.
- 시위는 서울에서 많이 일어나니 서울 중심 좌표를 기준으로
- 시위 상세 데이터에서 넘어오는 시위 장소 경도로 설정
- 근데 해보니 지구 반지름에 비해 너무 미미한 변화라 값이 똑같음 그래서 그냥 서울 좌표 하나로 가기로함
- 아니면 시위들 모든 위경도를 계산해서 가장 가운데를 계산하기
- 아까 구한 실제 화면의 가로 픽셀으로 하버사인 공식을 통해 구한 두 좌표(카카오맵 왼쪽 끝과 오른쪽 끝) 실제 거리를 나누어 1px당 실제 거리를 구한다.
📌 최종 정리
- 카카오맵 높이(
calc(100dvh - 14vh))로 인해 y축(위도) 기준 1px 거리 계산이 어려움 → 경도 차이만 활용하여 계산
- 히트맵 반지름이 하나의 값만 받기 때문에, 위도·경도를 따로 계산하는 방식은 적절하지 않음
- 현재 화면을 기준으로 1px당 실제 거리를 계산했으므로, 시위 위치를 추가로 반영할 필요 없음
- 서울 중심 경도(
127.0016985)를 고정값으로 사용하여 1px당 실제 거리 계산
📚 참고 자료