개요

필자는 흔히 현장에서 GIS엔진이라고 말하는 미들웨어의 도입을 강력히 반대하는 입장입니다. 대부분의 2D GIS 사이트에서 GIS엔진은 성능을 떨어뜨리는 원인이기 때문입니다.
정보시스템은 정보저장 및 조회의 편의를 위하여 DBMS와 함께 동작합니다.(일부 예외는 존재합니다) 꽤 오래전부터 DBMS는 SDE(Spatial Data Extension)를 통해 공간데이터에 특화된 기능 및 함수를 제공합니다. SDE은 강력한 공간분석도구 입니다. 이의 활용을 통해 별도 미들웨어 없이 SQL만으로 Geo Processing을 수행할 수 있고 수행결과는 DBMS에 테이블 형식으로 정의함으로써 데이터 저장구조를 전체 시스템 수준에서 동일하게 가져갈 수 있는 장점이 있습니다.

공개SW인 PostGIS를 이용하여 경계분할을 진행합니다. 별도의 솔루션이 아닌 오직 DBMS가 지원하는 함수만을 이용합니다. 과정별 생성되는 데이터는 Qgis에서 확인했습니다.

본 글에서는 "보로노이다이어그램"을 이용하여 경계를 나누어 각각이 동일 면적에 근접하도록 분할하는 기법을 설명합니다. 이해를 위해 "보로노이 다이어그램"을 이해하셔야 합니다.

> 보로노이다이어그램 1 : 위키피디아
> 보로노이다이어그램 2 : 네이버캐스트

또한 K-Means 알고리즘에 대한 기반 지식 또한 요구됩니다.

> K-평균 알고리즘 : 위키피디아
> K-평균 군집화 : 티스토리(untitledblog)

이하 기술되는 SQL의 실행을 위하여 PostGIS의 GEOS 버전이 2.3.0 이상 이어야 합니다. 아래의 질의를 통해 PostGIS의 버전을 확인하고, 만일 기준을 충족하지 않을 경우 PostGIS를 업그레이드 하십시오. 간단한 설치 명령어만으로 쉽게 업그레이드 할 수 있습니다. 별도 설명하지 않겠습니다.

 select postgis_full_version();
POSTGIS="2.4.6 r17068" PGSQL="96" GEOS="3.7.0-CAPI-1.11.0 673b9939" SFCGAL="1.2.2" PROJ="Rel. 4.9.3, 15 August 2016" GDAL="GDAL 1.11.4, released 2016/01/25" LIBXML="2.9.1" LIBJSON="0.11" RASTER

 

본문

본 게시글에서 사용하는 PostGIS 함수는 다음과 같습니다. 상세 설명은 공식 사이트의 도큐먼트를 참조하십시오.(필독)

경계 분할 시행

1. 경계준비 : 시도경계 테이블에서 서울시 경계만을 추출한 별도 테이블 생성 (생략가능 과정)
CREATE TABLE seoul AS
    SELECT * FROM ngii_cdm_4326 WHERE bjcd = '1100000000';

2. 서울 경계 내에 존재하는 랜덤 포인트 셋 생성 : 포인트 개수가 많을 수록 최종 생성되는 분할 경계의 면적은 동일 값에 수렴
CREATE TABLE seoul_pts AS
    SELECT (ST_Dump(ST_GeneratePoints(geom, 10000))).geom AS geom FROM seoul WHERE bjcd = '1100000000';

3. K-Means 알고리즘을 이용한 군집화
CREATE TABLE seoul_pts_clustered AS
    SELECT ST_ClusterKMeans(geom, 10) over () AS cluster_id, geom FROM seoul_pts;

4. 클러스터 별 중심점 생성
CREATE TABLE seoul_pts_clustered_center AS
    SELECT cluster_id, ST_Centroid(ST_collect(geom)) AS geom FROM seoul_pts_clustered
    GROUP BY cluster_id;

5. 중심점을 기준으로 보로노이 다각형 생성
CREATE TABLE seoul_voronoi AS
    SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(geom)))).geom AS geom FROM seoul_pts_clustered_center;

6. 서울 경계와 보로노이 경계의 폐합 폴리곤 경계 생성
CREATE TABLE seoul_divided_result AS
    SELECT ST_Intersection(a.geom, b.geom) AS geom FROM seoul a
    CROSS JOIN seoul_voronoi b;

 

마치며

본 블로그의 카테고리 중 "꿀팁-PostGIS"가 상대적으로 빈약했습니다. 카테고리의 빈부격차를 줄이고자 임의의 시나리오를 만들어 게시글을 작성했습니다. 하지만 전하고자하는 메시지는 명확합니다.

공개SW가 보여주는 기능 및 성능은 필자를 많이 놀라게 합니다. 본 게시글에서 설명한 류의 Geo-Processing을 수행해야 한다면 저는 Shell Script를 만들어서 이를 호출하는 것으로 개발 코드를 많이 줄일 것 같습니다. 기능을 이행하는 수단은 한가지가 아니겠지만 가장 좋은 것은 이미 존재하여 검증된 것을 잘쓰는 것입니다. PostGIS는 이미 시장에서 검증되어 기술성숙도가 높은 공개SW입니다.

GIS엔진, 오라클이라는 굴레만 벗어난다면 가성비 좋은 아주 훌륭한 앱을 제작할 수 있습니다.

+ Recent posts