refactor: 재배치 거리 계산 방식 PostGIS 적용 - #104
Conversation
…om/baro-team/baro-server into refactor/relocation-distance-logic # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
There was a problem hiding this comment.
Code Review
This pull request introduces PostGIS-based spatial queries to optimize distance-based relocation assignments, adding a geom point column to StandWeight and a fallback to application-side Haversine calculations. Feedback suggests defining the geom column as geography(Point, 4326) instead of geometry to utilize spatial indexes (GIST) and avoid casting overhead in the repository query. Additionally, the application-side fallback logic should be optimized to prevent redundant Haversine calculations on the entire dataset.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| targetList = allStands.map { stand -> | ||
| val dist = calculateHaversine(request.currentLat, request.currentLon, stand.latitude, stand.longitude) | ||
| TargetStand(stand.standId, stand.weight, dist, stand.latitude, stand.longitude) | ||
| }.filter { it.distance <= 10000.0 } | ||
|
|
||
| if (targetList.isEmpty()) { | ||
| targetList = allStands.map { stand -> | ||
| val dist = calculateHaversine(request.currentLat, request.currentLon, stand.latitude, stand.longitude) | ||
| TargetStand(stand.standId, stand.weight, dist, stand.latitude, stand.longitude) | ||
| }.filter { it.distance <= 30000.0 } | ||
| } |
There was a problem hiding this comment.
allStands에 대해 하버사인 거리를 계산하고 TargetStand로 매핑하는 작업이 targetList.isEmpty()인 경우에 중복으로 수행되고 있습니다. 전체 정거장 데이터가 많을 경우 불필요한 연산으로 인해 성능 저하가 발생할 수 있으므로, 거리 계산 및 매핑을 최초 1회만 수행한 후 필터링하도록 개선하는 것이 좋습니다.
val mappedStands = allStands.map { stand ->
val dist = calculateHaversine(request.currentLat, request.currentLon, stand.latitude, stand.longitude)
TargetStand(stand.standId, stand.weight, dist, stand.latitude, stand.longitude)
}
targetList = mappedStands.filter { it.distance <= 10000.0 }
if (targetList.isEmpty()) {
targetList = mappedStands.filter { it.distance <= 30000.0 }
}| @Column(columnDefinition = "geometry(Point, 4326)") | ||
| val geom: org.locationtech.jts.geom.Point? = null, |
There was a problem hiding this comment.
공간 인덱스(GIST)를 효율적으로 활용하고 거리 계산 시 매번 geography로 캐스팅하는 비용을 줄이기 위해, 컬럼 정의를 geometry(Point, 4326) 대신 geography(Point, 4326)로 변경하는 것을 권장합니다. geography 타입을 사용하면 미터(m) 단위의 거리 연산(ST_DWithin, ST_Distance 등) 시 별도의 캐스팅 없이 공간 인덱스를 직접 탈 수 있습니다.
| @Column(columnDefinition = "geometry(Point, 4326)") | |
| val geom: org.locationtech.jts.geom.Point? = null, | |
| @Column(columnDefinition = "geography(Point, 4326)") | |
| val geom: org.locationtech.jts.geom.Point? = null, |
Summary
PostGIS의 공간 인덱스(GIST)와 내장 함수ST_DWithin,ST_DistanceSphere를 활용하여, 공간 연산 책임을 애플리케이션 서버에서 데이터베이스 단으로 위임RelocationAssignRequest에usePostGis플래그를 추가하여, 기존 방식과 PostGIS 방식 비교 테스트 환경 구현