본문으로 건너뛰기
Back to Projects
팀 프로젝트 / 익명 물류 운영사

NP-OIS

물류 운영자가 주문 Excel을 같은 기준으로 변환하고, 오류를 검수해 업무용 파일로 내려받는 웹 도구입니다.

2026.05 - 2026.07 · Frontend 직접 구현 / 서버 변환 기준·실패 기록 처리 기여

ReactTypeScriptViteTanStack Query
Snapshot

프로젝트 요약

사용자
주문 파일을 처리하고 검수하는 물류 운영자
해결 과제
판매처마다 형식이 다른 주문 Excel을 반복해서 가공해야 했고, 변환 오류가 생기면 원본과 결과를 대조해 수정하기 어려웠습니다. 파일 등록부터 표준 변환·오류 검수·산출물 보관까지 한 흐름으로 처리할 도구가 필요했습니다.
내 기여
기존 MVP를 인수해 주문 파일 등록, 변환 진행 상태, 결과 검수·보정, 다운로드·보관을 하나의 Frontend 흐름으로 연결했습니다. 서버에서는 변환 기준 고정, 실패 이력, 파일 저장·다운로드 처리에 기여했습니다.
결과
운영자가 주문 Excel을 등록하면 시스템이 표준 주문으로 변환하고, 오류를 원본 행과 비교해 보정한 뒤 업무용 Excel·ZIP 파일로 내려받을 수 있는 처리 흐름을 구현했습니다.

사내 코드는 비공개입니다.

User flow

서비스 이용 흐름

  1. 01

    주문 Excel 업로드

  2. 02

    양식 확인·변환 요청

  3. 03

    오류 검수·보정

  4. 04

    산출물 생성·보관

변환 시작

해당 작업에 사용할 상품·주문 기준 버전을 기록합니다.

변환 실패

작업의 실패 상태와 원인을 별도 기록으로 남깁니다.

운영자는 변환 상태를 확인하고, 완료된 작업의 오류를 검수한 뒤 산출물을 받습니다.
Contribution

나의 역할

Frontend 직접 구현

  • 기존 React SPA를 공통 컴포넌트·업무 페이지·타입으로 나누고, 파일 등록부터 검수·산출물까지 화면을 연결했습니다.
  • 활성 queue·run에서만 진행 상태를 조회하고, 종료 시 polling을 멈춘 뒤 관련 Query cache를 갱신했습니다. 운영자는 완료 상태를 확인하고 해당 run의 검수로 이어갈 수 있습니다.
  • 검수 화면에서 원본 행·표준 주문·제외 행을 비교하고, 누락 매핑 보정·재검증·검수 재개를 연결했습니다.

서버 직접 기여

  • 변환 run의 기준정보 snapshot 고정, 여러 원본 파일의 배치 등록과 storage metadata 관계, 동일 배치의 중복 변환 방지 guard·테스트, 파일 저장·streaming download를 다뤘습니다.
Case studies

대표 기술 문제

01

한 주문 파일에 서로 다른 변환 기준이 적용될 수 있음

문제

주문 변환은 상품, 판매처, 수량 단위 같은 기준정보를 계속 참조합니다. 각 행을 처리할 때마다 최신값(latest)을 조회하면, 처리 중 기준이 수정된 순간부터 파일 앞·뒷부분에 서로 다른 기준이 적용될 수 있었습니다. 같은 원본을 재실행해도 결과가 달라져 오류 원인을 추적하기 어려운 구조였습니다.

해결

변환 작업(run)을 시작할 때 source별 snapshot id·version·hash를 저장하고, 이후 모든 조회를 고정된 snapshot ID로 제한했습니다. snapshot은 '이 작업이 시작할 때 사용한 기준 버전'을 의미합니다. 처리 중 최신 기준이 바뀌어도 하나의 run은 동일한 기준을 유지해, 결과와 사용 기준을 함께 추적할 수 있습니다.

02

파일 변환이 실패해도 원인 기록을 남겨야 함

문제

원본 Excel을 Storage에서 읽고 Apache POI로 parsing하는 작업은 시간이 오래 걸립니다. 이 과정을 run 생성·상태 변경과 하나의 DB transaction으로 묶으면 connection을 오래 점유하게 됩니다. 예외가 발생해 transaction 전체가 rollback되면 '실패함'이라는 run 기록까지 사라져, 운영자가 원인을 확인하지 못할 수 있었습니다.

해결

짧은 start transaction에서 run과 snapshot을 먼저 저장한 뒤, 긴 Storage I/O·parsing·mapping은 transaction 밖에서 수행했습니다. 처리가 끝나면 성공 데이터를, 오류가 나면 실패 상태와 원인을 각각 별도 transaction으로 저장했습니다. 파일 처리가 실패해도 추적할 run 이력을 남기면서 DB connection을 오래 점유하지 않도록 구성했습니다.

Case studies

성능·리소스 최적화

01

검수 목록이 데이터가 쌓일수록 느려짐

문제

운영자가 필요한 것은 '어느 작업에 누락이 몇 개 있는지'와 같은 요약 정보입니다. 하지만 목록을 열 때마다 원본 데이터 전체를 불러와 개수를 계산하면 데이터가 쌓일수록 화면 응답이 느려집니다.

해결

목록에 필요한 상태·누락 개수만 summary projection으로 모아 batch 조회했습니다. 원본 행 같은 상세 데이터는 해당 run을 열었을 때만 불러오고, 누락 항목은 DB aggregate pagination으로 페이지 단위로 나눴습니다.

02

파일을 DB에 쌓아 저장과 다운로드가 무거워짐

문제

Excel 원본과 결과물은 크기가 크고 계속 쌓입니다. 파일 자체를 DB에 저장하고 다운로드할 때 한 번에 메모리로 읽으면, 검색을 담당해야 할 DB와 서버 메모리 모두 부담이 커집니다.

해결

Excel·ZIP 파일은 local/Object Storage에 저장하고, DB에는 storage key·size·SHA-256·업무 상태 같은 metadata만 남겼습니다. 개별 파일과 ZIP은 전체를 메모리에 올리지 않고 stream으로 응답했습니다. DB metadata 저장이 실패하면 방금 생성한 object를 보상 삭제해, 업무 기록 없이 파일만 남는 상태를 방지했습니다.

03

큰 Excel 파일 미리보기가 서버를 오래 점유함

문제

업로드 직후 파일 전체를 미리보기로 보여 주려면 서버가 모든 행과 열을 읽어야 합니다. 잘못 만든 파일에 수만 개의 행이나 지나치게 긴 문자열이 들어 있으면 서버 메모리와 화면 응답을 동시에 점유할 수 있었습니다.

해결

파일 30MB, scan 10,000행, preview 8행·80열, cell 220자로 미리보기 읽기 범위를 제한했습니다. Backend와 UI가 같은 제한을 사용하고, 한도를 넘는 파일은 무리하게 열지 않고 명시적인 validation error를 반환했습니다.