OpenStreetMap에서 도보 최단경로 찾기

Choi Wontak·2025년 5월 8일

고민거리

목록 보기
2/4
post-thumbnail

난이도 ⭐️
작성 날짜 2025.05.08

고민 내용

프로젝트에서 도보 경로를 찾는 과제가 있었는데 API를 쓰기에는 보통 유료라 고민이다..

🤔
무료로 도보 경로를 찾을 수는 없을까?


찾아보기

https://download.geofabrik.de/asia/south-korea.html
여기서 OSM에서 제공하는 대한민국 지도 정보를 다운로드 받을 수 있다.

.osm.pbf는 OpenStreetMap에서 큰 지도 데이터를 처리하기 위해 제공하는 압축된 파일이다.

파일을 다운받아 Resources에 넣어두었다.

다음은 osm pbf를 처리하기 위해 자바 코드로 넘어간다.

도보 길찾기를 좀 편리하게 하기 위해 GraphHopper라는 라이브러리를 이용하였다.

implementation 'com.graphhopper:graphhopper-core:8.0'

이렇게 의존을 추가해주고, 테스트를 해보았다.

public static void main(String[] args) {
        GraphHopper hopper = new GraphHopper();
        hopper.setOSMFile("src/main/resources/map/south-korea-latest.osm.pbf");
        hopper.setGraphHopperLocation("graph-cache");

        CustomModel customModel = new CustomModel();
        // road_access == DESTINATION 일 경우 우선순위를 0으로 곱해서 무시
        Statement avoidDestinationRoads = Statement.If("road_access == DESTINATION", Statement.Op.MULTIPLY, "0");
        customModel.addToPriority(avoidDestinationRoads);

        Profile profile = new Profile("foot")
                .setVehicle("foot")
                .setWeighting("custom")
                .setCustomModel(customModel);

        hopper.setProfiles(profile);
        hopper.importOrLoad();

        GHRequest req = new GHRequest(37.5665, 126.9780, 37.5796, 126.9770)  // 서울시청 → 경복궁 예시
                .setProfile("foot")
                .setLocale("en");

        GHResponse res = hopper.route(req);
        if (res.hasErrors()) {
            System.out.println(res.getErrors());
            return;
        }

        PointList path = res.getBest().getPoints();
        path.forEach(p -> System.out.println(p.getLat() + ", " + p.getLon()));
    }

GraphHopper는 이것저것 설정할 것들이 좀 있었는데,
특히 CustomModel 설정 방법이 찾아봐도 잘 안나와서 애먹었다.

OSM PBF 파일을 불러와서 그래프를 만드는데,
처음에만 만들고 이후에는 만든 엣지, 노드 등의 가공된 정보를 활용하도록 setGraphHopperLocation로 설정한 폴더에 캐싱해두고 이후엔 importOrLoad로 캐싱된 그래프를 불러온다.

요런 식으로 바이너리 파일이 저장된다.

서울시청 → 경복궁 예시를 넣어보았는데,

이런 식으로 osm pbf 파일 처리를 진행하고,

요렇게 결과를 보여준다.

처음 실행하면 그래프 생성 과정 때문에 무려 41초가 걸리지만,
두 번째부턴 1.108s로 확 줄어든다.

이제 요게 진짜 도보 경로가 맞는지 확인이 필요하다.

GPT에게 leaflet으로 지도 위에 경로를 그릴 수 있도록 html 작성을 부탁했다.

결과물로 나온 위치 정보를 JSON 형식으로 바꿔서 넣어줬더니...

조금 자세히 보면,

진짜 도보를 이용하는 것을 알 수 있다!
차도 건너는 부분도 찾아보니 실제 횡단보도였다.

res.getBest().getDistance() // 거리 (m)
res.getBest().getTime() // 시간 (ms)

이 두 코드를 이용하면 거리와 시간도 구할 수 있다.

자바
2.006148099905989 km
24 min

실제 카카오 맵
1.8 km
28 min

경로 상의 차이가 있음을 감안했을 때, 단순 자바 라이브러리를 이용한 것 치고는 오차가 크지 않은 것 같다.


결론

setVehicle을 foot으로 설정해서 도보 경로로 뽑아보았는데, car로 설정하면 자동차 경로도 뽑을 수 있는 듯하다.

알고리즘도 CH 알고리즘, A*, Dijkstra 등 다양한 커스텀 알고리즘을 적용할 수 있는 것 같으니 활용도가 무궁무진 할 것 같다!

결론
자바 경로 찾기는 GraphHopper로!


profile
백엔드 주니어 주니어 개발자

0개의 댓글