[혼자왔니] postGIS를 활용한 인근 피드 조회
카테고리: RUAlone
태그: Info
공간 데이터를 다뤄야 하는 상황
사용자의 모집글에는 다음과 같은 내용이 포함된다.
따라서, 사용자가 게시글을 검색할 때 자신의 현재 위치 근방 1.5km 내에 있는 음식점들에 대한 모집글만 조회할 수 있도록 기능을 만들기 위해 자신의 위치 인근 게시글을 탐색해야 하는 상황이 생긴다.
postgreSQL의 postGIS 익스텐션을 활용해보자.
공간 데이터를 다룰 때 사용성과 성능 측면에서 월등하다고 알려진 postgreSQL
의 postGIS
를 사용해보기로 했다.
라이브러리 및 설정 파일 세팅
// hibernate-spatial
implementation 'org.hibernate:hibernate-spatial:5.6.11.Final'
// postgresql
runtimeOnly 'org.postgresql:postgresql:42.5.4'
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: # url
username: # username
password: # password
jpa:
database: postgresql
database-platform: org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect
Point 객체를 이용해서 위치에 대한 정보를 저장하자.
사용자의 좌표, 음식점의 좌표 이 두 가지 값을 가지고 둘 사이의 거리를 측정하여 일정 거리 미만에 해당하는 값들만 불러올 예정이다. 따라서 위도, 경도로 초기화시킨 point
객체가 필요하다.
@Table(name = "post")
@Entity
public class Post extends BaseEntity {
...
@Column(columnDefinition = "geometry(Point, 4326)", nullable = false)
private Point restaurantPoint; // 음식점(Point) 객체
...
}
import org.locationtech.jts.geom.*;
// 0(좌표 평면), 4326(위도-경도 좌표계)
private GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
/**
* 위도, 경도를 받아 Point 객체를 반환하는 메소드
*
* @param latitude
* @param longitude
* @return
*/
private Point getPoint(double latitude, double longitude) {
Point point = geometryFactory.createPoint(new Coordinate(latitude, longitude));
return point;
}
SRID
는 좌표계를 나타내는 값으로, 자주 사용하는 값은 0(좌표평면)과 4326(위도-경도 좌표계)이다.
PostGI
S와 MySQL
의 가장 큰 차이점은 바로 4326 좌표계에서도 다양한 함수를 사용할 수 있다는 것이다.
(MySQL
은 4326으로 지정해도 결국 좌표평면 좌표계 기준으로 공간 데이터를 다룬다)
인근 게시글을 조회하기 위한 쿼리를 작성해보자.
postGIS
에는 거리를 측정하는 다양한 함수가 있다.
그 중 ST_DWithin
함수를 사용하고자 한다.
해당 함수를 JPQL
형식으로 PostRepository에 적용시켜주었다.
public interface PostRepository extends JpaRepository<Post, Long> {
@Query(value = "select p from Post p where dwithin(p.restaurantPoint, :point, 1500, false) is true and p.isActive is true")
Page<Post> findPostByDistance(Pageable pageable, Point point);
}
더 살펴볼 내용들
아무래도 인근 좌표를 찾기 위해 왠지 post table을 full scan할 것 같다는 것이 조금 우려스럽다.
따라서,
point
객체가 적용되어있는 restaurant_point column에 인덱스를 건다든지,ST_DWithin
함수 외에postGIS
에서 제공하는 거리 측정 관련 여러 함수들의query plan
을 비교하여 더 적합한 함수를 찾는 등
추후에 성능적인 이슈를 생각해보려고 한다.
Reference
1) https://gksdudrb922.tistory.com/245 [postGIS 초기 세팅]
댓글 남기기