Docker 를 설치한 환경에서 다음과 같은 DockerFile 을 작성합니다.
FROM ghcr.io/osgeo/gdal:ubuntu-small-latest
ENV LC_ALL=C.UTF-8
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
RUN apt update && apt-get install -y --no-install-recommends postgresql-client vim
이후 아래처럼 build, run 합니다.
-v
옵션은 여러분들 상황에 맞게 바꿔주세요.
docker build -t gdal_build .
docker run --name gdal -v 'C:\gdal_docker\bind_dir:/bind_dir' -itd gdal_build
생성된 container 에 bash 를 실행해서 컨테이너 내부로 접속합니다.
docker exec -it gdal bash
여기까지하면 준비는 끝입니다.
이 게시물에서 사용하는 예시 데이터를 다운로드 받는 방법은 다음과 같습니다.
https://business.juso.go.kr/addrlink/elctrnMapProvd/geoDBDwldList.do?menu=5
위 링크에 접속해서 구역의 도형(.shp)
목차로 가서
전체자료
의 가장 최신 데이터(2024-12)를 사용했습니다.
(데이터를 받으려면 신청을 해야됩니다)
데이터 신청을 완료하면 위 그림처럼 각 시도별로 구역의 도형 정보를 받을 수 있습니다.
하나의 zip 파일에는 위 그림처럼 여러 shape 정보가 혼재되어 있습니다.
이 중에서 사용할 데이터는 다음과 같습니다.
TL_SCCO_CTPRVN.*
: 행정경계(법정동)_시도
TL_SCCO_SIG.*
: 행정경계(법정동)_시군구
TL_SCCO_EMD.*
: 행정경계(법정동)_읍면동
TL_SCCO_LI.*
: 행정경계(법정동)_리
위에서 다운로드 받은 zip 데이터를 압축해제 하면 다음과 같습니다.
이렇게 압축해제된 상태에서 하고자 하는 일은 다음과 같습니다.
*.shp
을 찾아냅니다.tl_scco_ctprvn_202412
#!/bin/bash
# 에러나면 전체 스크립트 정지
set -e
# 총 걸린 시간을 추출하기 위해 "시작 시간"을 미리 추출
start_time=$SECONDS
# 함수 정의
## 1. shape file upload 함수.
## ShapeFile 이 모여있는 Directory 내부를 재귀적으로 순회하면서
## file_pattern 에 매칭되는 파일들을 찾아낸다(주로 shp 파일이다).
## 찾아낸 이후에는 target_table 에 ogr2ogr 로 데이터를 업로드한다.
upload_shapefile() {
local file_pattern="$1"
local target_table="$2"
echo "find file pattern => ${file_pattern} .. and upload to => ${target_table}"
for SHP_FILE in $(find "${SHAPEFILES_DIR}" -type f -name "${file_pattern}"); do
if [ -f "$SHP_FILE" ]; then
echo "Processing $SHP_FILE"
ogr2ogr -append -progress -f PostgreSQL \
"PG:host=${DB_HOST} dbname=${DB_NAME} port=${DB_PORT} user=${DB_USER} password=${DB_PASSWORD} schemas=${DB_SCHEMA}" \
"${SHP_FILE}" -nlt PROMOTE_TO_MULTI -nln "${target_table}" \
-s_srs EPSG:5179 -t_srs EPSG:5186 --config SHAPE_ENCODING "EUC-KR" \
--config PG_USE_COPY YES;
else
echo "No ${file_pattern} files found in ${SHAPEFILES_DIR}"
exit 1
fi
done
}
## 2. 인덱스 생성 함수.
## 데이터를 모두 테이블에 업로드 한 후에 인덱스를 생성할 때 필요한 함수이다.
create_index() {
local table_name="$1"
echo "Creating Index on [geom] column"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
create index ${table_name}_geom_idx
on ${DB_SCHEMA}.${table_name} using gist (geom);
"
}
## 3. 권한 변경 함수.
## 테이블과 관련된 권한 변경이 필요할 때 사용하는 함수이다.
update_authorization() {
local table_name="$1"
# echo "Change Table [${table_name}] Authorization"
# psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
# alter table ${DB_SCHEMA}.${table_name} owner to tester1;
# grant delete, insert, select, update on ${DB_SCHEMA}.${table_name} to tester2;
# "
}
## 4. 임시 테이블 명칭을 실제 운영할 때 사용하는 테이블 명으로 바꿔치기 합니다.
rename_temp_to_prod() {
local temp_table_name="$1"
local prod_table_name="$2"
echo "Renaming Tables [${temp_table_name}] ==> [${prod_table_name}_${DATA_STD_DATE}]"
## 만약 기존 운영 테이블이 있다면 해당 테이블에 "_old" 를 붙여서
## 충돌을 미연에 방지할려면 조금 작업이 필요하겠죠?
## 이건 스스로 해보시기 바랍니다!
## 5. 임시 테이블 ==> 운영 테이블 명으로 변경
echo "RENAME TEMP TABLE TO PRODCUTION TABLE"
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
alter table ${DB_SCHEMA}.${temp_table_name} RENAME TO ${prod_table_name}_${DATA_STD_DATE};
"
}
# PostgreSQL 연결 정보
DB_HOST="host.docker.internal"
DB_PORT="5432"
DB_NAME="postgres"
DB_USER="postgres"
DB_SCHEMA="public"
DB_PASSWORD="root"
DATA_STD_DATE="202412"
########### 파일들 압축해제 ###########
# for file in /bind_dir/TL_SCCO_AREA/*.zip; do unzip -o "$file" -d "$(dirname "$file")"; done
########### 변수 세팅 ###########
# 임시 테이블 명
CURRENT_DATETIME=$(date +"%Y%m%d_%H%M%S")
PROD_CTPRVN_TABLE="tl_scco_ctprvn"
PROD_SIG_TABLE="tl_scco_sig"
PROD_EMD_TABLE="tl_scco_emd"
PROD_LI_TABLE="tl_scco_li"
TEMP_CTPRVN_TABLE="${PROD_CTPRVN_TABLE}_${CURRENT_DATETIME}"
TEMP_SIG_TABLE="${PROD_SIG_TABLE}_${CURRENT_DATETIME}"
TEMP_EMD_TABLE="${PROD_EMD_TABLE}_${CURRENT_DATETIME}"
TEMP_LI_TABLE="${PROD_LI_TABLE}_${CURRENT_DATETIME}"
SHAPEFILES_DIR="/bind_dir/TL_SCCO_AREA"
########### 0. 비밀번호 설정 ##########
export PGPASSWORD=$DB_PASSWORD
########### 1. 임시 테이블 생성 ##########
# 기존 geonpaas table 스키마 최대한 그대로 유지
# 1-1. 시도 레벨 테이블 생성
echo "Creating temporary 'CTPRVN' table: $TEMP_CTPRVN_TABLE";
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
create table ${DB_SCHEMA}.${TEMP_CTPRVN_TABLE}
(
ogc_fid serial not null primary key,
ctprvn_cd varchar(5),
ctp_eng_nm varchar(40),
ctp_kor_nm varchar(40),
geom geometry(MultiPolygon, 5186)
);
comment on table ${DB_SCHEMA}.${TEMP_CTPRVN_TABLE} is '행정경계_시도(법정동)';
"
## 1-2. 시군구 레벨 테이블 생성
echo "Creating temporary 'SIG' table: $TEMP_SIG_TABLE";
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
create table ${DB_SCHEMA}.${TEMP_SIG_TABLE}
(
ogc_fid serial not null primary key,
sig_cd varchar(5),
sig_eng_nm varchar(40),
sig_kor_nm varchar(40),
geom geometry(MultiPolygon, 5186)
);
comment on table ${DB_SCHEMA}.${TEMP_SIG_TABLE} is '행정경계_시군구(법정동)';
"
## 1-3. 읍면동 레벨 테이블 생성
echo "Creating temporary 'EMD' table: $TEMP_EMD_TABLE";
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
create table ${DB_SCHEMA}.${TEMP_EMD_TABLE}
(
ogc_fid serial not null primary key,
emd_cd varchar(10),
emd_eng_nm varchar(40),
emd_kor_nm varchar(40),
geom geometry(MultiPolygon, 5186)
);
comment on table ${DB_SCHEMA}.${TEMP_EMD_TABLE} is '행정경계_읍면동(법정동)';
"
## 1-4. 리 레벨 테이블 생성
echo "Creating temporary 'LI' table: $TEMP_LI_TABLE";
psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "
create table ${DB_SCHEMA}.${TEMP_LI_TABLE}
(
ogc_fid serial not null primary key,
li_cd varchar(10),
li_eng_nm varchar(40),
li_kor_nm varchar(40),
geom geometry(MultiPolygon, 5186)
);
comment on table ${DB_SCHEMA}.${TEMP_LI_TABLE} is '행정경계_리(법정동)';
"
########### 2. shapefile 데이터 업로드 ##########
upload_shapefile "TL_SCCO_CTPRVN.shp" "${TEMP_CTPRVN_TABLE}"
upload_shapefile "TL_SCCO_SIG.shp" "${TEMP_SIG_TABLE}"
upload_shapefile "TL_SCCO_EMD.shp" "${TEMP_EMD_TABLE}"
upload_shapefile "TL_SCCO_LI.shp" "${TEMP_LI_TABLE}"
# ################## 3. 인덱스 생성 및 권한 변경 ##################
create_index ${TEMP_CTPRVN_TABLE}
create_index ${TEMP_SIG_TABLE}
create_index ${TEMP_EMD_TABLE}
create_index ${TEMP_LI_TABLE}
# ################## 4. 권한 관련사항 변경 ##################
update_authorization ${TEMP_CTPRVN_TABLE}
update_authorization ${TEMP_SIG_TABLE}
update_authorization ${TEMP_EMD_TABLE}
update_authorization ${TEMP_LI_TABLE}
# ############### 5. 기존 상용 테이블과 이름 바꿔치기 ###############
rename_temp_to_prod ${TEMP_CTPRVN_TABLE} ${PROD_CTPRVN_TABLE}
rename_temp_to_prod ${TEMP_SIG_TABLE} ${PROD_SIG_TABLE}
rename_temp_to_prod ${TEMP_EMD_TABLE} ${PROD_EMD_TABLE}
rename_temp_to_prod ${TEMP_LI_TABLE} ${PROD_LI_TABLE}
echo "+==================================================================================================+"
echo "+==================================================================================================+"
end_time=$SECONDS
echo "Completed uploading TL_SCCO_*.shp files in ... $((end_time - start_time)) seconds!"
echo "+==================================================================================================+"
echo "+==================================================================================================+"
# Completed uploading TL_SCCO_*.shp files in ... 33 seconds!