대학생 주거 리뷰 플랫폼, 찐빵 서비스 운영 중 문제가 발생하였다.
원룸 리뷰를 작성할 때 건물 정보를 함께 입력하게 되는데, 원룸의 위치만으로 캠퍼스를 명확히 특정할 수 없는 경우가 많았다.
예를 들어
- 건물이 두 개 이상의 캠퍼스 반경에 겹치는 경우
- 특정 캠퍼스에서 조금 떨어져 있지만 사실상 생활권인 경우
- 애초에 전혀 다른 곳에 사는 경우
초기 설계 단계에서 검색 필터에서 캠퍼스를 선택할 경우 캠퍼스 ID를 이용하여 검색하는 로직으로 구현했기에, 이런 애매한 상황은 마커 조회 및 검색 로직에서 걸림돌이 되었다.
그래서 캠퍼스 위치(위도·경도)를 기준으로 반경 1~2km 내의 모든 마커를 불러오는 방식으로 로직을 전환하기로 했다.
그래서 현재 위치(위도, 경도) 기반으로 반경에 속하는 마커들을 어떻게 하면 불러올 수 있을까 해서 발견한 것이 Haversine 공식이다.
Haversine 공식이란?
지구와 같은 구체의 두 지점 사이의 거리를 계산하기 위한 수학 공식이다.
![]()
)

잘 와닿지 않겠지만 대표적인 예를 보자.

위 두 사진을 보았을 때 신기하게 밑의 경로가 곡선이지만 더 짧은 것을 볼 수 있다.
왜냐하면 밑의 곡선 경로가 돌아가는 것처럼 보이지만, 사실 3차원의 공간에서의 거리를 2차원 평면에서 거리로 투영했기 때문에 곡선으로 보이지만 실제 지구 곡면 위에선 직선에 해당하는 경로이다.
그래서 Haversine 공식을 사용하면 곡면상의 최단 거리를 수학적으로 계산을 하기에 GPS, 네비게이션, 지도 서비스 등 여러 거리 계산에 활용된다.
계산 공식 및 코드
계산 공식은 다음과 같다

중심각이 위와 같을때 (d는 두 지점 사이의 거리, r은 지구의 반지름), $θ$의 하버사인은 다음과 같이 계산 가능하다.

)

)

위를 토대로 실제 거리 d는 다음과 같이 계산된다.
$$
d=2R⋅arcsin(hav(θ))
$$
즉, 두 점의 위도·경도를 이용해 중심각을 구한 뒤, 이를 지구 반지름에 곱하면 실제 거리를 구할 수 있다.
위도·경도 값은 반드시 라디안(radian) 단위로 변환 후 계산해야 한다.
보통 DB나 API로 받는 좌표는 도(degree) 단위이므로 변환 과정이 필수다.
주의사항
위도·경도 값은 반드시 라디안(radian) 단위로 변환 후 계산해야 한다.
보통 DB나 API로 받는 좌표는 도(degree) 단위이므로 변환 과정이 필수다.
private static final double EARTH_RADIUS_METERS = 6371000; // 지구 반지름 (m 단위)
private double calculateDistanceMeters(double lat1, double lng1, double lat2, double lng2) {
// 1. 위도·경도 차이를 라디안으로 변환
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
// 2. Haversine 공식 적용
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
* Math.sin(dLng / 2) * Math.sin(dLng / 2);
// 3. 중심각(θ) 계산
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
// 4. 거리 반환 (단위: m)
return EARTH_RADIUS_METERS * c;
}- 위도, 경도 차이를
Math.toRadians()를 이용하여 라디안으로 변환 - 두 점 사이의 구면 삼각형에 Haversine 함수 적용
Math.atan2()로 중심각 구하기- 지구 반지름에 곱해 실제 거리를 계산
마무리
Haversine 공식에서는 지구가 완전한 구형이라고 가정을 했지만 실제 지구는 적도 쪽이 좀 더 길쭉한 타원형이기 때문에 아주 정확하다곤 할 수 없다. 그래서 매우 정확한 거리를 알아야한다면 타원체인 것을 고려한 Vincenty 공식을 사용하는게 좋다. 하지만, 계산량이 좀 더 많아지고 살짝 더 복잡하다..
우리 서비스는 단순히 1~2km 반경의 마커들을 조회만 하면 되기에 계산량이 적고 좀 더 빠른 Haversine 공식을 채택하였지만 각 서비스에 맞춰서 원하는 공식을 적용하면 좋을 거 같다..!
참조
[지리 정보] 지리적 좌표계, 위도/경도의 이해 및 Haversine 공식을 이용한 지도 좌표 거리 계산 Kotlin 함수 작성
'Framework & Library > Spring Boot' 카테고리의 다른 글
| [Spring Boot] Spring Boot Actuator 살펴보기 (0) | 2025.09.26 |
|---|