
요즘 프로젝트에서 공간 데이터를 다룰 일이 있어서 어떤 식으로 다뤄야할지 고민이 많다.
공간 데이터는 좌표계를 통한 지리적인 위치 데이터를 의미한다. 좌표계라는 단위는 위도 경도로 나타나는 일반적인 좌표계중 하나이다.
좌표계는 지구 상의 특정 위치를 정확하게 나타내기 위해 사용되는 시스템으로, 각각의 목적에 따라 여러 종류가 존재한다. 그 중에서 나는 가장 일반적으로 사용되는 위도/경도 좌표계를 사용하는 공간 데이터를 다룰 것이다.
SRS는 SRS_ID로 고유 번호로 표현되고 이를 이용해서 SRS 를 구분한다. 이것에 따라 같은 위치라도 정의가 달라지기 때문에 반드시 이를 인식하고 있어야한다. WGS84는 지구 전체를 구체 형태로 표시하기 때문에 지리 좌표계이다. 이는 4326으로 표현할 수 있다. 이에 대한 단위는 degree이다. ST_SPATIAL_REFERENCE_SYSTEMS에 잘 저장되어 있다.
MySQL에는 투영좌표계나 지리 좌표계에 평면 좌표계가 있다. 평면 좌표계에서는 SRID=0 인 좌표계로 표현되며 단위를 가지지 않고 X,Y 축이 제한이 없다. X축 Y축 단위를 m 로 표현하면 SRID=3857인 투영 좌표계가 된다.
MySQL8.0 부터는 SRID를 지원하기 때문에 SRID에 대해서 명시적으로 지정하지 않을시 0으로 인식 되기 때문에 실제 구면상의 거리를 계산하는 것이 아닌 단위가 없는 평면 좌표계에서 계산하게 된다.
결과적으로 실제로 존재하는 지구상의 위치 데이터를 표현하는 것이 우리의 목표 이기 때문에 우리는 WGS84(4326)으로 지구를 표현하기로 마음 먹었다.
MySQL에서 제공하는 공간 데이터의 종류는 총 7가지이다. 단일 타입으로는 Point, LineString, Polygon 세 가지가 있다. 나머지 타입들은 이 세 가지 타입의 조합이다.
- Point : 좌표 공간의 한 지점
- LineString: 다수의 Point를 연결해 주는 선분
- Polygon: 다수의 선분이 연결되어 닫힌 상태
각각의 컬럼에는 당연하게도 알맞은 데이터 타입만 입력할 수 있지만, geometry 타입에는 모든 공간 데이터 타입의 저장이 가능한 슈퍼 타입이다.
MBR 이란?
Minimum Bounding Rectangle의 약자로 해당 도형을 감싸는 최소 크기의 사각형을 의미한다. 이 사각형들의 포함관계를 B-Tree 형태로 구현한 인덱스가 R-Tree 인덱스이다.
일반적으로 WGS84 기준의 위도, 경도 좌표 저장에 주로 사용된다. R-Tree 인덱스의 경우 각 도형의 포함 관계를 이용해 만들어진 인덱스다. 따라서 ST_Contains 혹은 ST_Within()등 과 같은 포함관계를 비교하는 함수로 검색을 수행하는 경우에만 인덱스를 이용할 수 있다.
공간 데이터들은 공간 함수를 통해 활용할 수 있다. 현재 내가 구현해야하는 기능은 현재 위치를 기준으로 일정 반경 내에 있는 추억의 장소 데이터들을 찾아 내는 기능이다.
앞서 ST_DISTANCE를 사용할 시 올바르게 인덱스를 사용할 수 없다는 사실을 책에서 확인했었다.
따라서 위에서 언급한 R-Tree 인덱스 용도를 사용하기 위해서 ST_Contains 혹은 ST_Within()등 과 같은 포함관계를 비교하는 함수를 사용하는 편이 좋은 퍼포먼스를 낼 수 있을 거라 느꼈다.

위의 그림 처럼 일정 반경을 기준으로 그림을 그려줄 필요가 있었는데, 범위를 나타내는 반경 사각 박스를 어떤식으로 그릴지에 대해 고민을 할 필요가 있었다. 처음에는 ST_MakeEnvelope를 활용하려고 했으나 제대로 검색이 되지 않았다.
그 후로 다른 함수를 찾아보던 중 ST_BUFFER이라는 함수가 있다는 것을 알게되었고 이를 사용하기로 했다.
SELECT
*,
ST_Distance(POINT_COLUMN, ST_GeomFromText('POINT(-73.985656 40.748817)', 4326)) AS distance
FROM
테이블 이름
WHERE
ST_Within(
POINT_COLUMN,
ST_Buffer(
ST_GeomFromText('POINT(-73.985656 40.748817)', 4326),
100
)
)
AND member_id IN (1, 2);
ST_BUFFER같은 경우에는 hibernate 공식 홈페이지 참고 결과 hibernate 구현체로 사용할 수 없다는 사실을 알 수 있었다. 따라서 mysql native 쿼리를 사용하는 것으로 선택을 했다.


그 결과 올바르게 검색이 되는지를 확인할 수 있었다.
공간 데이터에 대해서 너무 나이브하게 생각한 느낌이 강했다. Point 에 대한 검색을 하려니 생각보다 변수가 많았다.
공간 데이터를 정확하게 이해하기 위해서는
가 크게 필요한 것 같았다.
이러한 이해를 바탕으로 접근한다면 효율적으로 공간 데이터에 대한 이해를 할 수 있을 것 같다.
https://tecoble.techcourse.co.kr/post/2023-10-04-spatial-data/
Real MySQL
https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html