"우리 관할에 소화전이 몇 개 있나"는 표로 답하지만, "어디가 부족한가"는 지도라야 답합니다. 소방용수는 개수가 아니라 분포가 중요하기 때문입니다 — 100개가 도심에 몰려 있고 외곽이 비어 있다면, 총량은 충분해도 그 외곽은 위험 구역입니다. 이 안내서는 소방용수 위치와 건물 위치를 공간적으로 겹쳐, 도달 반경 밖 공백 구역을 지도로 찾아냅니다.
이 안내서는 프로젝트 아이디어 소방용수시설 접근성 분석 지도의 기술 배경을 설명합니다.
- 소방용수·건물·관할 경계의 좌표계와 기준 시점을 대조할 수 있습니다.
- 중복·결측·이설 기록을 점검한 뒤 최근접·버퍼 분석을 수행할 수 있습니다.
- 직선거리 스크리닝과 도로 경로·현장 확인의 역할을 나눌 수 있습니다.
- 지도의 공백 후보를 확정 판정이 아닌 사람 확인 우선순위로 설명할 수 있습니다.
데이터와 도구
공공데이터 지도에서 받습니다.
| 데이터 | 출처 | 쓰는 것 |
|---|---|---|
| 전국소방용수시설 표준데이터 | 공공데이터포털 | 소화전·저수조 좌표·유형 |
| 건물/주거지 | 건축물대장·브이월드 | 분석 대상 지점 |
| 행정경계 | SGIS·브이월드 | 관할 범위·집계 단위 |
도구는 레포 레이더의 GEO 클러스터 — geopandas(공간 연산)·folium(지도 시각화)입니다.
1. 좌표계 — 여기서 대부분의 오류가 난다
공간분석의 가장 흔한 실수는 좌표계입니다. 공공데이터의 경위도(위도·경도, EPSG:4326)는 "도(度)" 단위라 그대로 거리를 재면 엉터리가 나옵니다 — "0.003도"는 위치에 따라 실제 거리가 다릅니다. 거리를 재려면 미터 단위 투영좌표계로 변환해야 합니다. 한국 표준은 EPSG:5179(UTM-K)입니다.
왜 이런 일이 생기는지는 지구본과 종이지도의 차이로 이해하면 쉽습니다. 둥근 지구를 평면에 펴는 방식이 좌표계인데, 경위도(EPSG:4326)는 세로줄·가로줄을 도(度)로 매긴 격자라 한 칸이 나타내는 실제 거리가 위치마다 다릅니다 — 적도에서 멀어질수록 경도 한 칸의 실제 폭이 좁아지기 때문입니다. 반면 투영좌표계(UTM-K)는 우리나라 영역을 아예 '미터 자'로 바꿔 편 것이라, 두 점 좌표를 빼면 곧바로 미터가 나옵니다. 그래서 거리를 잴 땐 미터 자로 갈아탄 뒤 재야 합니다.
import geopandas as gpd # 소방용수·건물을 GeoDataFrame으로 (원본은 보통 경위도 EPSG:4326) water = gpd.read_file("fire_water.geojson").set_crs(4326, allow_override=True) bldg = gpd.read_file("buildings.geojson").set_crs(4326, allow_override=True) # 거리 계산 전 반드시 미터 단위 투영좌표계로 — 한국 표준 UTM-K water_m = water.to_crs(5179) bldg_m = bldg.to_crs(5179)
set_crs(4326, allow_override=True)는 좌표값·축 순서·원천 메타데이터를 살펴보지 않고 “이 값은 EPSG:4326”이라는 꼬리표를 덮어씁니다. 원천이 다른 투영좌표이거나 CRS가 불명인데 이 줄을 그대로 쓰면, 잘못된 선언을 기준으로 to_crs(5179)가 변환해 이후 거리도 함께 왜곡됩니다. 실제 분석에서는 원천 메타데이터·데이터 사전·좌표 범위·알려진 기준 지점을 먼저 대조해 원래 CRS를 확인한 뒤 선언해야 합니다.빠뜨리면 어떻게 되는지 숫자로 보면 분명합니다. 200m 떨어진 두 지점을 경위도 그대로 재면 약 0.0018 같은 정체불명의 값이 나옵니다(도 단위라 그렇습니다). 변환 후 재면 200이 나오죠. 문제는 앞의 0.0018이 뒤에서 쓸 "200m 초과" 필터(> 200)를 통과하지 못해, 진짜 공백 지점이 멀쩡한 곳으로 둔갑한다는 것입니다.
to_crs(5179) 한 줄을 빠뜨리면 이후 모든 거리·버퍼가 무의미해집니다. 그런데 코드는 에러 없이 돌고 숫자도 그럴듯하게 나옵니다 — 위험도 예측의 데이터 누수처럼, 조용히 틀리는 종류의 실수라 가장 위험합니다. 분석 시작 전 좌표계부터 확인하세요.2. 최근접 거리 — 각 지점에서 가장 가까운 용수까지
각 건물에서 가장 가까운 소방용수까지의 거리를 잽니다. geopandas의 최근접 공간조인이 이걸 한 번에 해 줍니다.
# 각 건물에 가장 가까운 소방용수를 붙이고, 그 거리(m)를 함께 계산 joined = gpd.sjoin_nearest(bldg_m, water_m, how="left", distance_col="용수거리m") print(joined["용수거리m"].describe()) # 분포 — 중앙값·최댓값을 본다 공백 = joined[joined["용수거리m"] > 200] # 도달 기준 초과(예: 200m) print(f"공백 건물 {len(공백)}개 / 전체 {len(joined)}개")
용수거리m결측을 따로 처리하지 않습니다NaN > 200비교가False가 되어 판단 불가 후보를 잡지 못합니다- 실제 분석:
joined[joined["용수거리m"].isna()]를 별도 후보로 분리해야 합니다: - 거리 데이터가 없는 용수시설 있는가?
- 건물 좌표가 누락되었는가?
- CRS 변환 오류인가?
- 거리 기준 공백 + NaN 판단 불가를 합쳐 최종 해석합니다
기준 거리(예 200m)는 관할 특성·장비·규정에 맞춰 정합니다. 하나로 고정하지 말고 100·200·300m로 나눠 단계별 공백을 보는 편이 유용합니다.
3. 도달 반경(버퍼) — 용수가 덮는 범위
거꾸로, 각 소방용수가 반경 안에서 덮는 범위를 그려 겹치지 않는 빈 곳을 봅니다. 버퍼(buffer)는 각 점 둘레에 원을 그립니다 — 투영좌표계라 단위가 미터입니다.
covered = water_m.buffer(200).union_all() # 모든 용수의 200m 도달 범위 합집합 # 관할 경계에서 도달 범위를 빼면 = 공백 구역 gap_area = boundary_m.geometry.union_all().difference(covered)
4. 지도로 — 숫자가 아니라 눈으로
공백 건물과 공백 구역을 지도에 얹어야 의사결정자에게 전달됩니다. folium으로 대화형 지도를 만듭니다(시각화는 경위도로 되돌려서).
import folium m = folium.Map(location=[37.55, 126.9], zoom_start=13, tiles="CartoDB positron") # 공백 건물(빨강) · 소방용수(파랑)를 4326으로 되돌려 표시 for _, r in 공백.to_crs(4326).iterrows(): folium.CircleMarker([r.geometry.y, r.geometry.x], radius=3, color="crimson").add_to(m) m.save("소방용수_공백.html")
5. 한계 — 직선거리는 도달시간이 아니다
이 분석의 가장 큰 한계를 분명히 알아야 합니다. 직선거리(as-the-crow-flies)는 소방차 실제 도달거리가 아닙니다. 강·철길·일방통행·경사가 가로막으면 200m 안의 용수도 실제로는 멀 수 있습니다. 더 정밀하게 하려면 도로 네트워크 기반 경로 거리를 써야 하지만, 그건 훨씬 무거운 분석입니다.
| 지표 | 이 분석 | 현실 |
|---|---|---|
| 거리 | 직선 | 도로 경로 |
| 함정 | 강·철길을 무시 | 실제 우회 필요 |
| 용도 | 1차 스크리닝 | 후보 구역 좁히기 |
설계 판단
분석 단계를 높일수록 현실에 가까운 대신 데이터·계산·운영 비용이 늘어납니다. 첫 지도에서부터 현실을 완벽히 재현하려 하기보다, 질문에 필요한 정밀도를 단계별로 고릅니다.
| 방식 | 맞는 질문 | 트레이드오프 | 사람이 확인할 것 |
|---|---|---|---|
| 직선거리·버퍼 스크리닝 | 넓은 범위에서 현장 확인 후보를 줄일 때 | 도로·지형·통행 제약을 반영하지 못함 | 공백 후보의 좌표·시설 상태 |
| 도로 네트워크 경로 비교 | 우회·단절 경로가 중요하고 신뢰할 수 있는 도로 자료가 있을 때 | 네트워크 갱신과 경로 조건 설계가 필요 | 경로 자료의 최신성과 통행 조건 |
| 현장 확인 중심 | 좌표·시설 상태·도로 자료를 믿기 어려운 후보일 때 | 여러 곳을 한번에 보기 어려움 | 실제 접근 가능성과 시설 상태 |
운영 확인 기록
분석 결과와 함께 다음 세 계보를 남기면 다시 계산할 때 어디서 차이가 생겼는지 추적할 수 있습니다.
- 좌표계 확인: 원천에 선언된 CRS, 실제로 해석한 CRS, 계산 단위, 좌표 범위를 기록합니다. 알려진 합성 기준 지점을 지도에 올려 축척·축 바꾸기·단위 오해를 계산 전에 걸러냅니다.
- 네트워크 거리 확인: 도로 그래프의 기준일·통행 조건·경로 없음 건수를 기록합니다. 경로를 못 찾은 지점을 거리 0이나 공백으로 바꾸지 않고 판단 불가로 보내며, 직선거리와 경로 거리가 크게 다른 표본을 사람이 확인합니다.
- 최신성 확인: 용수·건물·경계·도로별 원천 기준일과 추출일을 따로 남깁니다. 폐지·이설·신설 확인일이 서로 다르면 한 날의 현황처럼 합치지 않고, 시점 불일치와 현장 확인 필요를 지도에 함께 표시합니다.
운영 시나리오
다음은 특정 지역·시설의 실제 상태와 무관한 가상 데이터 운영 사례입니다. 공백 지도의 모양이 달라졌을 때 현실이 바뀐 것으로 단정하지 않고 입력 계보를 먼저 따라갑니다.
가상 시나리오 1: 누락된 CRS를 경위도로 강제 선언해 거리가 왜곡된 경우
- 탐지: 코드는 오류 없이 끝났지만 용수 점이 예상 범위 밖에 놓이고, 알려진 두 기준 지점 사이의 계산 거리도 원천 지도에서 확인한 관계와 맞지 않았습니다. 본문의
set_crs(..., allow_override=True)자체는 이 이상을 탐지하지 않습니다. - 원인 가설: CRS가 없거나 다른 투영좌표인 원천을 좌표값 확인 없이 EPSG:4326으로 강제 선언한 뒤 EPSG:5179로 변환해, 틀린 출발 좌표계가 모든 거리 계산에 전파됐다고 봅니다.
- 대응: 공백 지도 공유를 멈추고 원본 파일을 다시 열어 원천 메타데이터·데이터 사전·좌표 범위·알려진 기준 지점을 대조합니다. 원래 CRS를 확인한 뒤에만 선언하고 투영하며, 결과에 맞추려고 좌표 숫자를 임의로 이동시키지 않습니다.
- 재발 확인: CRS가 올바른 합성 기준 지점과 CRS 누락·오지정 픽스처를 별도로 두고, 거리 계산 전에 선언 CRS·좌표 범위·기준 지점 위치가 맞는지 사람이 확인합니다. 이 검사는 본문의 최소 예제 밖에 별도로 추가해야 합니다.
가상 시나리오 2: 최근접 거리가 NaN이라 공백 필터에서 빠진 경우
- 탐지: 전체 건물 수와 거리 기준 결과를 대조하니 일부 행이 충분 후보와 공백 후보 어디에도 없었고, 해당
용수거리m값은NaN이었습니다. - 원인 가설: 본문의
joined["용수거리m"] > 200비교에서NaN은False가 되므로, 최근접 용수를 찾지 못한 행이 공백이 아닌 정상처럼 필터 밖으로 빠졌다고 봅니다. - 대응: 결과 공유를 멈추고
isna()로 거리 결측 행을 별도 판단 불가 후보로 분리합니다. 빈 용수 자료·잘못된 geometry·조인 범위 문제를 확인하기 전에는 공백이나 충분으로 바꾸지 않습니다. - 재발 확인: 정상 거리·기준 초과·거리
NaN합성 행을 함께 실행해 세 집합의 합이 전체와 일치하고,NaN행은 거리 기준 결과가 아니라 판단 불가 큐에 남는지 확인합니다.
한계와 리스크
| 리스크 | 발생 조건 | 영향 | 완화·사람 승인 |
|---|---|---|---|
| 좌표계·축척 오해 | 경위도와 미터 단위 좌표를 혼용하거나 CRS를 틀리게 지정함 | 거리·버퍼·공백 면적이 의미 없게 변함 | 원천 CRS·단위를 기록하고 알려진 표본 지점을 사람이 지도에서 확인 |
| 스냅샷 시점 불일치 | 건물·용수·경계가 서로 다른 기준일임 | 공백 또는 충분 후보가 데이터 버전 차이로 생김 | 기준일을 지도와 보고서에 표시하고 시점 불일치 구역은 담당자가 판단 불가로 승인 |
| 우선순위의 운영 명령 오인 | 직선거리 공백 후보를 현장 확인 없이 확정 판정으로 설명함 | 지형·도로·시설 상태를 놓친 자원 판단 | 결과를 확인 후보로만 표시하고 점검·증설·배치는 소속 기관 기준과 담당자 승인 필요 |
자주 묻는 질문
Q. 직선거리 기준 안에 있으면 접근성이 충분한가요?
아닙니다. 직선거리는 넓은 범위의 확인 후보를 줄이는 스크리닝입니다. 도로·지형·시설 상태·소속 기관 기준을 현장에서 따로 확인합니다.
Q. 같은 좌표의 시설은 자동으로 하나로 합쳐도 되나요?
좌표만으로는 부족합니다. 고유 ID·시설 유형·상태·기준일을 함께 보아야 같은 시설의 중복인지, 한 지점의 다른 시설인지 구분할 수 있습니다.
Q. 데이터가 없는 구역을 공백으로 표시해도 되나요?
결측과 공백은 다릅니다. 본문 코드에서는 거리 NaN이 > 200 비교를 통과하지 않아 자동으로 판단 불가가 되지 않습니다. 최신 시설·경계 자료가 없거나 최근접 거리가 NaN이면 isna()로 별도 판단 불가 후보를 만들어야 자료 부재를 시설 부재나 충분으로 오해하지 않습니다.
Q. 지도만 보고 점검·증설 순서를 확정해도 되나요?
안 됩니다. 이 지도는 현장 확인 후보를 정렬할 뿐입니다. 실제 점검·증설·자원 배치는 현장 상태와 소속 기관의 공식 기준을 담당자가 확인해 결정합니다.
핵심 정리
- 좌표계·고유 ID·기준일은 거리 계산 전에 통과해야 할 입력 계약입니다.
- 직선거리와 버퍼는 현장 확인 후보를 줄이는 1차 스크리닝입니다.
- 현재 예제의
> 200필터는 거리NaN을 잡지 못하므로isna()판단 불가 후보를 별도로 분리합니다. - 결측·낡은 자료·시점 불일치는 공백이 아니라 판단 불가로 분리합니다.
- 지도에는 후보와 함께 가정·기준일·불확실성을 표시하고 최종 판단은 사람에게 둡니다.
다음 단계
- 소방 공공데이터·API 지도: 소방용수·공간·경계 자료의 출처와 인증·갱신 조건을 확인합니다.
- 공공 API 데이터 표준화: 페이지·필드명·고유 ID·중복을 정리해 공간 분석의 입력 경계를 다집니다.
- 지역별 화재 위험도 예측: 공백 지도와 예측 순위를 모두 사람 확인 후보로 제한하는 원칙을 연결합니다.
사람 검토 체크리스트
- [ ] 거리·버퍼 계산 전에 미터 단위 투영좌표계(EPSG:5179)로 변환했습니다. - [ ] 소방용수 표준데이터의 좌표 정확성·최신성을 확인했습니다(폐지·이설 반영). - [ ] 도달 기준 거리를 관할 특성에 맞게 정하고, 여러 단계로 나눠 봤습니다. - [ ] 결과가 직선거리 기반이라는 한계를 보고서에 명시했습니다. - [ ] 공백 구역은 현장 확인 우선순위로만 쓰고 단정하지 않았습니다.