프로젝트 목록

(주)사운드마인드

오디야 보호자 앱

GPS는 자주 틀립니다. 틀린 것을 그럴듯하게 보여주는 대신, 모르는 것은 모른다고 말하는 화면을 만들었습니다.

역할
위치 해석 로직과 화면 설계 · 구현
기간
2025.07 ~ 현재
사용 기술
React NativeTypeScriptTanStack QueryZustandNaver MapSTOMP
앱 / 클라이언트네이티브서버워커저장소외부
부모 앱은 서버를 폴링해 위치를 읽고, 푸시는 조회를 앞당기는 신호로만 씁니다. 화면 수정은 스토어 심사 없이 OTA로 배포됩니다.블록에 마우스를 올리면 연결된 흐름만 강조됩니다. 드래그로 이동, 버튼으로 확대할 수 있습니다.

개선 결과

  • 89개

    위치 해석 로직에 붙인 단위 테스트

  • 956역

    지하철 추론에 사용하는 역 데이터 (47개 노선)

  • 3단

    이동 수단 추측이 통과해야 하는 필터

01문제

부모가 보는 화면은 자녀 단말이 올린 좌표를 그대로 찍는 것으로는 쓸모가 없습니다. 집에 두 시간 있었다, 지하철로 이동한 것 같다, 지금은 학교 근처다 같은 말로 바꿔야 비로소 정보가 됩니다. 문제는 원본 데이터가 깨끗하지 않다는 점이었습니다. 실내에서는 GPS가 흔들리고 지하철에서는 아예 끊깁니다. 해석을 잘못하면 부모가 틀린 정보를 사실로 믿게 되는데, 자녀 안전과 직결된 서비스에서 이것은 기능이 없는 것보다 나쁩니다.

02제약

가장 큰 제약은 데이터가 아니라 사용자 쪽에 있었습니다. 자녀 단말 앱은 스토어를 통해 배포되는데, 실제로 현장에서 도는 단말의 대부분이 구버전이었습니다. 새로 만든 해석 화면은 구버전이 보내지 않는 필드를 필요로 했습니다. 실시간 추적에는 다른 문제가 있었습니다. 앱과 서버가 각자 상태를 판단하다 보니 서로 어긋나는 일이 잦았습니다.

  • 실내 GPS 흔들림 때문에 한 장소에 머문 것이 여러 개로 쪼개져 표시됐습니다
  • 지하철 구간은 좌표가 통째로 비어 있어 추측 외에는 방법이 없습니다
  • 구버전 자녀앱은 해석에 필요한 필드를 보내지 않습니다
  • 실시간 추적에서 앱과 서버가 각자 판단해 상태가 어긋났습니다

03검토한 대안

GPS가 끊긴 구간을 화면에 어떻게 표현할지가 핵심이었습니다. 비어 있는 시간을 그냥 두면 부모가 불안해하고, 채워 넣으면 틀릴 수 있습니다.

장점문제
공백을 직선으로 잇기경로가 끊기지 않아 보기에 자연스러움건물을 관통하는 직선이 그려지고, 실제로 가지 않은 경로를 사실처럼 보여줌
공백을 비워두기틀릴 여지가 없고 구현이 단순함지하철로 이동한 30분이 통째로 사라져, 부모가 위치 추적이 고장 났다고 인식함
조건을 모두 만족할 때만 추론채택맞을 때만 표시하므로 신뢰를 잃지 않고, 아닐 때는 공백으로 남겨 오해를 만들지 않음필터를 통과하지 못하는 실제 이동도 표시되지 않아 커버리지를 일부 포기해야 함

04선택과 근거

커버리지를 일부 포기하는 쪽을 골랐습니다. 자녀 안전과 직결된 화면에서는 한 번의 오표시가 기능이 없는 것보다 손해가 큽니다. 부모가 화면을 한 번 의심하기 시작하면 맞는 정보까지 믿지 않게 되기 때문입니다. 그래서 틀릴 바에는 보여주지 않는다를 원칙으로 삼고 해석이 들어가는 모든 지점에 같은 기준을 적용했습니다.

지하철 이동을 표시하기까지

커버리지를 포기하는 대신, 화면에 뜬 것은 믿을 수 있습니다

  • 지하철 이동은 역 매칭, 거리, 소요시간 세 조건을 모두 통과해야 표시
  • 경로의 공백 판정은 한 곳에서만 계산해, 다른 값으로 그려 선이 겹치는 일을 방지
  • 체류 군집은 시작점에서 반경 3배를 넘어야 분리하고, 자정을 넘긴 체류는 날짜별로 분할
  • 구버전 자녀앱 사용자에게는 해석 화면 자체를 비활성화
  • 실시간 추적은 서버 세션이 진실이고, 푸시는 다음 조회를 앞당기는 신호로만 사용

05구현과 시행착오

해석 규칙은 말로 정하기는 쉬운데 코드로 지키기가 어려웠습니다. 조건을 하나 고치면 다른 화면이 조용히 깨지는 일이 반복돼, 규칙을 화면에서 떼어내 순수 함수로 옮기고 테스트로 고정했습니다.

  • ① 체류 판정을 시작점 기준 고정 반경으로 만들었더니 천천히 이동하는 구간이 한 장소로 뭉쳤습니다. 현재 중심을 따라가되 시작점에서 반경 3배를 넘으면 분리하도록 바꿨습니다.
  • ② 자정을 넘긴 체류가 양쪽 날짜에 모두 전체 시간으로 잡혔습니다. 날짜 경계에서 잘라 각각 합산하도록 수정했습니다.
  • ③ 경로의 공백을 화면마다 따로 계산했더니 같은 구간에 선이 겹쳐 그려졌습니다. 계산 지점을 하나로 통일했습니다.
  • ④ 채팅 메시지가 중간에 잘려 도착했습니다. 프레임 종단 문자에서 문자열이 절단되는 것을 확인하고 전송 방식을 바꿔 해결했습니다.
  • ⑤ OS 글자 확대 설정에서 지도 위 라벨이 겹쳤습니다. 텍스트 컴포넌트를 감싸 확대를 무력화했는데, 기존 방식이 조용히 동작을 멈춘 상태였습니다.

06결과

해석 규칙은 전부 순수 함수로 분리하고 단위 테스트 89개를 붙였습니다. 반경을 몇 배로 볼지, 자정을 어떻게 처리할지, 공백을 어디서 판정할지 같은 규칙이 미묘해서 코드만으로는 지켜지지 않기 때문입니다. 실내 체류가 쪼개지던 문제와 잘못된 지하철 추측이 사라졌고, 구버전 사용자에게 빈 화면이 보이던 문제도 없어졌습니다. 부가로, 채팅 메시지가 중간에 잘려 도착하는 원인을 추적해 React Native가 문자열을 보낼 때 특정 문자에서 자른다는 것을 확인하고 전송 방식을 바꿔 해결했습니다.