2026년 2월 과업 수행 내역
평생교육 정보 접근 격차 시각화 플랫폼
핵심 기능 구현 보고서
(주)옥소폴리틱스 · tobl.ai
1. 과업 개요 및 성과 요약
1.1 2월 과업 목표
1월에 수립한 구조 설계서를 기반으로, 실제 227개 시군구 데이터를 활용한 Choropleth 지도 시각화와 지역 간 비교 분석 기능을 구현하였습니다. 사용자 경험 중심의 인터랙션 설계를 통해 직관적인 데이터 탐색 환경을 구축하는 것을 목표로 하였습니다.
1.2 주요 구현 성과
- •Choropleth 지도: 5개 지표(물리적·지적·사회적 접근, 정보 접근, IA 지수)의 분위수 기반 색상 스케일 시각화
- •지역 비교 페이지: 레이더 차트, 막대 차트, 비교 테이블을 통한 두 지역 간 다차원 비교 분석
- •지도 인터랙션: 지역 검색, 하이라이트 줌, 시도 경계 오버레이, 포커스 퀵링크 등 UX 개선
- •통계 대시보드: 분포 차트, 요약 통계, 지역 상세 패널을 통한 데이터 탐색 환경 구축
2. Choropleth 지도 시각화
2.1 지표 체계
227개 시군구 및 17개 시도 단위로 5개 지표를 분위수(Quantile) 기반 색상 스케일로 시각화합니다.
| 지표 ID | 지표명 | 설명 |
|---|---|---|
| physicalAccess | Physical Access | 물리적 접근 — 교육 시설 및 인프라 접근성 |
| intellectualAccess | Intellectual Access | 지적 접근 — 교육 프로그램 다양성 및 품질 |
| socialAccess | Social Access | 사회적 접근 — 교육 참여 기회의 사회적 포용성 |
| informationAccess | Information Access | 정보 접근 — PC1 Score 기반 종합 정보 접근도 |
| iaIndex | IA Index | 0–100 지수 — 전체 지표 종합 정보 접근 격차 지수 |
2.2 분위수 색상 스케일
데이터 분포 기반 5분위(Quantile) 방식으로 색상을 할당하여, 극단값의 영향을 최소화하고 상대적 비교가 용이하도록 설계하였습니다.
Q5 (상위 20%)
Q4
Q3
Q2
Q1 (하위 20%)
2.3 공간 단위 전환
- •시·군·구 (기본): 227개 행정구역 단위의 상세 분석. 시도 간 구분을 위해 교대 채도(alternating opacity) 기법 적용
- •시·도: 17개 광역 단위 집계 데이터 시각화. 시도 라벨 오버레이 동시 표시
3. 데이터 수급 및 적재
3.1 데이터 수급 및 적재
제공받은 227개 시군구 및 17개 시도의 평생교육 정보 접근 격차 지표 데이터를 JSON 형식으로 가공하여 정적 데이터 파일로 적재하였습니다. 2024년 기준 데이터를 연도별 디렉토리 구조로 관리하여 향후 연도 추가에 대비하였습니다.
public/data/
└── 2024/
├── sigungu-indicators.json (227건, 약 54KB)
└── sido-indicators.json (17건, 약 4KB)
3.2 시군구 데이터 스키마
| 필드 | 타입 | 설명 |
|---|---|---|
| sido | string | 시도명 (예: 강원특별자치도, 경기도) |
| sigungu | string | 시군구명 (예: 영월군, 수원시) |
| rank | number | IA 지수 기준 전국 순위 |
| n | number | 평생교육 기관 수 |
| physicalAccess | number | 물리적 접근 점수 |
| intellectualAccess | number | 지적 접근 점수 |
| socialAccess | number | 사회적 접근 점수 |
| informationAccess | number | 정보 접근 PC1 Score |
| iaIndex | number | 종합 IA 지수 (0–100) |
3.3 GeoJSON 지리 데이터
Choropleth 지도 렌더링을 위해 시도 및 시군구 행정구역 경계 GeoJSON 파일을 준비하였습니다.
| 파일 | 설명 |
|---|---|
| korea-sido.json | 17개 시도 경계 GeoJSON (행정구역 코드, 시도명 포함) |
| korea-sigungu.json | 227개 시군구 경계 GeoJSON (시도, 시군구, 행정코드 포함) |
3.4 데이터 활용 흐름
- •useIndicatorData 훅: 연도/공간단위/지표 조합에 따라 JSON 파일을 fetch하고, 지도 렌더링용 dataMap(지역→값) 구성
- •useGeoData 훅: 선택된 공간 단위(시도/시군구)에 해당하는 GeoJSON 파일을 로드하여 Leaflet에 전달
- •useSigunguData 훅: 비교 페이지 및 지역 상세 패널에서 전체 시군구 데이터 배열을 활용
4. 지도 인터랙션 설계
3.1 지도 인터랙션 기능
| 기능 | 설명 |
|---|---|
| 지역 검색 | 칩(Chip) 스타일 UX로 지역을 검색하고 선택 상태를 직관적으로 표시. 시도별 그룹핑된 드롭다운 제공. |
| 하이라이트 줌 | 검색 또는 선택된 지역으로 자동 flyToBounds 이동. 선택 지역에 pulse 애니메이션 테두리 적용, 비선택 지역 투명도 감소(dim) 처리. |
| 시도 경계 오버레이 | 시군구 모드에서 시도 경계를 흰색 2px 라인으로 오버레이하여 광역 구분 명확화. 호버 시에도 경계가 유지되도록 imperative 스타일링 적용. |
| 시도 라벨 | 17개 시도명을 지도 위에 텍스트 라벨로 표시. 흰색 text-shadow로 가독성 확보, pointer-events 비활성화. |
| 포커스 퀵링크 | 전국·수도권·영남·호남·강원 등 주요 권역으로 즉시 이동할 수 있는 필 버튼 UI. |
| 마우스 호버 툴팁 | 각 지역에 마우스를 올리면 지역명과 현재 선택된 지표 값을 실시간으로 표시하는 스티키 툴팁. |
3.2 기술적 해결 사항
- •호버 성능 최적화: GeoJSON 전체 재렌더링 대신 Leaflet의 setStyle() API를 사용한 imperative 스타일 변경으로 호버 시 시도 경계선 유지 및 성능 개선
- •레이어 관리: 시군구 GeoJSON 위에 시도 경계 GeoJSON을 별도 레이어로 렌더링하여 시각적 계층 구분
- •SSR 호환: Leaflet 컴포넌트를 next/dynamic으로 SSR 비활성화하여 서버 렌더링 오류 방지
5. 지역 비교 분석 기능
4.1 비교 분석 페이지 구성
두 시군구를 선택하여 5개 지표를 다각도로 비교할 수 있는 전용 페이지(/compare)를 구현하였습니다. 레이더 차트, 막대 차트, 비교 테이블의 3가지 시각화 방식을 제공합니다.
| 컴포넌트 | 기능 |
|---|---|
| RegionSelector | 시도별 그룹핑된 검색 가능 드롭다운. 텍스트 입력으로 실시간 필터링. |
| ComparisonRadar | Recharts RadarChart로 5개 지표를 퍼센타일(0–100) 정규화하여 오버레이 비교. |
| ComparisonBar | Recharts BarChart로 지표별 두 지역 값을 나란히 비교하는 그룹 막대 차트. |
| ComparisonTable | 5개 지표의 값, 차이, 높은 쪽 강조를 보여주는 비교 테이블. |
4.2 데이터 정규화
레이더 차트에서 스케일이 다른 5개 지표를 동일한 축으로 비교하기 위해, 전체 227개 시군구 데이터에서 각 지표별 퍼센타일 순위를 계산하여 0–100 범위로 정규화합니다. 이를 통해 절대값이 아닌 상대적 위치를 기준으로 지역 간 비교가 가능합니다.
4.3 색상 체계
6. 사이드바 및 통계 패널
5.1 사이드바 패널
| 기능 | 설명 |
|---|---|
| 공간 단위 전환 | 시·군·구 / 시·도 토글 버튼으로 분석 단위 전환 |
| 연도 선택 | 드롭다운 방식의 연도 셀렉터 (현재 2024년) |
| 지표 아코디언 | Lucide 아이콘 + 영문/한글 이중 라벨. 선택 시 아코디언 펼침으로 미니 레전드 표시 |
| MiniLegend | 선택된 지표의 6색 그라디언트 바 + 최솟값/최댓값 표시 |
| 지역 상세 패널 | 지도에서 시군구 클릭 시 5개 지표 값과 순위를 사이드바 하단에 표시 |
5.2 통계 패널
지도 하단에 현재 선택된 지표의 요약 통계와 분포 차트를 표시하는 패널을 구현하였습니다.
| 컴포넌트 | 설명 |
|---|---|
| StatCard | 평균, 중앙값, 최솟값, 최댓값, 표준편차, 데이터 수 등 6개 요약 통계 |
| DistributionChart | Recharts BarChart 기반 분포 히스토그램 (5분위 구간) |
7. 파일 구조 및 의존성
6.1 신규·수정 파일 목록
2월 과업에서 신규 생성 및 주요 수정된 파일 목록입니다. 총 34개 파일, 약 4,400줄의 코드가 추가되었습니다.
| 파일 경로 | 설명 |
|---|---|
| src/app/page.tsx | 메인 대시보드 (상태 관리, 레이아웃 조합) |
| src/app/compare/page.tsx | 지역 비교 페이지 |
| src/components/map/KoreaMap.tsx | Choropleth 지도 (GeoJSON 렌더링, 호버, 클릭) |
| src/components/map/MapHighlightController.tsx | 검색 하이라이트 줌 컨트롤러 |
| src/components/map/MapLegend.tsx | 분위수 색상 범례 |
| src/components/map/RegionSearch.tsx | 칩 스타일 지역 검색 |
| src/components/map/SidoLabels.tsx | 시도명 텍스트 라벨 오버레이 |
| src/components/map/FocusLinks.tsx | 권역 퀵링크 버튼 |
| src/components/layout/Sidebar.tsx | 아코디언 사이드바 |
| src/components/layout/MiniLegend.tsx | 인라인 미니 레전드 |
| src/components/RankingPanel.tsx | 순위 패널 |
| src/components/RegionDetailPanel.tsx | 지역 클릭 상세 패널 |
| src/components/stats/StatsPanel.tsx | 통계 요약 + 분포 차트 패널 |
| src/components/compare/*.tsx | RegionSelector, ComparisonRadar, ComparisonBar, ComparisonTable |
| src/hooks/useGeoData.ts | GeoJSON 데이터 로드 훅 (시도/시군구) |
| src/hooks/useIndicatorData.ts | 지표 데이터 로드 + dataMap 구성 훅 |
| src/hooks/useRankingData.ts | 순위 데이터 계산 훅 |
| src/hooks/useSigunguData.ts | 시군구 전체 데이터 로드 훅 |
| src/utils/quantile.ts | 분위수 스케일 빌더 + 색상 매핑 |
| src/utils/colorScale.ts | 지표 라벨, 값 포맷터 |
| src/utils/statsCompute.ts | 요약 통계 계산 유틸 |
6.2 의존성 추가
| 패키지 | 용도 |
|---|---|
| lucide-react | 사이드바 지표 아이콘 (Gauge, Radar, Landmark, GraduationCap, Users) |