자연드림 구례 WCS 프로젝트 회고

Essay

자연드림 구례 WCS 프로젝트는 물류자동화의 거의 모든 프로세스가 들어간 대형 프로젝트입니다.

무엇을 만들어야 하는가?

자연드림 구례 물류센터는 총 3개 층으로 구성되어 있으며 다양한 물류자동화 설비가 적용된 대형 센터였습니다 굵직하게는 검수, 입고, 보관, 출고, 보충, 피킹, 합포, 팔레타이징 등의 업무가 있었고 각 업무마다 세부적인 프로세스도 상당히 다양했습니다.

저는 이 프로젝트에 백엔드 개발자로 참여했습니다.

주로 다음과 같은 비즈니스 로직을 담당했습니다.

  • 입고 시 어떤 랙의 어떤 셀에 상품을 적재할 것인지
  • 보충 시 어떤 상품을 얼마만큼 어떤 플로우랙에 어떤 경로로 보충할 것인지
  • 합포 시 어떤 재고에서 어떤 박스로 어떤 상품을 합포할 것인지
  • 출고 시 어떤 상품을 어느 위치에서 꺼내야 하는지

백엔드 개발로 참여하였지만 프로젝트 중간에 냉동 합포용 WPF 애플리케이션도 추가로 개발하게 되었습니다.

돌이켜보면 이 프로젝트는 제가 경험했던 물류자동화 프로젝트 중에서도 가장 많은 것을 경험할 수 있었던 프로젝트였습니다. 그리고 동시에 가장 아쉬움이 많이 남은 프로젝트이기도 합니다.

아쉬운 인터페이스 방식

물류센터에는 정말 다양한 시스템과 설비가 들어갑니다.

하나의 애플리케이션이 모든 설비를 직접 제어하는 구조가 아닙니다. 크게 보면 사람으로 치면 뇌의 역할을 하는 WCS가 있고, WCS의 명령을 받아 실제 설비를 움직이는 ECS가 있습니다.

---
config:
  layout: elk
---
flowchart TB
    WES["WCS"]

    DB["Interface DB"]

    subgraph device["설비"]
        ECS_1["ASRS ECS"]
        PLC_1["ASRS PLC"]

        ECS_2["AGV ECS"]
        PLC_2["AGV PLC"]

        ECS_3["Conveyor ECS"]
        PLC_3["Conveyor PLC"]

        ECS_4["DPS ECS"]
        PLC_4["DPS System"]

        ECS_5["Palletizer ECS"]
        PLC_5["Palletizer Robot"]

        ECS_6["GTP ECS"]
        PLC_6["GTP PLC"]

        ECS_7["Shuttle Rack ECS"]
        PLC_7["Shuttle Rack PLC"]

        ECS_8["DAS ECS"]
        PLC_8["DAS System"]

        ECS_9["합포 ECS"]
    end

    WCS <--> DB

    DB <--> ECS_1 --> PLC_1
    DB <--> ECS_2 --> PLC_2
    DB <--> ECS_3 --> PLC_3
    DB <--> ECS_4 --> PLC_4
    DB <--> ECS_5 --> PLC_5
    DB <--> ECS_6 --> PLC_6
    DB <--> ECS_7 --> PLC_7
    DB <--> ECS_8 --> PLC_8

    WCS <-- "HTTP" --> ECS_9

당시 시스템은 Interface DB를 두고 서로 폴링하는 방식으로 인터페이스하고 있었습니다. 당연히 이 구조에서는 폴링 주기에 따라 어느 정도의 레이턴시가 발생합니다.

일반적인 팔레트나 비교적 큰 물건을 이송하는 물류 시스템에서는 큰 문제가 되지 않습니다. 이 센터 역시 팔레트를 취급하는 구간이 많았고, 대부분의 상황에서는 문제가 없었습니다.

문제는 박스 컨베이어에서 발생했습니다.

이 센터에는 분기 포인트(Branch Point)가 정말 많았습니다. WCS가 이송을 담당하는 ECS에게 최종 목적지만 전달하고 ECS가 스스로 경로를 판단하도록 만들 수도 있습니다.

하지만 그렇게 하면 실시간으로 변하는 물류 상황에 유연하게 대응하기 어렵습니다. 그래서 대부분의 경우 WCS는 분기 포인트 직전의 BCR에서 다시 한번 판단합니다.

이 박스는 이 분기에서 어디로 가야할까?

WCS 입장에서는 이 판단 자체가 오래 걸리지 않습니다. 대개 수 ms 안에 판단할 수 있습니다.

문제는 그 판단 결과를 ECS가 인식하기까지 걸리는 시간이었습니다. WCS가 판단하고 Interface DB에 데이터를 기록합니다. 그리고 ECS가 그 데이터를 폴링하여 인식합니다.

판단 자체는 수 ms면 끝나는데 그 결과가 실제 설비에 전달되기까지의 레이턴시 때문에 물류의 흐름이 끊겼습니다.

물론 특정 구간의 인터페이스만 개선하면 해결할 수 있는 문제였습니다. 하지만 그러려면 ECS 업체와 인터페이스 방식 자체를 다시 협의해야 했습니다.

Standalone 이 아니기에 개발팀의 판단으로 구조를 바꾸기도 어려웠습니다.

그렇다고 이 방식이 잘못된 것은 아닙니다.

이기종 시스템 간의 인터페이스에서는 메시지를 안전하게 전달하고 유실을 방지하는 것이 중요합니다. Outbox Pattern 과 유사한 안정성을 DB 인터페이스를 통해 자연스럽게 확보할 수 있다는 장점도 있었습니다.

동작하지 않는 시스템은 아닙니다. 다만 더 좋은 퍼포먼스를 낼 수 있었는데 인터페이스 방식 때문에 힘을 충분히 끌어내지 못했다는 것이 아쉬웠습니다.

설비 레이아웃의 한계

물류 자동화 시스템은 설비 레이아웃 위에서 운영을 소프트웨어로 녹여냅니다.

여기서 중요한건 레이아웃 입니다. 아쉽게도 소프트웨어는 레이아웃에 없는 길을 창조하지 못하고 설비가 할 수 없는 기능을 만들어낼 수 없습니다.

결국 물류자동화 분야에서 소프트웨어의 역할중 하나는 이 레이아웃이 낼 수 있는 최고의 퍼포먼스를 만들어주는 것입니다.

최선을 다했지만 결과가 아쉬웠습니다.

소프트웨어만으로 최적화할 수 있는 영역에는 물리적인 한계가 있다는 것을 머리로는 알고 있었습니다. 그럼에도 무엇인가 만족스럽지 않았습니다.

조금만 레이아웃을 꼼꼼히 봐볼걸…

물론 제 역할이 아닙니다. 월권이 될 수 도 있습니다. 그리고 레이아웃 검토단계에서 뛰어난 전문가들이 이걸 놓쳤을리도 없습니다.

그럼에도 불구하고 아쉽습니다.

고객의 요구사항을 담지 못한 레이아웃

고객의 중요한 요구사항 중 하나는 출하 박스의 순서였습니다.

출하 박스의 순서를 맞춰 팔레타이징해야 했고 이 순서는 상위 배송 시스템 및 배송 루트와도 연계되어 있었습니다. 문제는 이 순서를 정렬해줄 수 있는 Sorter가 없었다는 것입니다.

결국 출하 순서를 제어할 수 있는 곳은 사실상 DPS밖에 없었습니다.

DPS(Digital Picking System)는 단순한 시스템입니다. 예를 들어

바나나를 1열 3행에서 12개 피킹하세요.

라는 작업을 사람이 인지할 수 있도록 표시기에 불을 켜고 디스플레이에 정보를 보여줍니다. 여기에 컨베이어를 결합하면

바나나 1열 3행에서 12개를 피킹해서 눈앞의 박스에 담으세요.

라는 의미가 됩니다. 그리고 여기서부터 문제가 시작되었습니다.

DPS 레이아웃 (예시)

출고 배치가 시작되면 피킹박스들은 기차처럼 한 줄로 이동합니다.

시스템은 박스가 각 스테이션에 도착할 때마다 해당 스테이션에서 피킹해야 할 상품이 있는지 확인합니다. 피킹할 상품이 있다면 박스를 멈추고 DPS에 신호를 보냅니다.

문제는 이 박스가 피킹을 완료하기 전까지 뒤에 있는 모든 박스도 함께 멈춘다는 것입니다. 게다가 출하 순서를 이곳에서 맞춰야 했기 때문에 앞쪽 박스가 완료되기 전에는 이미 피킹을 끝낸 뒤쪽 박스도 빠져나갈 수 없었습니다.

고객의 요구사항과 맞지않는 레이아웃으로 인해 정상적인 속도가 안나오고 있었습니다.

여기에 특정 상품의 주문량이 많아 플로우랙의 재고가 부족해진다면 어떻게 될까요? 피킹을 멈추고 보충을 기다려야 합니다. 한 곳에서 발생한 문제가 뒤쪽의 모든 물류 흐름으로 전파됩니다.

모든 문제가 이곳에서 시작되었습니다.

사실 해결 방법은 비교적 단순 합니다.

컨베이어를 하나의 직선으로 연결하는 것이 아니라 피킹할 상품이 있는 경우 해당 박스를 분기시켜 스테이션 내부로 진입시키는 구조였다면 훨씬 유연하게 운영할 수 있었습니다.

문제는 이미 도면 설계 단계에서 이 부분이 충분히 고려되지 않았다는 것입니다. 뒤늦게 수정하려고 해도 물리적인 공간이 부족했습니다.

소프트웨어로 해결할 수 있는 문제가 아니었습니다.

부족한 플로우랙 보관능력

플로우랙에는 한 레일당 6개의 박스를 보관할 수 있었습니다. 그리고 뒤쪽에서는 크레인이 지속적으로 보충해주는 구조였습니다. 하지만 이 정도의 보관 능력으로는 고객이 기대하는 출고 케파를 감당하기 어려웠습니다.

물론 플로우랙의 재고를 어떻게 배치하고 언제 보충할 것인지에 대한 운영 전략도 중요합니다. 하지만 전략만으로 해결하기에는 물리적인 보관 능력 자체가 부족했습니다.

피킹 박스 몇 개만 지나가도 플로우랙의 재고가 바닥났고 출고량에 비해 빈약한 플로우랙의 보관 케파는 병목의 원인 중 하나가 되었습니다.

ASRS 크레인이 동작하고 → 팔레트가 디팔레타이징 존으로 이동하고 → 디팔레타이징이 진행되고 → 박스가 플로우랙으로 이동하고 → 플로우랙 크레인이 보충하고

이 모든 과정에 상당한 시간이 필요했습니다. 물리적인 거리도 너무 멀었습니다.

소프트웨어 입장에서는 출고 주문량을 미리 분석하여 필요한 물량을 예측하고 출고가 몰리기 전에 선제적으로 보충하는 방식이 최선이었습니다. 하지만 이것 역시 근본적인 물리적 한계를 완전히 해결할 수는 없었습니다.

병목이 생기는 2층

또 하나의 큰 병목은 2층이었습니다.

3층의 냉장·상온 출하 박스와 2층의 냉동 출하 박스가 2층에서 합류하고 이후 수직반송기를 통해 1층으로 내려갑니다. 1층에서는 로봇이 팔레타이징 작업을 수행합니다.

문제는 이 수직반송 구간과 팔레타이징 설비의 처리 속도가 충분하지 않았다는 것입니다. 출하량이 몰리면 2층에 박스가 쌓이기 시작했고 결국 명절 정체처럼 전체 흐름이 꽉 막히는 상황이 발생했습니다.

누구나 소프트웨어만의 문제는 아니라는 것을 알고 있습니다. 하지만 프로젝트는 우리만 잘 끝났다고 해서 끝나는 것이 아닙니다.

각자의 역역을 잘 수행하는 것은 당연하고 결국 가장 중요한 것은 센터 전체가 정상적으로 돌아가는 것입니다. 그리고 이 프로젝트는 점점 그 누구도 만족하기 어려운 결말을 향해 가고 있었습니다.

무사고 0 일차

이번 프로젝트는 정말 다사다난했습니다.

숙소 가스 누출, 두 번의 화재, 크레인 충돌, 자동차 접촉사고 등 돌이켜보면 다사다난한 프로젝트였습니다. 그중 인상적으로 남은 몇 가지를 소개해보려 합니다.

냉동창고에서 전자기기는 조심하세요!

어디서부터 잘못된 것인지는 모르겠지만 Scope에서 누락된 시스템이 하나 있었습니다. 합포를 도와줄 프로그램이었습니다.

피킹 박스에 담긴 상품을 실제 출하 박스로 옮기는 작업을 지원하는 프로그램이었습니다. 문제는 이 프로그램을 개발할 담당자가 없었다는 것입니다.

누구의 잘잘못을 따질 여유가 없었습니다. 다가오는 테스트 일정 때문에 일단 빠르게 만들어야 했습니다. 운영 자체가 복잡하지 않았기 때문에 WPF로 빠르게 개발했습니다.

그리고 이 프로그램은 냉동창고에서 사용할 예정이었습니다. 냉동창고는 영하 -25도 였습니다. 겁도 없이 노트북을 들고 들어가 테스트했습니다.

테스트는 문제없이 끝났습니다. 여기서 끝났다면 참 좋았겠지만 그렇지 않았습니다. 밖으로 나오자 노트북에서 블루스크린이 발생했습니다. 그리고 다시는 켜지지 않았습니다.

아득해졌습니다.

저는 손에 익은 도구를 사용하는 것을 좋아해서 회사의 허가를 받고 개인 노트북을 사용하고 있었습니다. 그렇게 대학 시절부터 함께했던 Dell XPS가 떠났습니다.

밀리는 일정 그로 인한 나비효과

물류센터 오픈 일정이 밀리는 경우는 흔하지 않습니다. 센터가 오픈하는 날짜에 맞춰 배차, 작업자, 상위 시스템 등 센터 외부의 수많은 요소가 함께 준비되기 때문입니다.

그런데 이 프로젝트는 오픈 일정이 밀렸습니다. 그리고 하필이면 팀원 중 한 분의 결혼식을 앞두고 있었습니다.

설마 했던 일이 벌어졌습니다. 결혼식 당일 센터가 오픈하게 되었습니다.

대부분의 신규 시스템은 오픈 직후 많은 문제가 발생합니다. 익숙하지 않은 시스템으로 인해 휴먼에러도 빈번하고 예상하지 못했던 버그도 터집니다.

그래서 보통 오픈이후 안정화 기간을 둡니다.

대체 인력이 없었습니다. 결국 남은 사람들이 어떻게든 버텨야 했습니다.

프로젝트의 일정 하나가 밀리고 → 그 작은 변화가 다른 사람의 일정에 영향을 주고 → 결국 또 다른 사람들에게 부담이 전가되었습니다. 프로젝트에서 일정이 단순히 일정표의 날짜 하나를 움직이는 일이 아니라는 것을 다시 한번 느꼈습니다.

마치며

가끔 함께했던 동료들을 만나면 빠지지 않고 나오는 이야기 중 하나가 이 프로젝트입니다. 그만큼 힘들었고 오래 기억에 남는 프로젝트였습니다. 센터가 오픈하면 설비가 로직대로 움직이고 작업자분들이 각자의 자리에서 일사불란하게 역할을 수행하는 질서를 보며 나름의 성취감을 느꼈습니다.

아쉽게도 이번은 기간도 길고 규모도 컸음에도 아쉬움이 컸습니다. 프로젝트가 끝나고 슬럼프가 왔었습니다.

돌이켜보면 아프고 힘들지만 다르게 보면 아무나 경험하기 힘든 소중한 경험입니다. 이제는 앞으로 더 나은 결정과 판단을 위한 경험치로 삼으려 합니다.