2호선 순환선은 지연이 발생하면 열번이 바뀌어, 같은 열차를 계속 추적할 수 없었습니다.
SMSS 응답을 열린데이터 응답과 병합·중복 제거하고, trainNo 앞자리를 노선 규칙에 맞게 강제 보정하는 로직을 만들었습니다.
지연 상황에서도 편성 추적 연속성이 유지됩니다.
불안정한 공공 API 위에서 서비스 품질을 지키는 구조를 골랐습니다.
SMSS와 열린데이터는 응답 스키마·필드 의미가 다릅니다. 폴백 분기를 서비스 로직에 두면 '어느 소스에서 왔는지'가 비즈니스 코드 전체로 번집니다. 그래서 두 소스를 각각 래퍼로 감싸 동일한 ttcVOList 포맷으로 정규화하고, 상위 로직은 소스의 존재 자체를 모르게 했습니다. 포트/어댑터를 교과서로 배우기 전에 필요해서 먼저 도달한 구조인데, 덕분에 폴백 전환이 무공수 스왑이 됩니다.
공공 API는 열차 편성(어떤 차량이 몇 량인지) 정보를 주지 않습니다. 크롤링으로 풀 수 없는 데이터라, 사용자 제보 → 투표 검증 → 반영의 크라우드소싱 루프를 설계해 데이터 자체를 사용자와 함께 만들었습니다. 모든 문제를 코드로 풀지 않는 것도 설계 결정이라고 생각합니다.
공공 API의 불안정성을 서비스 품질로 흡수하는 데 집중했습니다.
열차위치조회·편성정보·운행계획·크라우드소싱 4개 서비스 도메인으로 설계한 백엔드입니다. SMSS 실패 시 열린데이터 API로 자동 폴백하는 이중 API 시스템을 구축하고, Express.js REST API와 gRPC 서버를 병행 운영합니다. Redis 캐싱과 MongoDB로 데이터 지속성을 확보하며, Firebase Analytics로 지역별 사용자 분포와 트래픽 패턴을 분석합니다.
Promise.all 기반 병렬 API 호출로 전체 노선 업데이트 시간을 75% 단축하고, 압축 미들웨어로 네트워크 트래픽을 40% 절감했습니다. Redis 캐싱으로 평균 응답시간 150ms 이하, 99.5% 가용성을 유지하며 일 평균 1,400+ DAU를 처리합니다.
HMAC-SHA256 해시와 Nonce를 활용한 디지털 서명 검증 시스템을 구축하고, JWT 인증과 Rate Limiting, IP 지역 제한으로 보안을 강화했습니다. Winston 구조화 로깅과 에러 처리로 24/7 안정 운영을 달성했습니다.
데이터로 서비스 방향을 결정했습니다.
Firebase Analytics 기반 분석 결과 서울 68%·경기 22%·기타 10%로 수도권 사용자가 90%를 차지합니다. 90일간 12M+ 이벤트, 일 평균 1,400+ DAU를 유지하며, 크라우드소싱 편성 투표로 사용자 참여를 유도했습니다.
마주친 문제 · 고민하고 적용한 접근 · 실제 결과를 한 세트로 묶어 정리했습니다.
2호선 순환선은 지연이 발생하면 열번이 바뀌어, 같은 열차를 계속 추적할 수 없었습니다.
SMSS 응답을 열린데이터 응답과 병합·중복 제거하고, trainNo 앞자리를 노선 규칙에 맞게 강제 보정하는 로직을 만들었습니다.
지연 상황에서도 편성 추적 연속성이 유지됩니다.
단일 공공 API(SMSS)가 불안정해 장애 시 서비스 전체가 멈췄습니다.
서울시 열린데이터 광장 API를 동일 포맷(ttcVOList)으로 감싸 자동 폴백 계층을 만들고, 노선별 특수 파라미터를 객체로 분리했습니다.
단일 API 장애에도 서비스가 지속됩니다.
20개 노선을 순차 폴링하면 전체 갱신 주기가 목표(15초)를 넘었습니다.
Promise.all 기반 병렬 호출로 재구성하고 응답 압축을 적용했습니다.
전체 노선 업데이트 시간 75% 단축, 트래픽 40% 절감.