티스토리 뷰

물류 센터는 프론트엔드 엔지니어에게 가혹한 환경입니다. 수천 평의 창고 부지에는 필연적으로 Wi-Fi 음영 구역이 존재하며, 이동 중인 로봇에 탑재된 클라이언트는 시시각각 네트워크 단절과 지연을 경험합니다.

이러한 환경에서 '데이터 정합성''끊김 없는 사용자 경험(UX)'이라는 두 마리 토끼를 잡기 위해 고민했던 기술적 해결책들을 공유합니다.


1. 직면한 문제: "로봇은 움직이는데, 데이터는 멈췄다"

자율주행 물류 피킹 서비스를 운영하며 가장 빈번하게 발생한 문제는 네트워크 불안정으로 인한 서비스 이탈이었습니다.

  • UI 프리징: API 응답을 기다리는 동안 화면이 멈추거나 로딩 스피너가 무한히 도는 현상.
  • 데이터 오염: 네트워크 지연 중 사용자의 중복 클릭으로 인해 동일한 작업 명령이 여러 번 전송되는 문제.
  • 가시성 저하: 관리자 페이지와 현장 로봇 간의 작업 상태가 일치하지 않아 운영 효율 저하.

2. 해결 전략: 신뢰할 수 있는 클라이언트 구축

단순히 "네트워크를 좋게 만드는 것"은 엔지니어의 영역 밖이었기에, "네트워크가 나빠도 신뢰할 수 있는 앱"을 만드는 데 집중했습니다.

① Service Worker를 통한 오프라인 가용성 확보

네트워크가 완전히 끊긴 상황에서도 앱이 '깨지지 않는 것'이 최우선이었습니다. Service Worker를 도입하여 정적 자산을 캐싱하고, 오프라인 감지 시 사용자에게 명확한 안내 UI를 제공했습니다. 이를 통해 사용자는 앱이 고장 난 것이 아니라 네트워크 환경의 문제임을 즉각 인지하고 불필요한 재시도를 멈출 수 있었습니다.

② GraphQL Apollo Subscription 헬스 체크 최적화

실시간 로봇 상태를 수신하기 위해 WebSocket(Subscription)을 사용했지만, 소켓 연결은 유지되어도 내부 데이터 전송이 지연되는 '좀비 커넥션' 문제가 발생했습니다.

이를 해결하기 위해 커스텀 헬스 체크 로직을 추가했습니다. 서버와 Ping-Pong 메시지를 주고받으며 지연을 확인하고, 응답 시간이 임계치를 넘어서면 기존 연결을 강제로 끊고 재연결을 시도합니다.

sequenceDiagram
    participant S as 서버
    participant C as 클라이언트

    Note over S, C: WebSocket 연결 수립 (구독)
    S->>C: 핑 (Ping)
    C->>S: 퐁 (Pong, 정상)

    Note right of C: 네트워크 지연 발생
    S->>C: 핑 (Ping)
    Note over C: 헬스 체크 임계치 초과

    C->>C: 연결 강제 종료
    C->>S: 새로운 연결 요청
    S-->>C: 데이터 동기화 및 재연결 완료

③ 멱등성 기반의 비동기 동기화 전략

가장 핵심적인 변화는 '선 조작 후 최종 단계 동기화' 구조의 도입입니다.

  • 상태 기반 업데이트(State-based): "물품 1개 추가"와 같은 증분(Incremental) 명령 대신, 클라이언트가 이미 계산을 끝낸 최종 결과값(예: "현재 물품 수량은 2개")만을 동기화하도록 설계했습니다.
graph TD
    subgraph "증분 방식 (불안정)"
        A1[액션: +1] -->|네트워크 지연| B1(재시도: +1)
        B1 --> C1{서버}
        A1 --> C1
        C1 -->|결과| D1[최종 결과: 2]
    end

    subgraph "상태 기반 (안정 / 멱등)"
        A2[액션: 수량=1] -->|네트워크 지연| B2(재시도: 수량=1)
        B2 --> C2{서버}
        A2 --> C2
        C2 -->|결과| D2[최종 결과: 1]
    end
  • 비차단 로컬 우선 UX (Non-blocking Local-First): 중간 과정의 모든 액션은 서버 응답을 기다리지 않는 비동기 명령 전파(Asynchronous Command) 방식으로 처리했습니다.
  • 체크포인트 기반 2단계 정합성 보장: 작업을 마무리하는 핵심 시점(예: 피킹 완료 버튼 클릭)을 체크포인트로 설정합니다. 여기서 단순히 완료 요청을 보내는 것이 아니라, 1) 그동안 전파된 모든 벌크 데이터의 최종 상태가 서버와 일치하는지 먼저 확인(Reconciliation)하고, 2) 정합성이 확인된 상태에서만 최종 완료 명령을 수행합니다.
sequenceDiagram
    participant U as 사용자 (작업자)
    participant C as 클라이언트 (앱)
    participant S as 서버

    Note over U, C: [1단계: 비차단 작업 진행]
    U->>C: 물품 1 피킹 (수량: 1)
    C->>U: UI 업데이트 (즉시 반영)
    C-->>S: 비동기 명령 전파 (최종 수량: 1)

    U->>C: 물품 2 피킹 (수량: 2)
    C->>U: UI 업데이트 (즉시 반영)
    C-->>S: 비동기 명령 전파 (최종 수량: 2)

    Note over U, S: 네트워크 지연으로 일부 명령 전달 지연 가능성

    Note over U, C: [2단계: 체크포인트 정합성 확정]
    U->>C: "피킹 완료" 클릭
    C->>S: 벌크 데이터 최종 정합성 확인 요청
    S-->>C: 모든 데이터 동기화 확인 (Sync OK)

    Note over C, S: 데이터가 일치할 때만 최종 완료 단계 진입
    C->>S: 작업 최종 완료(Finalize) 요청
    S-->>C: 작업 종료 및 다음 태스크 할당 (200 OK)
    C->>U: 최종 성공 알림 및 화면 전환

3. 결과 및 회고

이러한 개선 과정을 통해 다음과 같은 성과를 얻을 수 있었습니다.

  1. 데이터 정합성 100%: 네트워크 장애 상황에서도 중복 작업이나 데이터 누락 없이 안정적인 운영이 가능해졌습니다.
  2. 작업 생산성 향상: 로딩 대기 시간이 사라짐에 따라 현장 작업자의 심리적 불안감이 해소되었고, 이는 곧 작업 속도 향상으로 이어졌습니다.
  3. 운영 공수 절감: 관리자와 현장의 데이터 불일치로 인해 발생하던 확인 절차가 획기적으로 줄어들었습니다.

프론트엔드 엔지니어링은 단순히 화면을 예쁘게 만드는 것을 넘어, 시스템의 제약 사항을 기술적으로 극복하여 비즈니스의 연속성을 확보하는 일임을 다시 한번 체감한 프로젝트였습니다.


다음 편 예고:
2편: 1대의 PC로 40대의 로봇을 검증하기: Playwright 기반 병렬 테스트 자동화

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함