본문으로 건너뛰기

오프라인 우선

개념 정의

오프라인 우선은 PDA가 네트워크에 항상 연결되어 있지 않아도 현장 작업을 일정 범위 안에서 계속할 수 있도록 설계하는 방식입니다. 모든 기능을 오프라인으로 허용한다는 뜻은 아닙니다. 스캔처럼 현장에서 멈추면 안 되는 작업은 로컬에 먼저 기록하고, 확정처럼 서버 검증이 필요한 작업은 온라인 상태에서 처리하도록 경계를 나누는 것입니다.

창고 PDA는 일반 웹 관리 화면과 환경이 다릅니다. 작업자는 이동하면서 스캔하고, 무선 신호가 약한 구역이 있으며, 같은 바코드가 짧은 시간에 반복 입력됩니다. 따라서 서버 요청 실패를 곧바로 작업 실패로 처리하면 현장이 멈춥니다.

실제 업무 흐름

오프라인 우선 PDA의 기본 흐름은 다음과 같습니다.

  1. 작업 시작 전 작업 목록, 상품, 바코드, 로케이션 정보를 내려받습니다.
  2. 작업자가 로케이션 또는 상품을 스캔합니다.
  3. PDA는 스캔 이벤트를 로컬 큐에 저장합니다.
  4. 화면은 로컬 큐 기준으로 진행률을 즉시 보여줍니다.
  5. 네트워크가 가능하면 큐를 서버에 전송합니다.
  6. 서버는 멱등 키로 중복 여부를 확인하고 업무 검증을 수행합니다.
  7. 성공한 이벤트는 SYNCED, 실패한 이벤트는 FAILED 또는 CONFLICT로 표시합니다.
  8. 충돌이 있으면 작업자가 해결할 수 있는 업무 메시지를 보여줍니다.

이 흐름에서 중요한 점은 "작업자 경험은 끊기지 않게", "서버 확정은 엄격하게" 가져가는 것입니다.

화면/기능 관점 설명

PDA 화면은 네트워크 상태와 동기화 상태를 작업자가 이해할 수 있어야 합니다.

기능설명
작업 목록 캐시온라인일 때 내 작업을 내려받아 오프라인에서도 표시
스캔 즉시 반영로컬 큐 저장 후 화면 진행률 증가
동기화 배지대기, 전송중, 완료, 실패 표시
충돌 해결 화면서버와 수량이 달라진 이벤트를 확인하고 재처리
수동 재전송실패 이벤트를 작업자가 다시 전송
작업 잠금 안내서버 검증이 필요한 확정 버튼은 오프라인에서 제한

예를 들어 피킹 화면에는 "지시 10개 / 로컬 스캔 8개 / 서버 반영 6개"처럼 표시할 수 있습니다. 이 차이를 숨기면 작업자는 완료됐다고 생각하지만 서버에는 일부만 반영된 상태가 됩니다.

백엔드 API 관점 설명

서버 API는 오프라인 큐의 재전송을 전제로 설계해야 합니다.

API역할
GET /api/pda/bootstrap작업에 필요한 기준정보 내려받기
GET /api/pda/tasks작업 목록 조회
POST /api/pda/scan-events/bulk여러 스캔 이벤트 일괄 전송
GET /api/pda/sync-status?taskId=...서버 반영 상태 조회
POST /api/pda/events/{eventId}/retry실패 이벤트 재처리
POST /api/outbound-tasks/{id}/complete-picking서버 검증 후 피킹 완료

스캔 이벤트 전송 예시는 다음과 같습니다.

{
"deviceId": "PDA-17",
"workerId": "worker-17",
"events": [
{
"scanEventId": "PDA-17-20260616-000001",
"taskId": "PICK-10001",
"scanType": "ITEM",
"barcode": "8800000000012",
"quantity": 1,
"scannedAt": "2026-06-16T09:10:00+09:00"
}
]
}

서버는 scanEventId를 유니크 키로 저장합니다. 같은 이벤트가 다시 오면 재반영하지 않고 기존 처리 결과를 반환해야 합니다.

데이터베이스 테이블 관점 설명

오프라인 우선 설계에는 로컬 저장소와 서버 테이블이 모두 필요합니다.

PDA 로컬 저장소 예시:

store역할
cached_tasks내려받은 작업 목록
cached_items상품/바코드 기준정보
scan_queue전송 대기 중인 스캔 이벤트
sync_log동기화 시도와 오류 기록

서버 테이블 예시:

테이블주요 컬럼
pda_devicedevice_id, warehouse_id, last_seen_at
pda_scan_eventscan_event_id, task_id, barcode, qty, status
pda_sync_batchbatch_id, device_id, status, received_at
outbound_task_progresstask_id, picked_qty, synced_qty, version

상태값 예시

스캔 이벤트 상태는 다음처럼 나눌 수 있습니다.

상태의미
PENDING로컬에 저장됐지만 아직 서버 전송 전
SYNCING서버 전송 중
SYNCED서버 반영 완료
FAILED네트워크 또는 서버 오류
CONFLICT서버 업무 상태와 충돌
IGNORED_DUPLICATE이미 처리된 이벤트

작업 완료 상태와 스캔 동기화 상태를 섞지 않는 것도 중요합니다. 작업은 PICKING인데 일부 스캔은 FAILED일 수 있습니다.

예외 상황

예외처리 방향
네트워크 끊김로컬 큐에 저장하고 화면에 전송 대기 표시
앱 강제 종료재실행 시 큐 복구
같은 이벤트 재전송멱등 키로 기존 결과 반환
서버에서 작업 취소됨큐 이벤트를 CONFLICT로 표시
기준정보 변경캐시 버전 확인 후 작업 중단 또는 갱신
수량 초과 스캔로컬에서 1차 차단, 서버에서 최종 검증
단말 시간 오류서버 수신 시각과 PDA 스캔 시각을 모두 저장

실무에서 자주 생기는 문제

  • 오프라인 큐 없이 API 실패 시 작업자에게 다시 스캔하라고 해서 중복 반영이 생긴다.
  • 로컬 진행률과 서버 반영 진행률을 구분하지 않아 완료 착시가 생긴다.
  • 스캔 이벤트 id가 없어 재시도와 중복 스캔을 구분하지 못한다.
  • 오프라인에서 출고확정까지 허용해 재고 부족이나 마감 상태를 뚫는다.
  • 기준정보 캐시가 오래되어 변경된 바코드를 인식하지 못한다.

설계 시 주의사항

오프라인 허용 범위를 명확히 정해야 합니다. 피킹 스캔 저장은 오프라인 허용이 가능하지만, 출고 확정, 재고 조정 승인, 마감 기간 변경 같은 액션은 온라인 서버 검증을 거쳐야 합니다. 또한 PDA 이벤트는 "명령"이 아니라 "현장에서 발생한 사실"로 저장하고, 서버가 업무 규칙에 따라 반영 여부를 결정하는 구조가 안전합니다.

간단한 예시 테이블

scan_event_idtask_idbarcodeqtylocal_statusserver_status
PDA-17-001PICK-1000188000000000121SYNCEDAPPLIED
PDA-17-002PICK-1000188000000000121PENDING없음
PDA-17-003PICK-1000188000000000991CONFLICTINVALID_ITEM

관련 문서 링크