# 확장 · 외부 라이브러리 — 실습 입력

중급(2-2)과 캡스톤(2-4)에서 만든 지도는 **외부 참조가 하나도 없었습니다.**
이 세션은 반대쪽을 봅니다. 라이브러리 하나를 들이면 무엇을 얻고 무엇을 내주는지,
그 판단을 문서로 남기는 법까지가 과제입니다.

지도를 더 예쁘게 만드는 시간이 아닙니다. **도입 여부를 스스로 판정하는** 시간입니다.

## 이 폴더에 없는 것

**실제 입력 데이터가 들어 있지 않습니다.** 서울시 공개데이터를 직접 내려받는 것이
1단계 과제입니다. 내려받는 과정에서 컬럼명·인코딩·좌표 범위를 확인하게 됩니다.

완성본 웹앱과 정답키도 없습니다. 교안의 프롬프트로 직접 만듭니다.

## 예시데이터/ — 형식 확인용

실제 데이터를 받기 전에 **어떤 모양의 파일이 오는지** 미리 보라고 넣어 둔 가상 파일입니다.

| 파일 | 내용 |
|---|---|
| `예시_문화공간(가상).csv` | 218행 — 실제 데이터셋과 같은 컬럼 표기 |
| `예시_인구_구별(가상).csv` | 자치구 25행 |

**실습에는 쓰지 않습니다.** 시설명은 `예시시설 001`이고 좌표는 자치구 근처로 흩뿌린
무작위 값입니다. 실제 시설 위치가 아닙니다.

다만 실제 공개데이터에서 늘 마주치는 결함 네 가지를 일부러 섞어 두었습니다 —
**좌표 없음 2건 · 서울 범위 밖 1건 · 위도와 경도가 뒤바뀐 행 1건.** 1단계 매핑에서
이 네 건을 찾아내고 건수를 밝히는지가 점검 지점입니다. 만든 웹앱에 이 파일을 올려
`214행 / 제외 4건`이 나오면 매핑이 제대로 된 것입니다.

## 수업 전에 내려받을 것

인터넷이 되는 PC에서 미리 받아 두십시오. **수업 중에 받으면 시간이 모자랍니다.**

| 파일 | 데이터셋 | 받는 곳 |
|---|---|---|
| `input/문화공간.csv` | 서울시 문화공간 정보 | 서울 열린데이터광장 `OA-15487` |
| `input/인구_구별.csv` | 서울시 주민등록인구 (연령별/구별) | 서울 열린데이터광장 `OA-12235` |

1. <https://data.seoul.go.kr> 에서 데이터셋 번호나 이름으로 검색합니다.
2. **CSV**로 내려받습니다.
3. 글자가 깨지면 CP949입니다. 엑셀에서 열어 **UTF-8로 다시 저장**합니다.
4. 위 이름으로 바꿔 `input/`에 넣습니다.

> 문화공간 정보에는 `문화시설명 · 주제분류 · 주소 · 자치구 · 위도 · 경도`가 들어 있습니다.
> **컬럼명은 갱신 시점에 따라 다릅니다.** 그래서 1단계가 "컬럼명을 가정하지 말고
> 헤더부터 읽어라"입니다. 캡스톤에서 배운 그 단계를 그대로 씁니다.

두 데이터 모두 **공공누리 제1유형(출처표시)** 입니다. 산출물에 출처를 밝히면
상업적 이용과 변경까지 허용됩니다.

## 작업 폴더는 직접 만듭니다

중급과 같은 구조입니다.

```
내작업폴더/
  CLAUDE.md     상시 규칙 — 2-2의 것을 가져오되 한 줄을 고칩니다
  input/        내려받은 CSV 2개 — 읽기 전용
  working/      판단의 흔적 (계획 · 라이브러리 검토서 · 감사)
  output/       산출물 (접근성 표 · 지도 웹앱 · 보고서)
```

## CLAUDE.md에서 고칠 한 줄

2-2의 `CLAUDE.md`에는 이렇게 되어 있습니다.

```
웹 산출물은 외부 라이브러리 없이 단일 HTML 파일로 만들고
데이터를 외부로 전송하지 않는다.
```

이 세션에서는 앞부분이 성립하지 않습니다. 규칙을 지우지 말고 **조건을 붙여 고칩니다.**

```
웹 산출물은 단일 HTML 파일로 만든다. 외부 라이브러리는 working/library_review.md에
검토 결과를 남기고 승인된 것만 쓴다. 버전은 반드시 고정한다.
분석 대상 데이터는 어떤 경우에도 외부로 전송하지 않는다.
```

**규칙을 없애는 것과 조건을 다는 것은 다릅니다.** 감사에서 묻는 것은 "왜 썼나"가
아니라 "쓰기로 한 근거가 어디 있나"입니다. 그 근거를 만드는 것이 3단계 과제입니다.

## 무엇이 밖으로 나가는지부터 정확히 알아야 합니다

이 세션에서 가장 자주 어긋나는 이해입니다. 나가는 것과 나가지 않는 것을 구분하십시오.

| 나가는 것 | 나가지 않는 것 |
|---|---|
| 라이브러리 파일 요청 (CDN) | 내려받은 CSV의 내용 |
| 화면에 보이는 영역의 지도 타일 요청 | 시설 목록 · 좌표 · 분석 결과 |
| 그 요청에 담기는 **어느 지역을 보고 있는지** | 계산식 · 보고서 문구 |

**내 데이터가 서버로 올라가는 것이 아닙니다.** 라이브러리는 브라우저에서 돌고,
CSV는 내 PC에서만 읽힙니다. 다만 **"강남구 일대를 확대해 보고 있다"는 사실**은
타일 요청으로 드러납니다. 이것이 우리 기관에서 허용되는 범위인지가 판단할 문제입니다.

## 쓰는 것

| | 내용 | 조건 |
|---|---|---|
| 라이브러리 | MapLibre GL JS | BSD-3-Clause · API 키 불필요 |
| 배경지도 | OpenFreeMap | 가입·키·한도 없음 · 출처표시 필수 |
| 지형 (선택) | AWS Terrain Tiles | 3D 지형을 볼 때만 |

배경지도 출처 문구는 화면에 반드시 남깁니다.

```
OpenFreeMap © OpenMapTiles Data from OpenStreetMap
```

## 내부망이라면

타일이 안 받아져 **배경이 비어 있는 화면**이 나옵니다. 오류가 아니라 정상입니다.
이때 어떻게 할지가 5단계 과제입니다 — 2-2에서 쓰던 캔버스 방식으로 되돌아가는
폴백을 함께 만들어 둡니다. 그래야 같은 파일을 두 환경에서 모두 씁니다.

## 참고 — 도착점이 어떤 모습인지

같은 스택으로 만든 공개 사례가 있습니다. 서울 문화시설 약 2,460곳을 3D로 얹고
커널 밀도·500m 격자·접근성 공백(800m 초과)까지 얹은 연구용 프로토타입입니다.

**Seoul Cultural Facilities Digital Twin** — <https://jason-j-kim.github.io/seoul-culture-3d/>

수업에서 이만큼 만들지는 않습니다. **구조만 참고**하고 실습은 우리 데이터로
처음부터 만듭니다. 이 사이트도 외부 참조는 MapLibre 한 줄과 타일 두 종이 전부입니다.
"라이브러리를 많이 쓴다"와 "잘 고른 하나를 쓴다"는 다릅니다.

---

데이터는 실제 공개데이터입니다. 좌표가 진짜이므로 배경지도 위에 제자리에 찍힙니다.
2-2·2-4의 좌표는 가상이었습니다 — 그래서 그쪽은 배경지도를 깔면 오히려 틀린 화면이 됩니다.
