프로젝트 / 모바일·디바이스
모바일·디바이스공공 데이터 API통계 모델Jetpack ComposeNode.js폴더블 UI
«앉을까» 지하철 착석 예측 앱
노선도·실시간 도착·혼잡도 통계를 한 화면에 모으고 «이 열차를 타면 몇 정거장 안에 앉을까»를 추정하는 폴더블 앱
- 기간
- 2026.10
- 형태
- 사이드 프로젝트
- 상태
- 동작 확인
- 역할
- 공공 데이터 실측 조사·착석 모델 설계·서버/안드로이드 앱 개발 1인 수행
656개노선 그래프에 묶은 역 (노선 24개)
58%도착 예정 초 필드가 0으로 오는 비율 — 메시지 파싱으로 보정
950회/일실시간 호출 상한 (공식 한도 1,000회)
문제
수도권 지하철에서 앉을 수 있는지는 열차 도착 시각, 시간대별 혼잡도, 역별 하차 인원을 함께 봐야 판단할 수 있습니다. 세 정보는 서로 다른 공공 데이터에 흩어져 있고, 역 이름 표기도 원본마다 달랐습니다.
실시간 도착 API는 하루 1,000회 한도가 있고, 도착 예정 초 필드가 0으로 오는 행이 58%였습니다. 원본 노선 그래프에는 급행이 건너뛰는 선이 섞여 있어 그대로 쓰면 정거장 순서가 틀어졌습니다.
접근
- 공공 데이터 출처를 직접 호출해 실측 조사 문서로 정리했습니다. 실시간 도착·열차 위치, 30분 단위 혼잡도 통계, 월별 시간대 승하차, 칸별 혼잡도 과거 실측을 비교하고, 종료 예정인 상용 API는 쓰지 않기로 정했습니다.
- 데이터 빌드 도구가 원본을 노선·혼잡도·승하차 JSON으로 합칩니다. 역 이름은 표준 키로 맞추고, 빼도 6정거장 안에 우회로가 있는 급행 건너뛰기 선은 그래프에서 제거합니다.
- 착석 모델 v1은 칸 정원 160명=100%, 좌석 54석을 기준으로 입석 인원과 역별 하차로 비는 좌석을 계산하고, 입석자가 공평하게 경쟁한다는 가정으로 누적 착석 확률을 구합니다. 앱은 이 값을 «통계 기반 추정»이라고 밝힙니다.
- 의존성 없는 Node 서버가 실시간 응답을 20초 캐시하고 하루 950회 상한을 지킵니다. 출퇴근 시간대(평일 07:00–09:30, 17:00–20:00) 밖 호출은 하루 60회로 제한합니다.
구조
데이터 빌드공공 원본 → 노선 그래프·혼잡도·승하차 통계 JSON을 생성합니다.
역 선택노선도에서 역을 누르면 방향별 실시간 도착과 지금 시간대 혼잡도가 뜹니다.
ETA 보정도착 메시지(«n분 m초 후», «n번째 전역»)와 수신 시각 지연 보정으로 도착 시각을 다시 계산합니다.
착석 계산탑승역 혼잡도와 역별 하차로 정거장마다 누적 착석 확률을 구합니다.
판정누적 50%를 넘는 첫 역과 한 줄 판정을 보여 줍니다.
주요 기능
좌표 기반 노선도Canvas로 그린 노선도에서 핀치 줌·이동·노선 필터를 지원합니다.
정거장별 착석 타임라인출발·도착 역을 고르면 정거장마다 누적 착석 확률과 «앉을 것으로 보이는 역»을 보여 줍니다.
출퇴근 즐겨찾기자주 타는 구간을 출근·퇴근으로 나눠 저장하고, 지금 시간대에 볼 구간을 홈에 먼저 띄웁니다.
폴더블 2단 화면접으면 한 화면씩 하단 탭으로, 펼치면 왼쪽 노선도 | 오른쪽 역·착석 화면으로 나뉩니다.
호출 예산 관리서버가 캐시와 일일 호출 계수를 관리해 공식 한도 안에서만 실시간 데이터를 씁니다.
결과
- 노선 24개·역 656개 노선 그래프와 혼잡도·승하차 통계를 묶은 데이터 빌드를 완성했습니다.
- 실시간 도착 프록시·캐시·착석 모델 서버와 폴더블 안드로이드 앱(노선도·역·착석·즐겨찾기·설정)을 만들어 개인 서버에 배포했습니다.
- 혼잡도 통계가 없는 노선은 «예측 불가»로 표시하고, 즐겨찾기에서는 실시간 다음 열차로 대체해 보여 주도록 처리했습니다.
- 한계도 문서로 남겼습니다. 혼잡도 통계는 1~8호선만 있고, 칸별 차이는 아직 모델에 반영하지 않았습니다.
포인트
이 앱이 내는 값은 예측이 아니라 기대값입니다. 그래서 화면에 «통계 기반 추정»을 늘 밝히고, 데이터가 없는 노선은 숫자를 지어내지 않고 «예측 불가»로 표시했습니다. 모델보다 «모르는 것을 모른다고 보여 주는 화면»이 신뢰에 더 중요했습니다.
공식 문서만 읽었다면 도착 예정 초 필드를 그대로 썼을 것입니다. 실제로 호출해 보니 58%가 0이었고, 결국 사람이 읽는 메시지를 파싱하는 쪽이 정확했습니다. 공공 API는 쓰기 전에 실호출로 분포부터 보는 것이 맞았습니다.
기술
KotlinJetpack ComposeNode.js공공 지하철 실시간 APIOpenStreetMap 데이터Tailscalepm2
상단 영상은 실제 화면이 아니라 구조를 보여 주는 재구성 목업입니다.