본문 바로가기

Programming/프로그래밍 내용 정리

수학 공식으로 점철된 SQL 수십 줄, PostGIS 함수 한 줄로 정리하다

 

1. 무엇을 개발하려고 했을까

 

배달 서비스는 날씨나 운영 상황에 따라
유연하게 정책을 조정해야 하는 특성을 가집니다.

 

예를 들어, 기상 악화로 특정 지역의 접근성이 급격히 낮아지거나
명절 등 특정 상권에 주문 수요가 일시적으로 집중되는 상황이 발생할 수 있기 때문입니다.

 

 

 

 

이러한 상황에 대응하기 위해 

주문이 생성될 때 해당 주문의 도착 좌표가

지도 상에 정의된 ‘도착지 중단 구역’(다각형)에 포함되는지를 판단하는 기능이 필요해 졌습니다.

이 판단은 다각형 영역 기준으로 수행되어야 했으며,
주문 생성 흐름의 핵심 경로에 포함되는 로직인 만큼 지연 없는 응답 성능이 중요했습니다.

 

 


2-1. 기존 방식의 한계

 

기존 시스템에도 오라클 DB 기반으로, 특정 구역을 설정하는 기능이 있기는 했습니다.


그러나 기존 로직은 배송 구역을 하나의 공간 객체(면)로 다루지 못하고,
좌표 기반의 수치 데이터로만 관리하는 방식이었습니다.

 

 

실제 데이터 모델은 다음과 같은 구조를 가지고 있었습니다.

 

 

 

이 테이블은 배송 구역을 하나의 도형으로 통째로 저장하지 않고,
도형을 이루는 선 하나하나를 잘라 각각 개별 레코드로 저장한 구조였습니다.

 

하나의 배송 구역은 여러 개의 선분 레코드로 구성되며
각 선분은 시작 좌표(S_MAP_X, S_MAP_Y)와

종료 좌표(E_MAP_X, E_MAP_Y)를
각각의 컬럼으로 저장하고 있었습니다.

 

이러한 구조로 인해 ‘배송 구역’이라는 도메인 개념이

데이터베이스 상에서 하나의 의미 있는 단위로 표현되지 못하고
여러 개의 좌표 데이터로 분산되어 존재하는 한계를 가지고 있었습니다.

 

 

2.2 SQL 기반 좌표 계산 로직의 복잡성

 

기존 시스템에서는 특정 좌표가 배송 구역 내부에 포함되는지를 판단하기 위해
선분 데이터를 기반으로 SQL에서 직접 좌표 계산을 수행했습니다.

🔴 AS-IS

 

 

해당 쿼리는 선분의 시작점과 종료점을 이용해

도착 좌표와의 교차 여부를 계산하고,

이를 통해 영역 내부 포함 여부를 판단하는 방식입니다.

 

이 과정에서 하나의 정책 판단을 위해

복잡한 좌표 계산 로직이 SQL 내부에 직접 포함되어 쿼리 구조가 다소 복잡해졌습니다.

 

 


3. 계산이 아닌 공간 개념으로 문제를 다시 정의하다

 

기존 시스템은 오라클 기반 환경에서 운영되고 있었으나,
이번에 개발한 기능은 신규 서비스 흐름에 포함된 기능으로
PostgreSQL 기반 환경에서 구현할 수 있었습니다.

 

이에 따라 기존 좌표 계산 중심의 구현 방식을 확장하기보다는,
배송 구역과 도착 좌표를 공간 개념으로 명확히 표현할 수 있는 방식을 생각해 보게 되었습니다.

 

❓ PostGIS

어떤 방식이 적합할지 검토하던 중
PostgreSQL에서 제공하는 PostGIS를 활용하는 방안을 고려하게 되었습니다.

 

 

 

PostGIS는 공간 데이터를 데이터베이스 수준에서 직접 다룰 수 있도록 지원하는 확장 기능입니다.
점(Point), 선(Line), 면(Polygon)과 같은 공간 객체를 하나의 도메인 단위로 표현하고
이들 간의 관계를 공간 연산을 통해 직관적으로 처리할 수 있도록 해줍니다.

 

 

🔵 TO-BE


위에서 살펴봤던 복잡하고 길었던 🔴 AS-IS 코드가

PostGIS를 적용한 이후에는 의도가 명확한 한 줄의 조건식으로 단순화되었습니다.

 

하나의 다각형이 하나의 필드에 통째로 들어가는 방식입니다.

 

 

 

 

데이터 모델도 달라졌습니다.

하나의 배송 구역이 하나의 레코드로 표현되어

"배송 구역"이라는 도메인 개념이 데이터베이스에서도 그대로 드러나는 구조입니다.

 

 

 

 

 


4. 테스트 해보다

🔵 테스트 결론 (Conclusion)

GIS

 

 

기존 Oracle 기반 선분 좌표 + 산술 연산 방식과
PostGIS의 공간 객체(Polygon) + GIST 인덱스 방식을 동일한 데이터 조건에서 비교한 결과
PostGIS 방식이 평균 응답 시간 기준 약 18배 이상의 성능 개선을 보였습니다.

특히 기존 방식은 데이터 수 증가에 따라 선형적으로 성능이 저하되었습니다.
반면 PostGIS 방식은 공간 인덱스를 활용하여 대규모 데이터에서도 안정적인 응답 시간을 유지했습니다.

이를 통해 배달 가능 영역 판단과 같이
주문 생성 핵심 경로에 포함되는 로직에 대해
PostGIS 도입이 충분한 기술적·성능적 타당성을 가짐을 검증했습니다.

 

비교 목적 및 조건

1) 비교 목적

- 기존 Oracle 기반 Ray-Casting 산술 연산 로직의 성능 한계 검증
- PostGIS 공간 객체 + 인덱스 적용 시 성능 개선 효과 정량화
- 데이터 증가 상황에서의 확장성(Scalability) 비교

2)  비교 대상 로직

 

🧪 테스트 방법

1) 테스트 환경 초기화

- 두 테이블을 모두 제거 후 재생성하여 조건 동일화
- 재실행 시에도 오류가 나지 않도록 DROP TABLE IF EXISTS 사용

 

2) 기존 방식 테이블 생성 (선분 구조)

- Oracle 구조를 그대로 Postgres에 재현
- 선분 단위 좌표 저장

 

 

3)  PostGIS 테이블 생성

- Polygon Geometry 저장
- GIST 공간 인덱스 생성

 

 

4) 테스트 데이터 생성

 

 

 

5) 선분 → Polygon 변환

- 동일한 데이터로 PostGIS 테이블 구성
- ARRAY_AGG + ST_MakeLine + ST_MakePolygon
- 시작점 재추가로 Polygon 닫힘 보장

 

 

6) 성능 비교 쿼리 실행

 

 


5. 마무리하며: 계산을 넘어, 문제를 다시 정의하는 힘

 

이번 작업은 새로운 기술을 적용해 본 경험을 넘어,
기존 구조를 그대로 받아들이지 않고 왜 이런 한계가 발생했는지를 질문한 기록입니다.

 

처음에는 복잡한 수학 수식으로 점철된 SQL을 어떻게 최적화할지 고민했지만
문제의 본질은 계산 방식이 아니라

공간 데이터를 어떻게 모델링하고 있는가에 있음을 깨달았습니다.


이에 ‘좌표 계산’이 아닌 ‘공간 개념’으로 문제를 다시 정의했고
동일한 조건에서 직접 8,000건의 데이터를 생성해 실행 계획과 성능을 비교하며
추측이 아닌 데이터 기반으로 기술적 타당성을 검증했습니다.

 

그 결과, 평균 응답 시간은 72ms에서 4ms로 단축되었고
이는 단순한 성능 개선을 넘어

주문 생성이라는 핵심 경로의 안정성을 확보했다는 점에서 의미가 있었습니다.

코드의 가독성과 유지보수성, 그리고 확장성까지 함께 개선할 수 있었습니다.

 

 

문제를 올바르게 정의하고, 스스로 가설을 세우며 검증하는 과정에서
개발자로서 지치지 않고 성장할 수 있는 ‘사고의 근력’을 기를 수 있었다고 생각합니다.