오늘은 통계청 SGIS에서 제공하는 전국 인구통계 데이터를 활용해 인포그래픽 형태의 전국 인구 격자 지도를 만들어보려 한다. SGIS에서는 1km, 10km 단위 등 다양한 격자(Grid)별 인구 자료를 제공하고 있다. 격자 데이터를 활용하면 행정구역 경계에 얽매이지 않고 자료를 훨씬 직관적으로 볼 수 있다. 그리고 조금만 잘 가공하면 다양한 시각화나 분석에 아주 유용하게 활용할 수 있다ㅎㅎ 우선 레츠꼬 🗺️
1. 데이터 불러오기
SGIS 데이터는 회원가입 후 자료신청 절차를 거쳐야 다운로드할 수 있다. SGIS 홈페이지 → 자료제공 → 자료신청에서 신청해주면 된다. 기본정보(소속, 연락처, 활용목적 등) 입력해주고, 다운받고 싶은 데이터를 선택해주면 된다. 내 기억에는 아마 신청하고 30분내로 대부분 승인이 났다.

기본정보 입력 후 필수 항목 동의, 그리고 신청할 자료를 모두 선택해주면 된다. 나는 전국(전체) 격자통계 2010년, 2023년 데이터를 신청했고 격자 경계 포함 옵션도 포함해서 경계 Shapefile도 함께 받았다.

이렇게 신청해주고 승인이 될 때 까지 기다려주면 된다.
2. 데이터 가공하기
승인이 완료되면 격자 경계 파일(shp)과 인구통계 파일(txt)을 각각 압축 형태로 받을 수 있다. 파일 수가 꽤 많기 때문에 jupyterlab에서 자동으로 풀고 병합하는 방식으로 정리할 예정이다. 그 전에 QGIS에서 격자 경계 파일을 하나로 합쳐서 전국 단위 파일을 먼저 만들어야 한다.
QGIS에서 격자 경계 병합하기
다운받은 경계 shp파일의 압축을 모두 풀고 QGIS에서 열어보면 이렇게 전국 격자가 나눠져 있는 걸 볼 수 있다.

상단 메뉴 벡터 → 데이터 관리 도구 → 벡터 레이어 병합으로 들어가 불러온 격자 경계 파일을 모두 선택한 후 합쳐주면 하나의 geojson파일로 만들 수 있다.

이후 내보내기 → 피처를 다른이름으로 저장 해서 저장하면 격자 경계 파일은 준비 완료. 이제 합쳐진 격자 geojson 파일에 같이 다운받은 인구통계 자료(txt)를 붙여주면 된다. 그러나 우리가 다운받은 인구통계 자료는 격자 구역별로, 년도별로 압축파일로 쪼개져 있기 때문에 가공하기 꽤나 귀찮다. 우선 jupyterlab에서 압축파일을 모두 풀어주고 파일을 불러와 데이터를 하나로 합치는 작업을 해준다.
GeoJSON과 TXT 데이터 불러오기
우선 가공에 필요한 라이브러리들을 모두 로드한 뒤, 불러올 geojson 파일과 압축파일 경로를 변수로 지정해준다.
import geopandas as gpd
import pandas as pd
import zipfile
import os
geojson_path = "gis data/전국격자.geojson"
zip_path = "raw data/_census_reqdoc_1758382203683.zip"
extract_folder = "extracted_txts"
이후 GeoJSON을 불러오고 압축 파일을 풀어준다. 앞서 지정한 extract_folder 안에 연도별, 연령대별로 구분된 txt 파일이 들어가게 된다.
# GeoJSON 불러오기
gdf = gpd.read_file(geojson_path)
# 인구통계 파일 압축 해제
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
zip_ref.extractall(extract_folder)
연령대 구분 후 데이터 병합하기
txt 데이터를 열어보면 아래처럼 헤더 없이 구분자는 '^'으로, 연도, 격자코드, 연령별 인구로 구분되어있는 것을 확인할 수 있다.

그러나 모든 연령을 따로 볼 필요는 없기 때문에 연령대(유소년, 청년, 중장년, 노년)으로 구분하여 전처리해주었다.
bins = {
"유소년": [f"in_age_{str(i).zfill(3)}" for i in range(1, 16)], # 0–14세
"청년": [f"in_age_{str(i).zfill(3)}" for i in range(16, 31)], # 15–29세
"중장년": [f"in_age_{str(i).zfill(3)}" for i in range(31, 66)], # 30–64세
"노년": [f"in_age_{str(i).zfill(3)}" for i in range(66, 79)], # 65세 이상
}
이제 폴더 안의 모든 txt 파일을 읽어서 연도별로 묶고, 각 격자 단위로 인구 수를 합산해준다. 이후 격자마다 별도 파일로 분리되어있는 값들을 연도별로 합쳐서 하나의 파일로 만든다. 이 과정을 거치면 year_dict 안에 {'2010': DataFrame, '2023': DataFrame} 형태로 데이터가 저장된다.
txt_files = [f for f in os.listdir(extract_folder) if f.endswith(".txt")]
year_dict = {}
for file in txt_files:
txt_path = os.path.join(extract_folder, file)
df = pd.read_csv(
txt_path, sep="^", header=None,
names=["year", "GRID_10K_C", "variable", "value"],
encoding="utf-8", dtype={"GRID_10K_C": str}
)
year = str(df["year"].iloc[0])
# 격자별 총인구 계산
df_total = df.groupby("GRID_10K_C", as_index=False)["value"].sum()
df_total.rename(columns={"value": f"{year}_총인구"}, inplace=True)
# 연령대별 인구 합산
for label, codes in bins.items():
subset = df[df["variable"].isin(codes)]
df_age = subset.groupby("GRID_10K_C", as_index=False)["value"].sum()
df_age.rename(columns={"value": f"{year}_{label}"}, inplace=True)
df_total = df_total.merge(df_age, on="GRID_10K_C", how="outer")
# 같은 연도끼리 병합
if year in year_dict:
year_dict[year] = (
pd.concat([year_dict[year], df_total])
.groupby("GRID_10K_C", as_index=False)
.sum(numeric_only=True)
)
else:
year_dict[year] = df_total
GeoJSON 파일에 left join하기
연도별 데이터를 모두 병합하고, geojson 파일(격자 경계)을 기준으로 조인해준다. 이 때 키 값은 격자 코드 고유 식별자인 "GRID_10K_C" 칼럼을 기준으로 left join하면 된다. 아래 코드처럼 join을 수행하면 모든 격자에 인구정보가 매칭된다. 합쳐진 데이터는 geojson 파일로 내보내면 전처리는 끝이다.
merged_pop = None
for year, df_year in year_dict.items():
merged_pop = df_year if merged_pop is None else pd.merge(
merged_pop, df_year, on="GRID_10K_C", how="outer"
)
gdf_merged = gdf.merge(merged_pop, on="GRID_10K_C", how="left")
output_path = "전국격자_연령대별인구.geojson"
gdf_merged.to_file(output_path, driver="GeoJSON", encoding="utf-8")
3. QGIS에서 시각화하기
이제 가공이 끝난 전국격자_연령대별인구.geojson 파일을 QGIS에서 불러오자. 속성 테이블을 열어보면 격자에 연도별, 연령별 인구 통계 값이 잘 붙은걸 확인할 수 있다. 이제 이 격자를 이용해 인포그래픽 형태의 지도를 만들거다.

일단 먼저 시각화의 기본 베이스로 쓸 격자 중심점(Point)을 만들어주자. 툴박스에서 벡터 도형 도구 → 중심점을 찾아 실행하면 된다. 입력 레이어에는 전국격자_연령대별인구.geojson을 선택하고 실행해주면 된다. 그럼 아래처럼 격자마다 중심 point가 생성되는데 테두리선 없이, 회색조로 색상을 주면 깔끔한 배경 베이스가 만들어진다.

그리고 이제 단계구분도를 줄건데 중심점 레이어를 하나 복사한 뒤 레이어 스타일 작업 → 단계구분에서 스타일을 입히면 된다. 그레디언트 색상을 입력해주고 매소드는 색상, 범주는 내추럴 브레이크로 나누되 수동으로 조금 조절해주면 된다. 그리고 뒤에 베이스 지도를 깔아놨기 때문에 제일 첫 번째 범례(- 미만)는 비활성화 해서 베이스 지도 위에 깔아주면 완성!

이제 인포그래픽 형태의 전국 인구 격자 지도가 완성됐다. 인구가 많은 지역은 진하게, 적은 지역은 연하게 표현되어 전국 인구 분포가 한눈에 들어온다. 다른 연도나 연령대별로 보고 싶을 때는 같은 방법으로 단계 구분 값만 바꿔주면 된다. 다 하고 나니 너무 간단하네..ㅎㅎ 무튼 우리나라 인구 통계를 보여주는 간단한 인포그래픽 완성이다!
