퇴근길에는 갈림길이 있다. 어느 쪽이 빠른지는 그날그날 달라서, 지금 가장 빠른 길을 알려 주는 개인용 웹앱을 만들었다.
어떻게 비교하나#
서울 열린데이터광장의 실시간 도로소통 자료는 도로를 링크(교차로에서 교차로까지)로 나눠 링크마다 속도와 통행시간을 준다. 경로를 구성하는 링크들의 통행시간을 더하면 경로 시간이 된다.
- 속도에 거리를 곱하지 않고 통행시간을 그대로 합산한다. 링크가 교차로 사이라서 신호 대기가 이미 포함돼 있다.
- 자료가 없는 골목은 시속 15km로 가정한다.
- 경로 간 차이가 2분 미만이면 “비슷하다”고 표시한다.
한계도 적어 둔다#
직진과 우회전 차로가 구분되지 않아서 갈림 교차로에서 오차가 가장 컸다. 신호 운은 교차로마다 0~2분 정도 차이가 난다. 그래서 앱이 실제로 얼마나 맞는지 알려면 예측과 실제를 기록해야 했다.
출발 버튼 하나만 누르면 휴대폰 위치로 체크포인트 통과 시각을 저장하고, 구간별로 “예측 − 실제” 평균을 모은다. 기록이 쌓이면 이 평균으로 예측을 보정할 계획이다.
구성#
- Firebase Hosting(화면), Cloud Functions(서울시 API 대리 호출), Firestore(기록)
- 인증키와 접속 비밀번호는 Secret Manager에 보관하고, 브라우저에는 내려보내지 않는다.
- 홈 화면에 추가해 쓰도록 PWA로 만들었다.
장애 사례: 링크 하나가 앱 전체를 죽였다#
어느 날부터 화면이 아예 뜨지 않았다. 원인을 따라가 보니 이랬다.
- 서울시 API가 구글 클라우드(서울 리전)에서 오는 요청을 간헐적으로 받지 않았다. 국내 네트워크에서 직접 호출하면 정상이었다.
- 링크 89개를
Promise.all로 한꺼번에 불렀기 때문에, 하나만 실패해도 전체 응답이 500이 됐다.
고친 방법은 세 가지였다.
- 호출마다 5초 제한과 최대 3회 재시도를 두고, 끝내 실패한 링크만 “연결 실패”로 표시한다. 전체 응답은 200으로 돌려준다.
- 성공한 값은 Firestore에 캐시해 두고, 서울시가 실패하면 30분 안의 값으로 대신한다.
- 요청 전체에 20초 마감을 둔다.
고친 뒤에는 89개 링크 요청이 1~2초 안에 끝났다. 외부 API를 묶어 부를 때는 부분 실패를 허용하는 구조가 기본이어야 한다는 걸 배웠다.