OSRM을 통해 한국의 실시간 교통 정보를 반영한 라우팅 엔진 만들기

September 22, 2025
OSRM을 통해 한국의 실시간 교통 정보를 반영한 라우팅 엔진 만들기
OSRM을 통해 한국의 실시간 교통 정보를 반영한 라우팅 엔진 만들기

OSRM을 통해 한국의 실시간 교통 정보를 반영한 라우팅 엔진 만들기

Language
ko
Tags
OSRM
Routing Engine
OSM
Docker
번역 대기
번역 대기
Authors
Jaewan Shin
Published
September 22, 2025
Use Original Cover Image
Type
Post
Children

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-OSRMUpdated Sep 21, 2025
 
Docker를 통해 로컬에 osrm 서버를 설치하는 방식이다.
  1. 대한민국 전역의 osm 데이터를 현재 위치에 다운로드한다. osm 원본 데이터는 .pbf 확장자를 가진다.
wget http://download.geofabrik.de/asia/south-korea-latest.osm.pbf
 
  1. osm 데이터로부터 osrm 그래프를 만든다.
    1. south-korea-latest.osm.pbf에는 도로망 외에 다양한 정보가 있는데 routing에 필요한 정보만을 추출한다.
    2. car.lua를 사용하여 자동차만을 위한 도로 그래프를 만든다. 이 과정에서 각 도로별 기본 속도, 일반통행 여부, 회전 가능 여부 등이 osrm 도로 그래프에 저장된다.
    3. 이 단계를 마치면 .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"
 
  1. 도로 그래프를 여러개의 cell로 paritioning한다.
    1. osrm은 Contraction Hierarchies (CH)와 Multi-Level Dijkstra (MLD) 알고리즘을 지원한다. CH가 더 빠르지만 MLD가 traffic 업데이트를 지원한다. MLD가 기본 값이며 parition, customize는 MLD를 위한 전처리이고 CH를 쓴다면 contract을 써야 한다.
    2. 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"
 
  1. 로컬 포트 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에 반영하는 방법은 아래와 같다.
  1. car.lua 파일을 현재 위치에 다운로드
wget https://raw.githubusercontent.com/Project-OSRM/osrm-backend/master/profiles/car.lua
 
  1. 스크립트 수정
  1. 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"
  1. 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하면 됨.
 
notion image
아래에서 필요한 값은 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