B마트 OMS의 물류주문관리를 통한 출고 최적화

1 day ago 2

퀵커머스는 ‘지금’ 주문한 상품이 ‘금방’ 도착하는 경험을 제공합니다. 이러한 속도 중심의 서비스는 단순히 빠르기만 해서는 만족스럽지 않습니다. 고객에게는 정시성과 정확성, 라이더에게는 도착 시점의 일관성과 대기 최소화, 그리고 피패킹센터(PPC: Picking Packing Center) 현장 작업자에게는 예측 가능한 작업 부하와 안정적인 운영이 함께 보장되어야 비로소 완성도 높은 퀵커머스가 실현됩니다.

우아한형제들이 운영하는 B마트는 이러한 기준을 만족시키기 위해 자체 물류 주문 관리 시스템인 OMS(Order Management System) 를 중심으로 물류 최적화 전략을 실행하고 있습니다. OMS는 B마트에서 발생하는 모든 주문의 흐름을 제어하며, 주문 생성부터 출고, 배송까지의 전 과정을 유기적으로 연결합니다. 이를 통해 고객에게 신뢰도 높은 서비스 경험을 제공하고, 라이더와 피패킹센터 현장 작업자의 운영 효율성을 함께 고려합니다.

이번 글에서는 B마트 OMS의 전반적인 역할과, 2025년 상반기에 수행된 두 가지 핵심 프로젝트를 중심으로, 어떻게 실질적인 문제를 정의하고 해결했는지 소개합니다. 특히, 배송 지연과 과도한 라이더 대기시간이라는 퀵커머스의 본질적인 문제에 대응한 기획적 접근과 시스템 설계, 그리고 이를 통한 개선 성과를 정리함으로써, 실무자뿐 아니라 퀵커머스 도메인에 관심 있는 분들에게도 깊이 있는 인사이트를 제공하고자 합니다.

OMS 소개 및 주요역할


우아한형제들의 OMS는 B마트의 퀵커머스 서비스를 위한 전용 물류 플랫폼입니다. OMS는 단순한 주문처리 시스템이 아닌, 고객의 수령 경험현장의 작업 여건, 그리고 라이더의 업무 흐름까지 고려한 전방위 최적화 시스템입니다.

📌 늦은 밤, 배달이는 아침에 먹을 우유와 계란을 B마트 송파잠실점에서 오전 7~8시 사이에 받기 위해 예약 주문합니다. 현재 송파잠실점에는 계란이 없지만 이른 새벽 입고될 예정이기 때문에 OMS는 구매 가능 수량으로 제공하였습니다.

오전 6시 30분, 계란이 입고된 것을 확인한 OMS는 배달이가 원하는 시간에 문 앞으로 배달하기 위해 현장 작업 부하를 체크하고, 출고 작업에 소요될 시간을 고려하여 출고와 배달을 요청합니다.

시간 맞추어 송파잠실점에 도착한 라이더는 오전 7시 10분에 배달이의 문 앞으로 배달을 완료하였습니다.

이로써, 배달이는 신선한 우유와 계란을 원하는 시간에 먹을 수 있었습니다.

다음은 OMS의 핵심 기능입니다.

  • 🔁 주문 흐름 제어: 고객의 주문은 출하 단위인 Shipment로 분리되어 OMS를 통해 체계적으로 처리됩니다. 주문이 접수되면, 재고 상태를 확인하고 출고 가능 여부를 판단하며, 이후 배송 가능성을 고려해 후속 프로세스를 제어합니다.

  • 📊 판매 재고의 통합 관리: OMS는 가용재고, 입고 예정재고, 그리고 이미 할당된 재고를 실시간으로 반영하여 주문 가능 상태를 조정합니다. 이를 통해 품절 방지뿐 아니라 고객 신뢰도 유지에도 기여합니다.

  • 🕒 마감 할인 기능: 소비기한과 수요 예측 데이터를 바탕으로 자동으로 할인 대상 상품을 정의하고, 해당 수량 및 할인율을 유동적으로 조정합니다. 상품 폐기율을 줄이며 동시에 소비자에게는 합리적인 소비 기회를 제공합니다.

  • 📈 작업 효율 데이터 연동: OMS는 지점별 작업 인원, 과거 출고 처리량, 피크 타임 분석 등의 운영 데이터를 바탕으로 출고 요청 타이밍을 제어하고, 라이더 호출 시점을 결정합니다. 이는 실시간 현장 대응력을 높이기 위한 기반이 됩니다.

  • 정시성 관리와 SLA 준수 지원: OMS는 각 주문의 처리 이력을 추적하고, 실제 출고완료시각과 목표 출고 시각 간의 편차를 관리함으로써 정시성과 SLA(Service Level Agreement) 준수를 시스템 차원에서 지원합니다.

OMS는 이처럼 고객 중심 설계를 기반으로 하되, 라이더의 대기시간과 동선 효율, 그리고 현장 작업자의 물리적 부하를 실시간으로 반영함으로써 서비스 전반의 균형을 맞춥니다.

과제 소개 및 개요

2025년 상반기, OMS의 기능을 보다 실효성 있게 확장하기 위한 두 가지 과제를 추진했습니다. 서로 다른 주제지만, 모두 고객/라이더/현장 작업자의 주문 경험을 개선한다는 공통 목표가 있었습니다.

  • 과제 1: B마트 피크매니지먼트

    • 목표: 예약배달 주문을 유휴 시간에 분산하여 피크타임 출고 밀집 현상 해소
  • 과제 2: 동적 출고예정시각 산정 및 적용

    • 목표: 피패킹 센터 지점별 현장 상황을 반영한 출고예정시각 산정을 통해 라이더 대기 최소화와 배달 품질 균형 확보

다음 장에서는 두 과제를 ‘문제 및 목표’, ‘기획 방향’, ‘기술 방향’, ‘성과 및 효과’ 순서로 좀 더 구체적으로 소개하겠습니다.

문제 및 목표

퀵커머스 서비스 특성상, 특정 시간대에 주문이 몰리는 피크타임이 발생합니다. B마트의 예약배달은 ‘고객이 원하는 시간 안에 도착’해야 하는 요구사항이 강한 형태의 주문입니다. 그런데 피크 시간대에 주문이 집중되면, 출고 인력이 한정된 상황에서 출고 지연이 발생하고, 반대로 주문이 적은 시간대에는 유휴 인력이 생기는 등, 전체적인 작업 효율성이 떨어지는 문제가 있었습니다.

문제 상황 예시)
오전 8시 42분, 9시 예약 시간이 다가오자 수십개의 주문이 한번에 출고요청됩니다. 가뜩이나 처리 중인 주문이 많았던 피패킹센터(PPC)의 작업자들은 당황합니다. 주문은 멈추지 않고 계속 들어오고 있습니다. 다른 하던 일은 차차하고 모든 현장 작업자들은 출고작업에 투입됩니다. 하지만 제시간에 맞춰 출고하기에는 역부족입니다. 이미 도착한 많은 라이더들은 언제 완료되는지 기웃거리고 있습니다. 현장은 혼란스럽고, 라이더의 소중한 시간은 흐르고 있으며, 고객에게 배송되는 시간은 늦어집니다.

이를 해결하기 위한 핵심 전략은 예약배달 주문의 출고 요청을 유휴 시간대에 미리 분산 처리함으로써, 피크 시간의 부하를 줄이고 전체 출고 작업 시간대별 부하를 고르게 만들어 동일 수준의 인원으로 더 많은 주문을 제시간에 처리할 수 있는 효율을 확보하는 것이었습니다. 고객의 희망 수령 시각을 절대적으로 보장하면서도, 출고 현장의 효율을 높이는 방향으로 구조를 설계했습니다.

💡 바로배달과 예약배달

– 바로배달: 고객이 주문하는 즉시 ‘바로’ 출고작업과 배달이 진행되는 서비스
– 예약배달: 고객이 원하는 시간(예: 09:00~10:00)안에 고객의 문앞으로 배달되는 서비스

기획 방향

품질 보존과 정시 배송이라는 기본 고객 가치는 지키면서 실시간 현장의 출고 작업 부하를 판단하고 적정한 수의 주문을 출고 요청하도록 아래와 같이 기획하였습니다.

  1. 출고요청과 배달요청 분리:
    • 기존에는 출고 요청과 배달 요청이 동일 기준으로 이루어졌습니다.
    • 이를 분리하여, 출고는 여유가 있는 시간에 처리하되, 배달은 고객 수령 희망 시각에 맞추도록 설계했습니다.
  2. 품질 보존을 위한 분산 시점 정의:
    • 냉장 보관이 가능한 출고대기장이 있음에도 불구하고, 너무 일찍 출고된 상품은 신선도 저하 우려가 있었습니다.
    • 신선도 저하 이슈를 방지 할 수 있도록 출고요청 분산의 시작 시점과 종료 시점을 명확히 정의했습니다.
  3. 현장 여유 판단 로직 고도화:
    • 목표 생산성을 기준으로 작업 인원 수와 현재 출고량을 비교하여, 실시간 현장 작업의 여유 상태를 판단하는 로직을 도입했습니다.
  4. 재고 부족 방지와 주문 보존:
    • 예약배달 주문의 특성상 입고 예정 상품을 포함한 주문이 많아, 출고 직전에 재고 부족이 발생할 수 있습니다.
    • 이를 방지하기 위해 재고 부족 주문은 일단 SKIP하고, 고객 희망 시간 내 배송가능한 마지막 시점에 출고 요청하도록 설계했습니다.

기술 방향

이 과제의 핵심은 변경되는 출고 요청 로직을 정확하게 반영하면서, 그에 따른 시스템의 확장성과 안정성까지 함께 고려한 아키텍처를 설계하는 것이었습니다.
출고 요청은 단순한 트리거가 아니라, 피패킹센터(PPC) 단위로 실시간 처리 가능한 주문만 선별하여 분산 요청하는 핵심 비즈니스 로직입니다.
이 로직은 주문 처리의 효율성과 작업 안정성을 좌우하기 때문에, 변화에 강하고 물리적 제약을 유연하게 반영할 수 있는 구조가 무엇보다 중요했습니다.
 

1. PPC 확장 시 일관된 성능을 어떻게 유지했나요?

PPC는 물리적으로나 시스템에서 완전히 독립된 단위로 동작합니다.
이 점을 기반으로 시스템 아키텍처는 PPC 단위로 분리했고, 다음과 같은 방식으로 성능을 확보했습니다.

  • 단일 노드 내 멀티스레드 기반 PPC 병렬 처리
    하나의 노드 안에서도 각 PPC 단위를 멀티스레드로 병렬 처리해, 노드 리소스로 인한 병목을 피할 수 있었습니다.

  • 노드 단위 수평 확장
    한 노드로 감당하기 어려운 경우엔, 여러 노드에 PPC 그룹을 분산 배치해 확장성을 확보했습니다.

이 구조 덕분에 PPC 수가 늘어도 병목 없이 확장 가능하고, 각 PPC가 독립적으로 작동하기 때문에 여러 작업을 동시에 처리하면서도 확장하기 쉬운 구조를 만들 수 있었습니다.

2. 주문 수가 많아졌을 때도 성능을 유지할 수 있을까요?

이 부분은 단순히 시스템 처리 성능만으로는 판단하기 어렵습니다. 각 PPC는 작업 공간, 인력 수, 작업 순서 등 물리적인 제약이 있어서, 실제로 처리 가능한 주문 수에는 현실적인 한계가 있기 때문입니다.

그래서 시스템은 다음과 같은 철학을 바탕으로 설계했습니다.

  • 단건 기준의 성능을 확보한 상태라면, 전체 처리 시간은 결국 물리적 처리 능력에 따라 결정됩니다.

  • 불필요하게 높은 TPS를 위한 과도한 최적화는 피하고, 대신 비즈니스 로직의 정확성과 일관성 유지에 집중했습니다.

이렇게 현실적인 주문량과 물리적 병목 조건을 기반으로 설계함으로써, 과도한 복잡성을 피하면서도 안정적인 운영이 가능한 구조를 만들 수 있었습니다.

3. 비즈니스 규칙을 어떻게 예측 가능하게 구현했나요?

출고 요청은 복잡한 조건들이 얽힌 영역이라, 예측 가능하고 명확한 규칙 기반 설계가 필수였습니다.
이를 위해 다음과 같은 방식으로 접근했습니다.

  • 비즈니스 정의 수준을 그대로 코드에 반영
    단순히 기능 구현이 아니라, 기획서에 정의된 수식이나 조건을 거의 그대로 코드에 옮겨서
    해석의 여지를 없애고 유지보수를 쉽게 만들었습니다.

  • 동일한 입력에 대해 동일한 결과를 보장
    비즈니스 로직은 외부 상태나 순서에 의존하지 않도록 설계하여,
    같은 입력이 들어오면 언제나 같은 결과를 반환하도록 구현했습니다.
    이러한 결정은 테스트 자동화, 변수에 따른 결과 분석 시에도 큰 도움이 되었습니다.

  • 동일한 결과를 유지하되 더 효율적이거나 안전한 방식으로 리팩토링
    구현 과정에서 개선점이 발견되면, 코드만 바꾸는 게 아니라
    비즈니스 정의 자체도 함께 업데이트해서 늘 1:1로 매핑되도록 했습니다.

📌 비즈니스 규칙 예시 – PPC별 주문 처리 가능 건 수

비즈니스 정의:
MAX(0, (PPC 목표 생산성 × (1건당 처리 시간 ÷ 60분) × 작업 인원) - 현재 출고 중인 주문 수)

코드 구현:

class OrderProcessingCapacityService( private val centerProductivityCalculator: CenterProductivityCalculator, private val processingTimePerOrderCalculator: ProcessingTimePerOrderCalculator, private val outboundWorkerCountCalculator: OutboundWorkerCountCalculator, private val currentOrderProcessingCountCalculator: CurrentOrderProcessingCountCalculator ) { fun calculate(centerCode: String, requestedAt: LocalDateTime): Int { val centerProductivity = centerProductivityCalculator.calculate(centerCode, requestedAt) val processingTimePerOrder = processingTimePerOrderCalculator.calculate(centerCode, requestedAt) val outboundWorkerCount = outboundWorkerCountCalculator.calculate(centerCode, reqeustedAt) val currentOrderProcessingCount = currentOrderProcessingCountCalculator.calculate(centerCode, reqeustedAt) return max(0, (centerProductivity * (processingTimePerOrder / 60.0) * outboundWokrerCount) - currentOrderProcessingCount) } }

이처럼 비즈니스 정의와 코드 간의 표현 수준이 같고, 테스트 데이터가 동일하면 입력에 대한 결과가 항상 일정하기 때문에
정확한 테스트, 변경 대응의 용이성, 운영 시 신뢰도 확보라는 세 가지 측면에서 큰 장점을 얻을 수 있었습니다.

정리

이번 과제는 다음과 같은 방향성을 중심으로 설계되었습니다.

  • 변경 가능한 출고 요청 로직을 유연하게 반영할 수 있는 구조
  • PPC 단위의 물리적 제약 조건을 고려한 현실적인 처리 모델
  • 독립성과 병렬성을 활용한 확장 가능하고 안정적인 아키텍처
  • 비즈니스 정의를 그대로 코드로 구현한 명확하고 테스트 가능한 규칙 로직

이렇게 설계한 결과, 시스템은 변화에도 강하고 유지보수가 쉬우며, 무엇보다 실제 운영 환경에 맞는 성능과 안정성을 함께 갖춘 구조로 완성할 수 있었습니다.

성과 및 효과

해당 과제를 통해 아래와 같은 정량적, 정성적 성과를 확인 할 수 있었습니다.

  • 시간대별 주문 분포의 분산화: 1시간을 10분 단위로 나누어 분석한 결과, 특정 시간대에 몰리던 주문이 15~18%씩 균등 분배
  • 예약배달 주문의 평균 출고 처리 시간 2.2분 감소 (11.6분 → 9.4분, 약 19% 단축)
  • 출고대기장 운영 효율 증대 및 작업자 피로도 감소
  • 라이더의 도착 시점 출고 완료 비중 증가

문제 및 목표

OMS에서는 출고가 완료될 예정시각을 ‘출고예정시각’이라는 용어로 정의하고 있고, 이 시각을 기준으로 배달생성요청시 픽업준비소요시간으로 적용 하고 있습니다. 즉, ‘이때까지 출고가 완료될 예정이니 픽업하러 와주세요.’라는 의미로 사용되고 있습니다.

기존의 출고예정시각은 주문이 생성된 시점으로부터 고정된 시간(예: 10분)을 더하는 단순 계산식에 기반해 설정되고 있었습니다. 이러한 방식은 현장의 실제 출고 여건을 고려하지 않기 때문에, 특히 피크타임에 여러 주문이 동시에 밀려드는 경우 현실과의 괴리가 발생했습니다. 라이더는 픽업하러 왔지만 상품이 준비되지 않아 대기하는 일이 반복되었고, 서비스 품질 저하와 라이더의 작업 스트레스 및 B마트 배차 선호도 하락 가능성으로 이어질 수 있는 리스크였습니다.

이번 과제는 이러한 문제를 해결하기 위해, 출고예정시각을 현장 상황에 맞춰 동적으로 산정하는 로직을 개발해 라이더의 대기 시간을 줄이는 동시에 고객 배송 품질도 저하되지 않도록 균형을 맞추는 것이 목표였습니다.

💡 출고예정시각 이란

출고가 완료될 것으로 예상되는 시각을 말합니다. 이는 곧 라이더가 픽업할 수 있는 시점으로, ‘이때까지 출고가 완료될 예정이니 픽업하러 와주세요.’ 라는 의미로 사용됩니다.

기획 방향

출고 가능 인원 대비 출고 작업량이 일정 수준을 초과하면 추가시간이 발생할 것이고, 적절한 추가시간을 출고예정시각에 더해줄 수 있도록 아래와 같이 기획하였습니다.

  1. 출고처리 가능 인원 기반 모델 설계:
    • 단순히 총 인원이 아닌, 출고 작업이 가능한 인원(입고, 진열, 지원 등 업무를 병행하는 인력의 가용성 포함)을 기준으로 계산해야 했습니다.
    • 각 피패킹센터(PPC) 지점별 운영 형태와 작업자 전환 비율을 반영해 인력 가용성 로직을 커스터마이징할 수 있도록 설계했습니다.
  2. 생산성 기반 소요 시간 추가 방식 적용:
    • 지점의 구조 및 출고 전략 등을 고려한 피패킹센터 지점별 목표생산성을 기반으로 출고예정시각이 추가로 더 필요한 기준을 세웠고, 그 기준에 맞추어 예상 소요 시간을 더해가도록 했습니다.
    • 특정 기준을 초과했을때 어느정도 시간을 더해주어야 너무 과하게 산정하진 않으면서 라이더 대기시간을 최소화 할 수 있을지를 고려하였습니다.
  3. 시뮬레이션 기반 정합성 검증:
    • 새로운 출고예정시각 산정 로직을 실제 지점 데이터에 적용하여 하루치 주문 데이터를 순차 처리한 결과를 확인했습니다.
    • 기존 방식 대비 신규 모델 시뮬레이션에서 출고 지연과 조기 완료 편차가 줄어들고 있음을 시각화 자료와 정의한 지표를 통해서 확인했습니다.

기술 방향

이번 과제의 핵심은 주문별 출고예정시각을 동적으로 계산하되, 실제 운영 환경과 유사한 방식으로 시뮬레이션을 설계하고, 예측 가능하고 테스트 가능한 비즈니스 로직으로 구현하는 것이었습니다.

출고예정시각은 단순한 계산 값이 아니라, 주문-출고-배송까지 이어지는 흐름 전반의 컨트롤 지점이기 때문에 정확한 시점 예측과 함께 시뮬레이션의 신뢰도와 재현성 확보가 가장 중요한 포인트였죠.

1. 어떻게 시뮬레이션을 설계했을까요?

시뮬레이션은 단순히 시각을 계산하는 작업이 아닙니다.
실제 시스템에서 발생하는 주문, 출고, 배달 등 도메인 이벤트의 흐름을 최대한 그대로 재현하는게 핵심이었습니다.

이를 위해 먼저 다음과 같은 준비 과정을 거쳤습니다.

  • 이벤트 통합 및 시간순 정렬
    주문, 출고, 배달에서 발생한 이벤트 데이터를 통합하고, 이를 시간순으로 정렬해 시뮬레이션의 처리 흐름을 결정했습니다.

  • 실행 흐름의 선형화 및 외부 의존 제거
    실제 환경은 비동기이지만, 시뮬레이션에선 순차적으로 이벤트를 처리했습니다. 이 과정에서 WMS 같은 외부 시스템의 응답은 내부에서 Mock 처리해, 외부 의존 없이 테스트 가능한 흐름을 만들었어요.

2. 비동기 처리 이슈는 어떻게 해결했을까요?

실제 프로덕션 환경에서는 출고 요청뿐 아니라 여러 단계에서 비동기 작업이 발생합니다.
예를 들어 출고 요청 자체가 비동기로 처리되면서 특정 로직을 수행하고, 이후 WMS와 통신을 하는데, 이 비동기 작업들이 완료되기 전에 다음 이벤트가 처리되면 아직 반영되지 않은 상태로 계산이 진행돼서 결과가 잘못될 수 있습니다.

하지만 시뮬레이션 환경에서는 실제 WMS 응답을 기다릴 수 없고, 다음 이벤트는 미리 수집한 이벤트를 순차적으로 처리하기 때문에, 비동기 작업이 모두 완료되기 전에 다음 이벤트가 실행되면 문제가 발생할 수밖에 없었습니다.

그래서 시뮬레이션에서는 모든 비동기 작업이 완료될 때까지 기다렸다가 다음 이벤트를 처리하도록 흐름을 제어했습니다.

구현은 아래와 같이 했습니다.

fun process(event: SimulationEvent) { when (event.type) { ... } while (asyncTaskExecutor.threadPoolExecutor.queue.isNotEmpty() || asyncTaskExecutor.activeCount > 0); }

비동기 큐가 완전히 비워질 때까지 다음 이벤트 처리를 멈춰서, 프로덕션 환경과 비슷한 순서로 이벤트가 처리되도록 만들었습니다.

3. 시간은 어떻게 재현했을까요?

시뮬레이션에서 중요한 건 과거의 상태를 정확히 재현하는 것입니다.
하지만 LocalDateTime.now() 같은 실시간 호출을 그대로 쓰면, 실행 시점마다 결과가 달라져서 테스트가 어려워집니다.

그래서 다음과 같은 방식으로 개선했습니다.

  • 컨텍스트 내에서 동일한 현재 시각이 필요한 경우 메서드 시그니처를 수정해 시각을 외부에서 주입
// AS-IS fun requestOutbound() { val requestedAt = LocalDateTime.now() ... } // TO-BE fun requestOutbound(requestedAt: LocalDateTime) { ... }
  • 중간 처리 로직 시점의 현재 시각이 필요한 경우 DI 기반의 시간 프로바이더(TimeProvider)를 활용
class ShipmentEventListener( ... private val currentTimeProvider: CurrentTimeProvider ) { @Async @TransactionalEventListener fun requestOutbound(...) { ... // AS-IS: // val now = LocalDateTime.now() // TO-BE: val now = currentTimeProvider.now() ... } }
  • JPA 엔티티 생성/수정 시각은 Auditing 설정을 변경해 시뮬레이션 시간을 반영
... @EnableJpaAuditing( dateTimeProviderRef = "simulatedDateTimeProvider", ) class SimulationApplication fun process(event: SimulationEvent) { simulatedDateTimeProvider.now = event.eventAt ... }

이렇게 해서 시뮬레이션과 실제 데이터를 일치시킬 수 있었고, 완전히 동일한 테스트 재현이 가능해졌습니다.

4. 시뮬레이션과 실제 환경의 차이는 어떻게 맞췄을까요?

시뮬레이션에서는 주문이 순차적으로 출고 요청되고, 그 흐름에 따라 출고예정시각이 계산되는 걸로 가정했습니다.

하지만 실제 운영 환경에서는 출고 요청이 재고 확인, 파티션 처리 등 다양한 요인으로 인해 반드시 순차적으로 진행되지 않습니다.

이 차이를 줄이기 위해 설계를 다음과 같이 조정했습니다.

  • 기존엔 주문번호 기반 파티셔닝으로 출고 요청을 처리했는데, 이 경우 재고 충돌이나 동시성 이슈로 예측 불가능한 지연이 생겼습니다.

  • 개선된 구조에서는 센터 코드 기반 파티셔닝으로 변경했습니다. 덕분에 보다 예측 가능한 순차적 흐름이 만들어졌고, 시뮬레이션의 전제와 실제 운영 간의 간극도 줄일 수 있었습니다.

5. 성능 문제는 없었을까요?

출고 요청이 순차적으로 이뤄진다는 점에서 성능 병목에 대한 우려가 생길 수 있지만, 실제로는 괜찮았습니다.

그 이유는 다음과 같습니다.

  • 실제 병목은 시스템이 아니라 작업 인력, 피킹 속도, 현장 처리 능력 쪽에서 먼저 발생

  • 출고요청 지연이 시스템 병목의 주요 원인이 되는 경우는 거의 없었음

결국 물리적인 처리 한계가 먼저 도달하기 때문에, 시스템 복잡도나 병렬성에 과도하게 신경 쓰지 않아도 목표 성능을 충분히 만족할 수 있었습니다.

✅ 정리

이번 과제는 다음과 같은 방향으로 설계되고 구현되었습니다.

  • 실제 운영 환경과 유사한 이벤트 흐름 시뮬레이션
  • 비동기 흐름을 제어 가능한 방식으로 순차 처리
  • 시간 재현성 확보를 위한 시간 주입 및 Auditing 제어
  • 프로덕션-시뮬레이션 간 차이를 줄이기 위한 파티셔닝 구조 개선
  • 물리적 한계를 고려한 현실적인 성능 판단 기준

이러한 접근 덕분에 출고예정시각을 정확하게 동적으로 계산할 수 있었고, 예측 가능하고 테스트 가능한 구조로 안정적인 운영까지 이어질 수 있었습니다.

성과 및 효과

일부 지점에서 파일럿을 시행한 결과는 다음과 같습니다.

  • 출고예정시각과 실제 출고완료시각 간의 편차(표준편차 기준)가 35.7% 감소 (4.9분 → 3.15분)
  • 라이더의 평균 대기시간이 86.67% 이상 감소 (0.75분 → 0.1분)
    • 5분 이상 대기율: 5.9% → 0.4%
    • 10분 이상 대기율: 0.8% → 0.04%

이번 두 과제를 통해 B마트의 OMS는 단순한 주문 관리 시스템을 넘어, 물류 운영의 실질적 퍼포먼스를 개선하는 플랫폼으로 진화하고 있음을 입증했습니다. 출고 요청의 시점을 유연하게 조정하고, 출고예정시각을 실제 현장 상황에 맞게 산정함으로써, 고객의 배송 경험뿐 아니라 라이더의 업무 만족도, 현장 작업자의 처리 효율까지 함께 고려한 통합적 개선을 이룰 수 있었습니다.

앞으로도 OMS를 고도화하여 B마트의 물류 경쟁력을 높이고, 고객에게는 더 빠르고 정확한 배송을, 라이더에게는 신뢰할 수 있는 픽업 경험을, 현장에게는 예측 가능한 운영 환경을 제공하고자 최적화를 위한 노력을 이어가겠습니다.


더 보기

우아한형제들의 물류플랫폼이 궁금하신가요?

이준한

고객에게 사랑받고, 사업적으로 가치 있는 퀵커머스 서비스를 만드는 것을 목표로 물류프로덕트를 기획하고 있습니다.좋은 사람들과 웃으며 일하는 것을 가장 중요하게 생각하는 PM입니다.

Read Entire Article