외부 API·시스템 연계 · API Integration

바코드 발행 주체가 바뀌었을 때: SAP 연동 주문등록의 정합성을 지킨 방법

SAP/EVS 전환으로 바코드 관리 경계가 달라진 기간에 요청 단위 처리와 서버 재검증으로 확인된 중복·유형 불일치 경로를 막고, 별도로 발견한 결과 수신 정보 정합성 문제를 수정한 과정을 정리합니다.

JavaSpringSAP데이터 정합성주문 처리

문제의 출발점

외부 시스템 도입은 API 호출을 하나 추가하는 것으로 끝나지 않는다. 어느 시스템이 데이터를 생성하고 관리하는지, 처리 완료 여부는 어디에서 판단하는지, 실패했을 때 어느 요청의 처리를 중단해야 하는지까지 함께 달라진다.

2024년 초, EZ-Seq·Eco-Seq 바코드 주문등록 프로세스를 SAP/EVS 연계 구조에 맞게 개선했다. 기존 주문 시스템은 바코드 요청·수정 정보를 SAP로 전달하는 창구로 남았고, 요청 정보 관리와 처리 기준은 외부 연계 영역으로 이동했다.

핵심 과제는 단순한 API 연동이 아니었다. 하나의 바코드가 올바른 서비스·요청·고객·결과 수신 정보와 연결되도록 주문등록 전 과정을 다시 점검해야 했다.

데이터의 기준이 바뀌면 모델도 함께 바뀌어야 한다

먼저 주문 및 이력 데이터에서 EZ-Seq와 Eco-Seq 바코드 유형을 구분할 수 있도록 구조를 보완했다. 기존 데이터에도 바코드 유형과 튜브 유형을 이관해 신규 주문과 과거 데이터가 같은 기준으로 처리되도록 했다.

새로운 구분값만 추가하고 기존 데이터를 그대로 두면 이후 검증 로직에서 과거 주문만 예외적으로 동작할 수 있다. 따라서 구조 변경과 데이터 마이그레이션을 하나의 작업 범위로 보고 처리했다.

전달받은 객체를 변경한 조회 메서드의 부수효과

전환 기간 초반에는 고객 결과 수신 이메일이 다른 고객 기준으로 주문 데이터에 등록될 수 있는 경로를 별도로 발견했다. 이 문제는 뒤에 진행한 요청번호별 처리나 중복 주문 방지 로직 때문에 발생한 것이 아니다.

원인은 결과 수신 이메일을 조회하는 메서드가 전달받은 파라미터 객체의 고객 식별 상태를 내부에서 바꾸는 구조였다. 여러 고객의 바코드 주문을 연속으로 처리하면 첫 조회에서 설정된 고객 식별값이 객체에 남아 이후 처리에서도 재사용될 수 있었다.

구조를 단순화하면 다음과 같다.

for (BarcodeRequest request : requests) {
    sharedContext.apply(request);

    RecipientInfo recipients = findRecipients(sharedContext);
    registerOrder(request, recipients);
}

문제는 findRecipients가 조회만 수행할 것이라는 호출자의 예상과 달리 sharedContext의 상태를 변경할 수 있었다는 점이다. 호출자가 소유한 객체를 메서드 내부에서 바꾸면 이후 로직은 어떤 값이 현재 요청의 기준인지 추적하기 어려워진다.

실제 수정에서는 각 조회 호출 직전에 고객 식별 상태를 초기화해 현재 주문을 기준으로 다시 결정하도록 했다. 서로 다른 고객의 바코드 주문을 연속으로 처리하는 회귀 시나리오도 함께 확인했다.

장기적으로는 조회 조건과 조회 결과를 분리하는 형태가 더 안전하다.

RecipientQuery query =
    RecipientQuery.of(request.getCustomerKey());

RecipientInfo recipients = findRecipients(query);

확인된 영향은 주문 데이터에 결과 수신 정보가 잘못 연결되는 경로였다. 이를 실제 결과 오발송이나 개인정보 사고로 확대하지 않고, 확인된 데이터 정합성 범위 안에서 수정 내용을 정리했다.

이 부수효과의 재현 조건과 단기 수정·장기 설계의 차이는 조회 메서드가 인자를 바꾼다면: 반복 처리에서 첫 번째 고객 값이 재사용된 이유에서 더 자세히 다뤘다.

같은 업무 규칙은 모든 입력 경로에서 검증해야 한다

별도로 EZ-Seq 서비스에 Eco-Seq 바코드를 사용하거나 그 반대의 조합으로 주문이 등록될 수 있는 경로도 확인했다. 화면에서 서비스와 바코드 유형을 각각 선택할 수 있었지만 두 값의 관계를 강제하는 검증이 충분하지 않았다.

선택한 서비스와 바코드 유형이 다르면 안내 메시지와 함께 등록을 차단하도록 개선했다. 바코드 스캔 화면뿐 아니라 Excel Upload 경로에도 같은 검증을 적용했다.

업무 규칙은 특정 화면의 UI 검증이 아니라 시스템 불변조건으로 관리해야 한다. 입력 경로가 여러 개라면 모든 경로에서 같은 규칙이 적용되는지 확인해야 한다.

화면의 지연 처리는 중복 방지 장치가 아니다

이후 기존 화면의 setTimeout 기반 순서 제어를 제거하고 요청번호별 독립 처리 구조로 주문등록 로직을 재구성했다. 시간 지연은 호출 사이에 간격을 둘 뿐, 반복 클릭이나 여러 브라우저 창에서 같은 바코드가 처리되는 상황의 정합성을 보장하지 못한다.

  • 등록 직전에 해당 바코드가 이미 사용됐는지 다시 확인
  • 각 요청번호를 하나의 처리 단위로 구분
  • 처리 결과에 맞춰 SAP 연계 영역의 바코드 사용 상태 반영
  • 실패한 요청은 요청번호별로 구체적인 실패 사유 표시
  • 화면의 setTimeout 기반 순서 제어 제거

화면에서 버튼을 비활성화하는 것만으로 정합성을 보장하지 않았다. 최종 판단을 서버에서 다시 수행해야 반복 클릭이나 복수 창처럼 클라이언트 상태를 신뢰할 수 없는 상황에도 대응할 수 있다.

이 개선은 앞서 수정한 결과 수신 이메일 오등록 경로와 별개의 작업이며, 이후 같은 객체 부수효과가 재발했다는 의미도 아니다.

결과 수신자 정책도 별도 요구사항으로 분리했다

그 뒤에는 바코드 주문의 결과 수신자 범위를 보완했다. 고객의 대표 이메일뿐 아니라 별도로 등록된 결과 수신 이메일도 포함하고, 중복 주소는 제거하도록 변경했다.

이 작업은 앞서 발견한 이메일 오등록 문제의 재발 수정이 아니라 결과 수신자 범위를 확장한 별도 요구사항이었다. 비슷한 데이터 항목을 다루더라도 버그 수정과 정책 변경을 구분해야 변경 이력과 검증 범위를 정확하게 설명할 수 있다.

검증은 정상 입력보다 경계 조건을 중심으로 했다

각 변경의 목적과 선후관계를 섞지 않은 채 다음 경계 조건을 중심으로 회귀 검증했다.

  • 서로 다른 고객의 바코드 주문을 연속으로 등록하는 경우
  • 주문등록 버튼을 반복해서 클릭하는 경우
  • 여러 브라우저 창에서 동일한 바코드를 사용하는 경우
  • 이미 사용된 바코드가 다시 전달되는 경우
  • 서비스와 바코드 유형이 일치하지 않는 경우
  • 스캔과 Excel Upload로 각각 주문을 등록하는 경우
  • 대표 이메일과 추가 결과 수신 이메일이 함께 존재하는 경우

이를 통해 확인된 반복 클릭·동일 바코드 재사용 경로의 중복 주문과 서비스·바코드 유형 불일치 등록을 차단했다. 고객 결과 수신 정보가 잘못 연결되던 경로도 별도로 수정하고, 결과 수신자 처리 범위를 보완했다.

외부 시스템 전환에서 배운 것

이번 작업에서 얻은 교훈은 네 가지다.

  1. 클라이언트의 시간 지연은 동시성이나 중복 방지 수단이 아니다.
  2. 외부 시스템 상태를 사용한다면 주문등록 직전 서버에서 다시 검증해야 한다.
  3. 전달받은 객체를 메서드 내부에서 변경하면 요청 사이의 상태가 섞일 수 있다.
  4. 업무 불변조건은 스캔·파일 업로드 등 모든 입력 경로에 동일하게 적용해야 한다.

외부 시스템 연계의 난도는 API 호출 자체보다 시스템 경계가 바뀐 뒤에도 기존 업무 규칙과 데이터 정합성을 유지하는 데서 생긴다. 이 작업은 SAP나 바코드 전체 시스템을 설계·이관한 경험이 아니라, SAP/EVS 연계 전환 과정에서 주문등록 로직의 경계 조건을 분석하고 안정화한 경험이었다.

공개 안내: 이 글은 실제 업무 경험을 바탕으로 내부 식별자, 고객 정보, 저장 구조와 비공개 코드를 제거하거나 공개용 pseudocode로 일반화했습니다.

TECHNICAL SERIES

SAP 연동 주문등록 정합성

바코드 발행 경계가 바뀐 주문등록 흐름과 반복 처리에서 발견한 숨은 상태 변경을 함께 살펴봅니다.

시리즈 전체 보기

현재 1/2

  1. 1바코드 발행 주체가 바뀌었을 때: SAP 연동 주문등록의 정합성을 지킨 방법
  2. 2조회 메서드가 인자를 바꾼다면: 반복 처리에서 첫 번째 고객 값이 재사용된 이유