1. OSRM이란?
OSRM은 Open Source Routing Machine의 약자로 길찾기 Routing과 관련된 다양한 기능을 제공하는 라이브러리이다.
다른 routing engine과 비교하여 속도가 매우 빠르다. 그 이유는 각 도로별 가중치를 미리 사전에 모두 계산해두기 때문이다. 이러한 특징 때문에 가중치를 변경하는 것은 유연하지 않고 오래 걸린다. 또한 완전히 무료이고 오픈소스이며 또한 실시간 교통 상황도 반영 가능하다.
자세한 정보는 아래에서 확인 가능하다.
2. OSM이란?
OSM은 Open Street Map의 약자로 전세계 지도에서 도로, 건물, 대중교통, 등산로 등에 대한 정보가 담긴 지리공간 데이터베이스이다. 누구나 자유롭게 지도를 편집하고 수정할 수 있다. 포켓몬 고, Meta의 지도 등이 osm 기반 지도로 인지도가 높으며 많은 데이터가 담겨 있다.
osrm, valhalla 등 많은 routing engine이 osm 지도 데이터를 기반으로 동작한다.
3. OSRM Install
아래 github 레포에서 자세한 설치 방법을 확인할 수 있다.
osrm-backend
Project-OSRM • Updated Sep 21, 2025
Docker를 통해 로컬에 osrm 서버를 설치하는 방식이다.
- 대한민국 전역의 osm 데이터를 현재 위치에 다운로드한다. osm 원본 데이터는 .pbf 확장자를 가진다.
wget http://download.geofabrik.de/asia/south-korea-latest.osm.pbf
- osm 데이터로부터 osrm 그래프를 만든다.
- south-korea-latest.osm.pbf에는 도로망 외에 다양한 정보가 있는데 routing에 필요한 정보만을 추출한다.
- car.lua를 사용하여 자동차만을 위한 도로 그래프를 만든다. 이 과정에서 각 도로별 기본 속도, 일반통행 여부, 회전 가능 여부 등이 osrm 도로 그래프에 저장된다.
- 이 단계를 마치면 .osrm.* 파일이 여럿 만들어진다.
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-extract -p /opt/car.lua /data/south-korea-latest.osm.pbf || echo "osrm-extract failed"
- 도로 그래프를 여러개의 cell로 paritioning한다.
- osrm은 Contraction Hierarchies (CH)와 Multi-Level Dijkstra (MLD) 알고리즘을 지원한다. CH가 더 빠르지만 MLD가 traffic 업데이트를 지원한다. MLD가 기본 값이며 parition, customize는 MLD를 위한 전처리이고 CH를 쓴다면 contract을 써야 한다.
- customize 단계에서 traffic을 반영할 수 있다. 아래처럼 두면 car.lua만을 사용한 기본값으로 되돌린다.
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-partition /data/south-korea-latest.osrm || echo "osrm-partition failed" docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-customize /data/south-korea-latest || echo "osrm-customize failed"
- 로컬 포트 5003번에 osrm 서버를 실행한다.
docker run -t -i -p 5003:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/south-korea-latest.osrm
4. OSRM Duration Adjust
osrm을 그냥 사용하면 일반적인 네이버 지도, 티맵, 카카오 네비 등에 비해 도착 예상 시간이 매우 짧게 나온다. 그 이유는 도로별 기본 속도가 매우 빠르게 설정되어 있고 실시간 교통 정보가 반영이 되어 있지 않기 때문이다.
4.1. car.lua 수정
4.1.1. OSRM Profile이란?
osrm에는 profile이라는 개념이 있다. profile은 도로별 기본 속도, 우회전 대비 좌회전의 페널티 정도, 유턴 여부, 차량 크기 정보 등 routing에 직접적으로 영향을 주는 parameter를 담고 있다. 기본 제공하는 profile은 car.lua, bicycle.lua, foot.lua가 있다. 아래 링크에서 car.lua를 확인할 수 있다.
이 Lua script를 수정하여 custom routing을 만들 수도 있다. 여기서 도로별 기본 속도를 관여하는 부분은
speeds 변수다. 기본값은 아래와 같이 지정되어 있다.speeds = Sequence { highway = { motorway = 90, motorway_link = 45, trunk = 85, trunk_link = 40, primary = 65, primary_link = 30, secondary = 55, secondary_link = 25, tertiary = 40, tertiary_link = 20, unclassified = 25, residential = 25, living_street = 10, service = 15 } },
4.1.2. OSM Highway Tags
위의
speeds 는 osm의 highway tag의 value들이다. osm에서는 각 도로를 way라고 부르며 way마다 id와 highway tag 등이 있다. highway tag는 그 way가 어떤 종류의 도로인지를 담고 있다. 실제로는 대중교통 way, 자전거 도로, 등산로까지 포함 되어 있어 아래 표보다 많지만 osrm에서 쓰이는 highway는 아래와 같다.highway value | ITS 교통 정보 유무 | Desc |
O | 진입이 제한된 고속도로. 비상 갓길 존재. | |
O | 고속도로의 진입로 | |
O | 도시 내 고속도로가 아닌 큰 도로 | |
O | 큰 도로의 진입로 또는 교차로 | |
O | 도시 내 주요 도로 | |
O | 주요 도로의 진입로 또는 교차로 | |
O | 시내 도로 | |
O | 시내 도로의 진입로 또는 교차로 | |
ㅤ | ㅤ | ㅤ |
△ | 주거지로 연결되지 않은 골목길 | |
△ | 골목길의 진입로 또는 교차로 | |
△ | 양쪽에 주택가가 있는 주거지로 연결된 도로. (골목길) | |
ㅤ | ㅤ | ㅤ |
X | tertiary보다 중요성이 낮으면서 residetial, service, track이 아닌 도로 | |
X | 넓은 보행자 도로. 차보다 보행자가 우선시됨. | |
X | 주유소로 들어가는 길과 같이 특정 service를 제공하는 곳으로 이동하는 도로. |
4.1.3. OSRM Profile Update
이를 고려했을 때 기본값으로 지정된 속도는 매우 빠른 속도임을 알 수 있다. speed 값은 실제 차량의 속도이지 최대 속도가 아니다. 그래서 traffic jam 등을 모두 고려한 최종 속도를 입력해야 한다. 기본 속도는 custom traffic 데이터가 없을 때 사용하는 값이므로 일반적인 traffic 환경의 속도를 입력해야 한다.
따라서 아래와 같이 수정하였다.
speeds = Sequence { highway = { motorway = 50, motorway_link = 15, trunk = 35, trunk_link = 10, primary = 25, primary_link = 5, secondary = 20, secondary_link = 5, tertiary = 7, tertiary_link = 5, unclassified = 5, residential = 5, living_street = 5, service = 5 } },
이 값을 osrm에 반영하는 방법은 아래와 같다.
- car.lua 파일을 현재 위치에 다운로드
wget https://raw.githubusercontent.com/Project-OSRM/osrm-backend/master/profiles/car.lua
- 스크립트 수정
- osrm-extract
docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-extract -p /data/car.lua /data/south-korea-latest.osm.pbf || echo "osrm-extract failed"
- osrm-partition, osrm-customize, 서버 실행
4.2. df_osm_traffic.csv 업데이트
osrm은 csv 형식을 통해 각 도로 내의 구간별 속도를 customize할 수 있다. 실시간 traffic 정보로부터 speed를 구하고 이를 routing에 반영하여 duration을 tmap에 보다 가깝게 하는 것이다.
4.2.2. ITS 교통소통정보
국가교통정보센터 (its)는 전국의 수십개 기관 및 자치단체로부터 전국 도로의 실시간 traffic 데이터를 가져오고 api로 가져올 수 있게 한다.
‘교통소통정보’ api에서 전국의 교통 데이터가 5분 간격으로 업데이트 되며 1분 내로 전국 교통 데이터를 가져올 수 있다.
아래와 같이 api key와 bounding box를 지정하여 그 영역 내의 모든 교통 정보를 가져온다.
f"https://openapi.its.go.kr:9443/trafficInfo?apiKey={cfg.its_api_key}&type=all&drcType=all&minX={minX}&maxX={maxX}&minY={minY}&maxY={maxY}&getType=json"
json으로 받아 df로 변환하면 아래와 같이 받을 수 있다. 전국 호출시 약 25초 내에 response를 받을 수 있고 529,252개의 row가 온다. 여기서 필요한 값은 linkid와 speed뿐이다. its는 도로를 link와 node로 구성한다. osrm에서는 traffic 반영시 speed만 반영 가능한데 두 node pair에 대한 speed를 업데이트 해야한다. 이를 위해서는 its link의 좌표가 필요하다.
roadName | roadDrcType | linkNo | linkId | startNodeId | endNodeId | speed | travelTime | createdDate |
강변북로 | ㅤ | ㅤ | 1020001302 | 1020023100 | 1020020100 | 35 | 39.16 | 20250715130500 |
강변북로 | ㅤ | ㅤ | 1020001304 | 1020037200 | 1020023100 | 42 | 5.65 | 20250715130500 |
4.2.3. ITS 표준노드링크
linkid에 대한 위경도 좌표 데이터가 담겨 있다. 2025년 5월 12일 데이터가 가장 최신 데이터이긴 하나 이 데이터를 사용하면 안 된다. 2024년 2월 23일 데이터를 사용하는 것을 권장한다. 시간이 지날 수록 새로운 도로가 개통되면서 linkid가 바뀌고 업데이트가 되는데 its에서는 새로 바꿨지만 각 지방 기관은 이전 linkid를 사용하는 경우가 많아 서로 호환이 안 되기 때문이다. 문의를 해보니 2023년 후반이나 2024년 초반 데이터가 가장 많이 호환된다고 한다.
- 압축 파일 중 NODELINKDATA/MOCT_LINK.shp 사용.
- LINK_ID로부터 LINESTRING 값 얻기 위해 사용.
- 1,548,963 rows. Load시 약 2분 소요. 한 번만 Load하면 됨.

아래에서 필요한 값은 LINK_ID와 geometry 뿐이다.
ㅤ | LINK_ID | F_NODE | T_NODE | LANES | ROAD_RANK | ROAD_TYPE | ROAD_NO | ROAD_NAME | ROAD_USE | MULTI_LINK | ... | REST_VEH | REST_W | REST_H | C-ITS | LENGTH | UPDATEDATE | REMARK | HIST_TYPE | HISTREMARK | geometry |
0 | 2360079706 | 2360321000 | 2360320800 | 2 | 107 | 000 | - | 왕방로 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 18.700310 | 20231113 | None | LINK1007 | 2360079702 | LINESTRING (216663.476 587691.911, 216666.639 ... |
1 | 3100551600 | 3100227900 | 3100228600 | 1 | 103 | 000 | 19 | 요천로 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 145.811661 | 20230829 | None | LINK0001 | None | LINESTRING (237794.632 315193.509, 237778.943 ... |
이 데이터를 OSM과 매칭이 되도록 알고리즘을 구성하여 최종적으로 아래와 같은 형식의 csv 파일을 만들면 된다.
osm_start_node_id | osm_end_node_id | speed |
2139941823 | 2139941793 | 35.0 |
2139941823 | 2139941793 | 42.0 |


