Summary
위도(Latitude), 경도(longitude) 등 공간 정보(GI, Geospatial Information) 을 Database 에서 다루는 방법에 대한 CS 학습 내용을 정리해봤습니다.
먼저 이를 학습할 때 중심을 두었던 제가 구현한 미션의 환경은 development 환경에서는 SQLite 의 In-Memory DB 를 사용하고, production 환경에서는 MySQL 8.x 를 사용하는 구조였습니다.
SQLite 에서는 단순한 Bounding Box Filtering 만 적용하고, 실제 Distance 계산은 Service Layer 에서 Haversine 공식을 이용해 수행하는 방법을 생각해봤습니다.
그리고 MySQL 에서는 SPATIAL INDEX 와 MBRWithin 함수로 1차 Filtering 후, ST_DISTANCE_SPHERE 지리 함수를 활용해 반경 기준 Filtering 과 Distance Sorting 까지 처리하는 식으로 성능 최적화 방법을 생각해봤습니다.
본 포스트는 현재 제가 학습하고 이해하려고 하는 내용을 바탕으로 정리한 것이며, 잘못 설명되거나 오해의 소지가 있는 부분이 있을 수 있습니다. 향후 학습을 통해 포스트 내용이 업데이트해 나갈 예정이니, 이를 감안하여 읽어주시면 감사하겠습니다!
배경
지도 정보를 저장하고 반경을 기준으로 데이터를 조회하는 기능 구현에 대한 계획을 세우면서, Database Level 에서 어떤 방식으로 처리할 수 있는지 조사하고 학습해봤습니다.
Database 와 Data Type
development 환경
- DB 종류
- SQLite In-Memory
- 좌표 저장 방식
- 위도(latitude) 와 경도(longitude) 를 각각
REAL타입으로 저장
- 공간 인덱스
- 지원되지 않음
- 거리 계산 방식
- Service Layer 에서 직접 Haversine 공식으로 계산
Haversine 공식이란, 두 좌표 간의 거리를 구할 때 사용하는 삼각법 및 삼각함수 기반 수식을 의미하며, 지구의 곡률을 고려한 정밀한 거리 계산을 수행합니다.
production 환경
- DB 종류
- MySQL 8.x
- 좌표 저장 방식
POINT타입 (공간 데이터)
- 공간 인덱스
SPATIAL INDEX사용
- 거리 계산 방식
- MBRWithin(POINT, Polygon) 단순한 사각형 범위(Box) 안에 좌표가 있는지 1차 후보 Filtering
- ST_DISTANCE_SPHERE(POINT, POINT) Meter 단위의 실제 distance 계산, 반경 Filtering 및 Distance Sorting 에 사용
Query 예시 및 내부 동작
MySQL 예시
내부 동작
MBRWithin공간 인덱스를 활용하여 대략적인 범위(Box) 에 포함되는 후보를 빠르게 Filtering 해줍니다.
ST_DISTANCE_SPHERE지구 곡률을 고려하여 정확한 거리 계산을 수행하며, 이 작업은 연산량이 크므로 가능한 한 적은 데이터에만 적용하는 것이 성능 상 유리합니다.
성능 고려사항
- SQLite 에서는 공간 인덱스를 사용할 수 없고, 단순히 위도와 경도에 대한 숫자 비교만 가능하기 때문에 Filtering 정확도가 낮고, distance 계산도 Application Layer 에서 별도로 처리해주어야 합니다.
- MySQL 은
SPATIAL INDEX를 활용하면 많은 데이터를 다룰 때도 Filtering 속도가 매우 빠릅니다. 하지만,ST_DISTANCE_SPHERE같은 지리 함수는 앞서 언급했듯 연산량이 무겁기 때문에 1차 Filtering 으로 candidate 수를 줄여주는 작업을 선행해주는 것이 좋습니다.
학습 내용 정리 및 개인적인 의견
- SQLite 는 간단한 테스트나 개발용으로는 충분하지만, 실제 production 환경에서 거리 기반 Query 를 효율적으로 처리하기에는 기능이 많이 부족한 것 같습니다.
- MySQL 는 Engine 이 다양한 Native 기능을 제공할 수 있어서 실제 production 환경에서 사용하기 좋습니다. 특히 공간 함수와 Indexing 기능을 통해 Database Level 에서 많은 Logic 을 처리할 수 있고, 이는 성능 최적화에도 유리한 방식이라고 생각합니다.
- 특히,
MBRWithin을 통한 1차 Filtering 과ST_DISTANCE_SPHERE의 조합이 Geolocation Query 의 기본적인 구조로 자주 사용되는 것 같습니다.
본 포스트는 현재 시점에서의 학습한 내용을 정리하고 이해한 부분을 공유하기 위해 정리된 내용으로, Database 는 너무나도 넓은 분야이기에, 앞으로 학습이나 실제 사례들을 접하면서 잘못 이해하고 있는 부분이 있다면 수정해 나갈 계획입니다.
