OpenStreetMap 에서 뽑은 자료
올라랩스(이하 "회사")가 앱 올라(olla) 를 만들며 OpenStreetMap(이하 "OSM") 자료로 만든 데이터베이스 표를 적었습니다. 표마다 원본 · 원본에서 고른 것 · 바꾼 것 · 다시 만드는 법을 적습니다.
이 쪽은 Open Database License(ODbL) 1.0 제4.6조 (b) 가 말하는 「데이터베이스에 가한 변경 또는 그 변경을 만드는 방법을 담은 파일」입니다.
| 구분 | 내용 |
|---|---|
| 이 쪽의 이용 조건 | Open Database License (ODbL) 1.0 |
| 원본 자료 | © OpenStreetMap 기여자 — openstreetmap.org/copyright |
| 적은 날 | 2026년 10월 29일 |
| 문의 | contact@olla.at |
회사의 적재 스크립트는 공개 저장소에 있지 않습니다. 그래서 고르는 규칙과 바꾸는 규칙을 이 쪽에 글로 모두 적었습니다. 스크립트 이름은 다시 만드는 차례를 가리키려고 함께 적습니다. 스크립트가 바뀌면 이 쪽도 함께 고칩니다.
1. 원본
모든 표가 아래 파일 하나에서 나옵니다.
| 구분 | 내용 |
|---|---|
| 자료 | OSM 대한민국 추출본 (Geofabrik) |
| 받은 곳 | download.geofabrik.de/asia/south-korea-latest.osm.pbf |
| 추출 시각 | 2026-08-10 20:21:40 (UTC) — 파일 머리의 osmosis_replication_timestamp |
| 갱신 순번 | 4398 (osmosis_replication_sequence_number, 갱신 주소 download.geofabrik.de/asia/south-korea-updates) |
| 받은 날 | 2026년 8월 11일 |
| 크기 | 약 285MB, 이력 없음 |
| 범위 | 경도 124.3188 ~ 132.3386, 위도 32.36076 ~ 38.64966 |
쓰는 도구는 osmium-tool(태그로 거르기 · GeoJSON 으로 내보내기), GDAL ogr2ogr(행정경계만), PostgreSQL · PostGIS 입니다. 좌표는 모두 WGS84(EPSG:4326)로 담습니다.
2. 표 한눈에
| 표 | 무엇 | 만드는 스크립트 | 쓰는 곳 |
|---|---|---|---|
| admin_sigungu | 시군구 경계 | load_admin_boundaries | 코스 · 장소 · 봉우리에 시군구 이름 붙이기, 다녀온 지역 지도 |
| land_polygons · admin_sigungu.geom_land | 육지 모양 · 바다를 뺀 시군구 모양 | load_land_polygons | 다녀온 지역 지도 그림 |
| osm_peaks | 봉우리 | load_osm_peaks | 산 정상 찾기 |
| mountains (정상 좌표 칸 일부) | 산의 정상 좌표 | 적재 때 DB 함수 refresh_summits_from_osm_peak, fill_summits | 정상 핀 · 정상 인증 |
| group_summits | 산 묶음의 확인된 정상 | verify_group_summits | 지도 산 정상 핀 |
| walk_ways | 걸을 수 있는 길 | load_walk_ways (+ fill_walk_elevation, attach_forest_facts) | 코스 만들기에서 길 잇기 |
| place_index | 이름 붙은 장소 | load_place_index | 지도 장소 검색, 받아 두는 지역 지도(오프라인 팩) |
| course_corrections (서울둘레길 일부) | 코스 선을 OSM 길 모양에 맞춘 기록 | load_seoul_dulle → seoul_dulle_snap | 서울둘레길 코스 선 |
3. 다시 만드는 차례
다른 표가 시군구 경계를 쓰므로 경계가 먼저입니다. 표 모양(칸)은 회사 데이터베이스의 표 정의가 미리 만들어 둡니다.
1. load_admin_boundaries — admin_sigungu
2. load_land_polygons — land_polygons, admin_sigungu.geom_land (경계를 다시 넣으면 반드시 다시 돌립니다)
3. load_osm_peaks — osm_peaks. 이어서 코스 적재(db_load)가 refresh_summits_from_osm_peak() 로 mountains 의 정상 좌표를 채웁니다
4. load_walk_ways — walk_ways. 이어서 fill_walk_elevation(고도) · attach_forest_facts(산림청 짝)
5. load_place_index — place_index
6. verify_group_summits --write — group_summits (코스를 다시 넣은 뒤에)
load_ 로 시작하는 다섯과 attach_forest_facts 는 data-pipeline 폴더에서 python -m normalize.<스크립트 이름> 으로, fill_walk_elevation · verify_group_summits · fill_summits 는 backend 폴더의 scripts 에서 돌립니다. verify_group_summits 는 카카오 지도 검색 열쇠가 있어야 합니다. 원본 경로는 환경 변수 OLLA_OSM_PBF 로 바꿀 수 있습니다.
4. admin_sigungu — 시군구 경계
고른 것
- 관계(relation) 중 boundary=administrative 이고 admin_level 이 4(시도) 또는 6(시군구)인 것. 읍면동(8)은 OSM 수록이 절반 남짓이라 쓰지 않습니다
- ogr2ogr 로 다각형을 만들고 name · admin_level · ref:KR:mois:legal(법정동코드) 세 태그만 꺼냅니다. 이름이 없는 것은 버립니다
바꾼 것
- 도형은 ST_MakeValid 로 고치고 MultiPolygon 으로 맞춥니다
- 표에는 시군구(6)만 담고, 시도(4)는 이름을 정하는 데만 씁니다
- 시도 이름은 OSM 시도 경계의 이름을 그대로 쓰지 않고 아래 차례로 정합니다. OSM 에 「전남광주통합특별시」 경계 하나가 전남과 광주를 묶고 있어서입니다. 정한 방법은 칸 sido_source 에 적습니다
| sido_source | 정하는 법 |
|---|---|
| osm_code | 법정동코드 앞 두 자리가 같은 OSM 시도 경계(코드가 있는 것)의 이름 |
| forest_address | 그 코드의 OSM 시도 경계가 없을 때, 그 시군구 안에 정상이 있는 산림청 산 정보(mountains.address)의 첫 낱말 중 가장 많은 것 — 표본 10개 이상, 90% 이상 같을 때만 |
| osm_area | 코드가 없을 때, 시군구 안쪽 한 점(ST_PointOnSurface)을 품는 OSM 시도 경계의 이름 |
| single_tier | 시군구가 하나도 없는 시도(세종)는 그 시도 경계를 한 칸으로 담고 시도 이름을 시군구 이름으로도 씁니다 |
- 이름을 못 정하면 비워 둡니다(NULL)
- 칸: osm_id(OSM 관계 번호) · name · legal_code(세종은 붙은 두 코드 중 앞의 것) · sido · sido_source · geom · geom_land · updated_at
다시 넣을 때 — osm_id 로 고쳐 쓰고, 새 원본에 없는 칸은 지웁니다.
5. land_polygons · geom_land — 육지 모양
행정경계는 바다(관할 해역)를 품습니다. 지도 그림에 쓸 육지 모양을 해안선에서 따로 세웁니다.
고른 것 — way 중 natural=coastline 인 것. osmium export 로 way 하나를 선 하나로 내보냅니다.
바꾼 것
1. 닫힌 해안선 중 시계 반대 방향인 것(OSM 해안선은 진행 방향 왼쪽이 육지)은 그대로 섬 하나 — source 칸 closed_way
2. 열린 해안선을 이어 붙여(ST_LineMerge) 닫히면 섬 하나 — merged_ways
3. 남은 열린 해안선과 시군구 경계 전체의 바깥 테두리를 함께 면으로 나누고(ST_Polygonize), 서울시청(126.978, 37.566) · 대전시청(127.385, 36.350) · 대구시청(128.601, 35.871) · 광주시청(126.851, 35.160) 네 점을 모두 품는 면 하나를 본토로 잡습니다 — mainland. 남한 추출이라 해안선이 휴전선에서 끊겨 해안선만으로는 본토가 안 닫힙니다
4. 육지 넓이가 95000 ~ 106000 제곱킬로미터를 벗어나거나 조각이 2500개보다 적으면 멈춥니다
5. admin_sigungu.geom_land = 시군구 경계 ∩ 육지 전체(ST_Intersection 의 면만 남김)
geom(바다를 품은 경계)은 그대로 둡니다. 「이 점이 어느 시군구인가」는 geom 으로, 「시군구를 어떻게 그리나」는 geom_land 로 합니다.
다시 넣을 때 — land_polygons 를 비우고 새로 채운 뒤 geom_land 를 다시 적습니다.
6. osm_peaks — 봉우리
고른 것 — 점(node) 중 natural=peak 인 것.
바꾼 것
- 담는 태그: name · name:ko · alt_name · ele. 앞뒤 빈칸을 지우고 빈 값은 비워 둡니다
- ele 는 숫자로 읽히고 0 초과 2200 이하일 때만 미터로 담고, 그 밖(「약 500m」 같은 글자, 범위 밖 값)은 비워 둡니다
- 시군구 · 시도: admin_sigungu 의 경계(geom)가 품으면 그 이름. 어느 경계에도 안 들면 비워 두고, 가까운 경계로 끌어 붙이지 않습니다
- 칸: osm_id(n + 번호) · name · name_ko · alt_name · ele_m · geom · sigungu · sido · loaded_at
다시 넣을 때 — 표를 비우고 통째로 다시 넣습니다.
7. mountains — 산의 정상 좌표 (일부 칸)
mountains 는 OSM 이 아닌 자료(산림청 등)로 만든 표입니다. 그중 정상 좌표가 비어 있는 산에 한해 OSM 봉우리 좌표를 옮겨 적습니다. 어디서 왔는지는 칸 summit_source 에 남깁니다.
summit_source = osm_named — 코스 적재 때마다 DB 함수 refresh_summits_from_osm_peak() 가 다시 정합니다.
- 대상: 100대 명산이고 높이가 적힌 산 중 정상 좌표가 없거나 이 함수가 채운 것. 다른 자료(봉우리 POI)가 먼저 채우고 남은 자리만 채웁니다
- 후보: 주소의 시군구 경계에서 5km 안이고 높이 차가 45m 이하인 osm_peaks (이름 · 높이가 있는 것)
- 고르기: 이름이 서로를 품는 것(산 이름 「계룡산_천황봉」의 봉우리 이름 · 산 이름과 OSM 이름), 또는 산림청 설명 글에 「OSM 이름(높이m)」이 적혀 있고 그 높이가 우리 높이와 2m 안인 것(설명 글에 산 이름이 높이와 함께 적혀 있으면 이 방법은 쓰지 않음). 여럿이면 이름이 겹치는 것 → 높이 차가 작은 것 → osm_id 차례
- 좌표는 0.000001도 눈금에 맞춥니다(ST_SnapToGrid)
- 후보가 사라진 산은 좌표를 다시 비웁니다. 다른 출처가 넣은 좌표는 건드리지 않습니다
summit_source = osm_peak — 2026-08-13 에 fill_summits 로 한 번 채운 것.
- 이름 일치(「북한산_백운대」 → 「백운대」, 봉우리 이름이 없으면 산 이름), 높이 차 30m 이내, 산의 범위 안(범위가 없으면 중심에서 20km 안) 셋을 모두 만족할 때만
8. group_summits — 산 묶음의 확인된 정상
코스 묶음(한 산의 여러 코스)마다 정상 핀을 찍을 자리를 정합니다. 증거가 모자라면 줄을 만들지 않습니다.
- 후보: 묶음 이름(괄호를 뗀 것 · 괄호 안의 것 포함)과 name 또는 name:ko 가 같은 osm_peaks 중, 묶음 코스의 범위 안이나 묶음 가운데에서 4km 안에 있고 묶음 코스가 50m 안을 지나는 것
- 카카오 지도 검색의 같은 이름 「산 · 산봉우리」와의 거리를 견줍니다. 카카오 좌표는 저장하지 않고 거리(kakao_m)만 남깁니다
| method | 고르는 법 | 찍는 자리 |
|---|---|---|
| osm_route_kakao | 코스가 지나는 같은 이름 봉우리가 하나 | OSM 봉우리 |
| kakao_pick | 여럿인데 카카오 같은 이름 50m 안에 드는 것이 하나 | OSM 봉우리 |
| osm_route_conv | 위에서 못 골랐고, 코스가 지나는 같은 이름 봉우리가 하나이며 코스들이 모이는 가장 높은 곳이 그 50m 안. 카카오 같은 이름이 300m 넘게 다른 자리면 뺌 | OSM 봉우리 |
| conv_kakao | 코스들이 모이는 가장 높은 곳과 카카오 같은 이름이 50m 안 | 코스들이 모이는 곳(우리 코스에서 구한 점) |
- 뒤의 두 방법(osm_route_conv · conv_kakao)에서는 이름에 정맥 · 대간 · 둘레길 · 종주 · 트레일이 든 묶음과, 코스 절반 넘게가 카카오 점에서 3km 밖에 있는 엉킨 묶음을 뺍니다
- 칸: group_id · geom · osm_id · peak_name(OSM 이름) · ele_m · method · kakao_m · checked_at
다시 넣을 때 — 표를 통째로 갈아 끼웁니다.
9. walk_ways — 걸을 수 있는 길
고른 것 — way 중 highway 가 아래 값인 선. 다른 값은 담지 않습니다.
| highway | kind 칸 | road_tier 칸 |
|---|---|---|
| path · bridleway | trail | — |
| steps | stairs | — |
| footway · pedestrian · cycleway | walkway | local |
| track | track | — |
| residential · living_street · unclassified | street | local |
| tertiary · secondary · primary · trunk (각 _link 포함) | street | arterial |
| motorway · motorway_link | street | motorway |
| service | service | local |
바꾼 것
- 그대로 옮기는 태그: highway · name · surface · sac_scale · foot · access. bridge · tunnel 은 값이 없거나 no 면 거짓, 그 밖은 참
- foot_banned 칸: foot=no 이거나, access 가 private · no 인데 foot 이 yes · designated · permissive · official 이 아니면 참. 이 값으로 길을 빼지 않고 표시만 합니다
- length_m 칸: 위도 37도 언저리 근사(경도 1도 88.9km, 위도 1도 111.0km)로 잰 대략의 길이. 0 인 선(같은 점만 늘어선 것)은 버립니다
- 좌표는 소수 일곱째 자리까지 담습니다. 같은 way 가 두 번 나오면 하나만 담습니다
- id 칸은 OSM way 번호입니다
덧붙인 것 — OSM 이 아닌 자료
- 고도(fill_walk_elevation): Copernicus GLO-30 지형 자료로 30m 마다 고도를 뽑아 9칸으로 고른 뒤 오르막 합 · 내리막 합(elev_gain_m · elev_loss_m)과 고도표(elev_samples)를 적습니다. 30m 보다 짧은 길은 elev_rough 를 참으로, 지형 자료가 안 덮는 자리는 비워 둡니다
- 산림청 짝(attach_forest_facts): 길을 한국 통합좌표계(EPSG:5179)로 옮겨, 길 길이의 80% 이상이 회사 코스 선 또는 산림청 등산로 조각의 20m 안에 들 때 가장 많이 덮인 것 하나를 짝으로 붙입니다(10m 보다 짧은 길은 안 붙임). 이름(forest_name — 코스 이름, 없으면 산림청 조각 이름)과 묶음 이름(group_name), 산림청 조각의 난이도 · 오르내림 시간 · 위험 안내를 옮겨 적고, 비율(match_ratio)을 함께 남깁니다. OSM 의 name 칸은 건드리지 않습니다
다시 넣을 때 — 있던 길(같은 way 번호)은 고치고, 새 길은 넣고, 새 원본에 없는 길은 지웁니다. 선 모양이 바뀐 길만 고도와 산림청 짝을 비워 다시 잽니다.
10. place_index — 이름 붙은 장소
고른 것 — osmium 으로 아래 태그를 가진 점 · 길 · 관계를 먼저 거르고, 점과 면(닫힌 길 · 다각형 관계)만 내보냅니다. 선은 버립니다.
- railway=station · halt
- amenity=townhall · bus_station · school · university · college · hospital · police · post_office · place_of_worship · public_bath · spa
- highway=services · rest_area
- leisure=golf_course · park · nature_reserve · resort · water_park · sauna · garden
- tourism=camp_site · caravan_site · alpine_hut · viewpoint · spa_resort · picnic_site · valley · attraction · theme_park · zoo · aquarium · observatory · museum · gallery
- natural=hot_spring · valley
- historic=castle · fort · citywalls · city_gate · archaeological_site · ruins · tomb · monument · memorial · building · manor · house · heritage · heritage_building · world_heritage · school · shrine · battlefield · pillory · stone · yes
- aerialway=station
- place=city · town · village · suburb · quarter · neighbourhood · hamlet · locality (점만)
이름 — name:ko 가 있으면 그것, 없으면 name. 앞뒤 빈칸을 지우고, 이름이 없으면 버립니다.
갈래(kind 칸) — 위 줄부터 차례로 보고 처음 맞는 줄을 씁니다. 어느 줄에도 안 맞으면 버립니다. rank 칸은 겹칠 때 먼저 남기는 차례값이며 작을수록 큰 장소입니다.
| 원본 | kind | rank |
|---|---|---|
| railway=station · halt — 단 station=subway 또는 subway=yes 면 이 줄은 안 맞음 | rail_station | 1 |
| amenity=townhall 이고 이름이 시청 · 군청 · 도청 · 구청으로 끝남 | city_hall | 1 |
| amenity=townhall 이고 이름에 행정복지센터 · 주민센터 · 읍사무소 · 면사무소 · 동사무소 (마을회관 같은 나머지는 이 줄들에 안 맞음) | town_office | 3 |
| amenity=bus_station 이고 이름에 「터미널」 | bus_terminal | 2 |
| amenity=bus_station 의 나머지 | bus_station | 6 |
| amenity=school | school | 5 |
| amenity=university · college | university | 4 |
| amenity=hospital | hospital | 4 |
| amenity=police | police | 4 |
| amenity=post_office | post_office | 5 |
| amenity=place_of_worship 이고 religion=buddhist (다른 종교는 안 맞음) | temple | 4 |
| highway=services | rest_area | 3 |
| highway=rest_area | rest_stop | 5 |
| leisure=golf_course | golf | 4 |
| railway=station · halt 의 나머지(station=subway 또는 subway=yes — 지하철 표시 역) | rail_station | 2 |
| tourism=camp_site · caravan_site · alpine_hut | camp_site · camp_site · alpine_hut | 5 |
| tourism=viewpoint | viewpoint | 6 |
| leisure=park · nature_reserve | park | 6 |
| aerialway=station | cable_car | 5 |
| place=city · town | city · town | 1 · 2 |
| place=village · suburb | village · suburb | 4 |
| place=quarter · hamlet | quarter · hamlet | 5 |
| place=neighbourhood · locality | neighbourhood · locality | 6 |
| historic= 위 「고른 것」의 값 | historic | 6 |
| 온천: natural=hot_spring, 또는 amenity=public_bath · spa · leisure=sauna 이고 bath:type 이 hot_spring · thermal · onsen · foot_bath 이거나 이름에 「온천」, 또는 leisure=resort · water_park · tourism=spa_resort 이고 이름에 「온천」 | hot_spring | 5 |
| tourism=museum · gallery | museum | 6 |
| tourism=attraction · theme_park · zoo · aquarium · observatory | attraction | 5 |
| 수목원: leisure=garden · tourism=picnic_site 이고 이름에 「수목원」 · 「식물원」, 또는 leisure=garden 이고 garden:type 이 arboretum · arboretum. · botanical (그 밖의 leisure=garden 은 안 맞음) | arboretum | 5 |
| tourism=valley · natural=valley, 또는 tourism=picnic_site 이고 이름에 「계곡」 | valley | 6 |
| tourism=picnic_site 의 나머지 | picnic_site | 6 |
바꾼 것
- 면은 점 하나로 줄입니다 — 바깥 고리의 넓이 가중 무게중심, 여러 조각이면 가장 큰 조각의 것
- 기차역(rail_station)은 이름이 「역」으로 끝나지 않으면 「역」을 붙입니다(원본 「충주」 → 「충주역」, 지도 글자와 같게)
- tourism=caravan_site 에서 온 장소의 이름에 한글이 한 글자도 없으면(원본의 「office」 · 「1」 · 「Park」 같은 것) 이름을 「카라반 터」로 바꿔 넣습니다. osm_id 와 좌표는 그대로입니다
- historic · hot_spring · museum · attraction · arboretum · valley · picnic_site 갈래의 장소가 다른 줄과 이름(빈칸 · 괄호를 지우고 소문자)과 위경도 소수 둘째 자리가 같으면 그 장소는 넣지 않습니다. 이 일곱끼리 겹치면 historic → hot_spring → museum → attraction → arboretum → valley → picnic_site 차례로 하나만 넣습니다
- 시군구 · 시도: admin_sigungu 의 경계(geom)가 품으면 그 이름, 안 들면 비워 둡니다
- name_key 칸: 이름에서 빈칸 · 반각 괄호를 지우고 소문자로 바꾼 검색 열쇠
- 칸: osm_id(n · w · r + 번호) · name · kind · rank · sigungu · sido · geom · name_key · gone · loaded_at
다시 넣을 때 — osm_id 로 고쳐 쓰고, 새 원본에 없는 장소는 지우지 않고 gone 을 참으로 표시합니다. 검색은 gone 이 거짓인 것만 봅니다.
사용자 폰으로 가는 것 — 받아 두는 지역 지도(오프라인 팩)에 그 지역 상자 안의 장소를 싣습니다. 칸은 name · kind · lat · lon · sido · sigungu 이고, 좌표는 소수 다섯째 자리로 줄입니다. 이름 열쇠 · 갈래가 같고 좌표가 소수 둘째 자리까지 같은 것(같은 곳이 점과 면으로 두 번 적힌 것)은 하나만 싣습니다. 같은 팩에 mountains 의 정상 좌표(7절)도 실립니다.
11. course_corrections — 서울둘레길 코스 선 보정
서울둘레길 2.0 원본 선(스마트서울맵)의 성긴 직선 구간을 OSM 길 모양에 맞춘 기록입니다(2026-10-28, 14코스 5구간 한 코스). 코스 선 자체는 OSM 이 아니고, 원본 점은 그대로 지납니다.
- 쓰는 OSM 길: highway 가 path · bridleway · steps · footway · pedestrian · track · residential · living_street · unclassified · service · cycleway 인 way. foot · access 로는 거르지 않습니다
- 원본 점 사이가 200m 이상이고 그 직선이 길에서 20m 넘게 벗어날 때만, 두 원본 점 사이를 길 위 경로로 바꿉니다. 직선에서 max(150m, 직선 길이 × 0.35) 밖의 길은 안 쓰고, 새 경로가 직선의 1.6배를 넘거나 원본 점 60m 안에 길이 없으면 바꾸지 않습니다
- 원본 선은 회사 데이터베이스에 그대로 남고, 무엇을 왜 바꿨는지는 course_corrections 에 남습니다
12. 이 쪽의 대상이 아닌 것
- 지도 그림(.pmtiles 타일) — OSM 으로 그린 「만든 작품(Produced Work)」입니다. 앱 지도의 ⓘ 와 이 사이트 아래에 출처를 밝힙니다
- OSM 이 아닌 자료(산림청 등산로 · 회사 코스 등)는 위에 적은 표에 덧붙인 칸 말고는 이 쪽에 적지 않습니다