GPX 파일 안에는 무엇이 들어 있나
GPX는 GPS 경로를 주고받는 표준 형식입니다. 열어 보면 그냥 XML이고, 구조는 30분이면 다 이해할 수 있을 만큼 단순합니다.
그런데 같은 코스를 담은 GPX 두 개가 기기에서 전혀 다르게 동작하는 일이 흔합니다. 하나는 "코스"로 들어가는데 다른 하나는 지도에 점만 찍히거나, 17 km짜리 코스가 40 km로 나오거나 합니다. 원인은 대부분 이 글에서 다루는 세 가지입니다.
점이 세 종류입니다
GPX에는 좌표를 담는 태그가 셋 있고, 셋 다 구조는 같은데 뜻이 다릅니다. GPX 1.1 스펙의 정의를 그대로 옮기면 이렇습니다.
| 태그 | 스펙의 정의 | 실제 의미 |
|---|---|---|
<wpt> | 지도 위의 웨이포인트, 관심 지점, 이름 붙은 지형지물 | 독립된 점. 화장실, 정상, 주차장 |
<rtept> (<rte> 안) | 목적지로 이어지는 분기점의 순서 있는 목록 | 계획된 경로. "여기서 좌회전" |
<trkpt> (<trk> 안) | 경로를 서술하는 점의 순서 있는 목록 | 기록된 자취. 빵부스러기 |
핵심은 rte는 계획이고 trk는 기록이라는 것입니다. 대부분의 기기와 앱이 이 둘을 다르게 취급합니다 — 한쪽은 따라갈 경로로, 다른 한쪽은 지나간 활동으로요. 받은 파일이 기대와 다르게 들어갔다면 가장 먼저 확인할 것이 이것입니다. 파일을 텍스트 편집기로 열어 <trk가 있는지 <rte가 있는지 보면 됩니다.
셋 다 없거나 좌표가 하나도 없으면 그 파일은 빈 파일입니다.
<trkseg>이 여러 개인 것은 정상입니다
<trk> 안에는 <trkseg>(트랙 세그먼트)가 하나 이상 들어갑니다. 스펙은 이렇게 정의합니다 — "논리적으로 순서대로 연결된 트랙 포인트의 목록", 그리고 세그먼트가 나뉘는 이유는 GPS 수신이 끊겼거나 기기가 꺼졌을 때입니다.
즉 <trkseg>이 셋이라고 경로가 셋인 게 아닙니다. 하나의 경로가 신호 끊김으로 세 토막이 된 것이고, 이어 붙이는 게 맞습니다.
<trk>가 여러 개인 것은 전혀 다른 이야기입니다
한 파일에 <trk>가 여럿이면 그건 서로 다른 경로입니다. 그리고 여기서 실제로 사고가 납니다.
이 사이트가 두루누비 코스를 들여올 때 겪은 일입니다.
두루누비는 한 코스의 본선과 만조 우회로를 하나의 파일에 두 개의<trk>로 넣습니다. 문서 안의<trkpt>를 전부 읽으면 둘이 끝과 끝으로 이어 붙습니다. 서해랑길 34코스는 실제 17.0 km인데 40.2 km로 나왔고, 한 경로가 끝나고 다른 경로가 시작하는 중간에 5 km짜리 점프가 직선으로 그어졌습니다.
그래서 이 사이트의 파서는 첫 번째 <trk>만 읽습니다. 세그먼트가 아니라 트랙 요소를 기준으로 범위를 잡기 때문에, 위의 <trkseg> 여럿은 그대로 이어지고 <trk> 여럿은 나뉩니다.
남의 GPX 거리가 이상하게 크다면 <trk> 개수를 세어 보세요. grep -c "<trk>" 파일.gpx 한 줄이면 됩니다.
<ele>는 선택 요소입니다 — 그리고 구멍이 문제입니다
고도는 각 점 안의 <ele>에 미터 단위로 들어가는데, 스펙상 선택 요소입니다. 없어도 유효한 GPX입니다.
까다로운 건 일부 점에만 있는 경우입니다. 천 개 점 중 몇 개가 <ele> 없이 오는 공개 파일이 실제로 있습니다. 구멍이 뚫린 프로파일로 누적 상승을 합하면 그 값은 틀립니다. 그래서 이 사이트는 고도를 전부-아니면-전무로 다룹니다 — 모든 점에 유효한 <ele>가 있을 때만 그 파일의 고도를 쓰고, 하나라도 비면 고도 서비스에 다시 물어봅니다.
고도가 채워져 있어도 값이 가짜인 경우는 더 까다로운데, 그건 누적 상승 안내에서 따로 다룹니다.
<time>은 방향을 정합니다
<time>도 선택 요소이고, 스펙은 UTC 기준 ISO 8601을 요구합니다.
기록된 활동에는 보통 있고 계획한 경로에는 보통 없습니다. 그런데 여기에 함정이 하나 있습니다 — GPX에는 "정방향"이라는 개념이 없습니다. 점은 문서에 적힌 순서대로 읽히고, 첫 점이 출발지가 됩니다.
그래서 역방향으로 내보낸 파일은 출발점과 도착점이 뒤바뀐 채로 들어갑니다. 이 사이트는 모든 점에 시각이 있고 그 시각이 거꾸로 흐르면(마지막 시각이 첫 시각보다 이르면) 시간순으로 뒤집습니다. <time>이 없는 파일은 그렇게 판단할 근거가 없어서 화면에서 직접 뒤집으셔야 합니다.
이 사이트가 내보내는 파일
지도에서 그린 경로를 GPX로 받으면 정확히 이 구조가 나옵니다.
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="gps-file-generator"
xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<name>경로 이름</name>
</metadata>
<wpt lat="37.5554" lon="126.9726">
<name>서울역</name>
</wpt>
<trk>
<name>경로 이름</name>
<trkseg>
<trkpt lat="37.5554" lon="126.9726"></trkpt>
<trkpt lat="37.5561" lon="126.9738"></trkpt>
</trkseg>
</trk>
</gpx>
읽을 점 세 가지입니다.
<trk>하나에<trkseg>하나. 위에서 본 두 함정을 애초에 만들지 않습니다.- 경유지는
<wpt>로 따로. 트랙 안에 섞지 않으므로 경로를 지우지 않고도 마커만 다룰 수 있습니다. <ele>도<time>도 없습니다. 그린 경로는 기록된 활동이 아니라 계획이고, 지어낸 고도나 시각을 넣는 것보다 없는 편이 정직합니다. 고도는 화면의 그래프에서 보시면 됩니다.
GeoJSON과 KML은 언제 쓰나
같은 경로를 세 형식으로 받을 수 있는데, 쓰임이 다릅니다.
| 형식 | 쓰는 곳 | 형태 |
|---|---|---|
| GPX | GPS 기기, 운동 앱 | XML. <trk> 하나에 트랙 포인트 |
| GeoJSON | 웹 지도, GIS 도구, 코드 | JSON. FeatureCollection 안의 LineString |
| KML | 구글 어스, 구글 지도 | XML. Placemark 안의 LineString |
무엇을 쓸지 모르겠으면 GPX입니다. 좌표 순서 하나만 조심하시면 됩니다 — GeoJSON과 KML은 경도,위도 순이고 GPX는 lat/lon을 이름으로 구분합니다. 직접 변환 코드를 짜다 지구 반대편이 나오는 사고가 대개 여기서 납니다.
파일이 기기에서 안 열릴 때
텍스트 편집기로 열어 위에서부터 확인하세요.
1. 좌표가 있나 — <trkpt, <rtept, <wpt 중 하나라도 있어야 합니다. 없으면 빈 파일입니다.
2. <trk>인가 <rte>인가 — 기대한 것과 다르게 들어갔다면 여기입니다.
3. <trk>가 몇 개인가 — 둘 이상이면 거리가 부풀고 중간에 직선 점프가 생깁니다.
4. 네임스페이스가 맞나 — xmlns="http://www.topografix.com/GPX/1/1". 엄격한 기기는 이게 없으면 거부합니다.
5. 점이 너무 많지 않나 — 기기마다 코스당 점 개수 상한이 있습니다. 수만 점짜리 파일은 줄여야 합니다.
받은 파일을 실제로 기기에 넣는 절차는 GPX 파일 사용법에 있습니다.
