홈 › 미니 프로젝트 › 04 / 4

4단계: 일마감 정산 배치 (배치 기술)

섹션 6진행 0 / 4

4단계: 일마감 정산 배치

하루치 주문 10만 건을 CSV로 받아 검증·결제·정산 집계를 거쳐 정산 파일을 만드는 배치를 순수 JDK로 구현한다. 이 단계에서 새로 쓰는 기술: 청크 읽기(BufferedReader), 검증 실패 스킵, 결제 게이트웨이 시뮬레이션과 지수 백오프 재시도, 청크 단위 트랜잭션(커밋/롤백), 체크포인트 저장과 재시작, Properties 직렬화, 임시 파일 후 원자적 이동(ATOMIC_MOVE), 최종 리포트, 결정적(deterministic) 장애 주입.

1. 이번 단계의 목표

1.1 새 요구사항

# 요구사항 세부
R18 일마감 정산 영업일의 주문 CSV(10만 건)를 읽어 결제를 확정하고 카테고리별·결제수단별 매출/수수료/정산액을 집계한다
R19 메모리 상한 파일 크기와 무관하게 메모리 사용이 청크 크기에 비례해야 한다
R20 검증 스킵 깨진 행(컬럼 누락, 숫자 아님, 수량 ≤ 0, 모르는 결제수단)은 사유별로 세고 건너뛴다. 배치가 멈추면 안 된다
R21 결제 재시도 게이트웨이 일시 장애는 최대 3회 지수 백오프 재시도. 영구 거절은 즉시 스킵
R22 트랜잭션 청크 단위로 커밋. 청크 도중 실패하면 그 청크의 집계는 전부 폐기(롤백)
R23 재시작 프로세스가 죽어도 마지막 커밋 지점부터 이어서 실행할 수 있다. 재시작 결과는 처음부터 한 번에 돌린 결과와 같아야 한다
R24 원자적 출력 정산 파일은 완성된 상태로만 존재한다. 반쯤 쓰인 파일이 보이면 안 된다
R25 리포트 읽음/처리/스킵(사유별)/재시도 건수, 집계표, 소요 시간
R26 재현성 같은 입력으로 돌리면 같은 결과. 장애 주입도 재현 가능해야 한다

1.2 3단계의 한계가 왜 문제였는가

3단계 마지막 표의 여섯 항목을 배치 관점에서 다시 본다.

  • 전부 메모리: 3단계는 주문을 Repository에 전부 담았다. 10만 건은 담기지만, R19는 "파일 크기와 무관"을 요구한다. 파일을 한 줄씩 읽어 1,000줄 단위로 처리하고 버리면 메모리는 1,000줄 분량으로 고정된다.
  • 실패하면 처음부터: 10만 건 중 4만 번째에서 프로세스가 죽었다고 하자. 3단계 방식은 재실행 시 처음부터다. 앞 4만 건의 결제 게이트웨이 호출이 반복되고(이중 결제 위험), 시간도 두 배다. R23은 "이어서"를 요구한다.
  • 반쯤 반영된 상태: 죽는 순간 집계 맵에는 4만 번째 청크의 절반이 들어가 있다. 이 상태를 저장했다가 이어 가면 그 청크가 두 번 반영된다. R22의 "전부 아니면 전무"가 필요하다.
  • 한 건이 전체를 멈춤: 3단계 OrderLine 생성자는 수량 0에 ValidationException을 던진다. 배치에서 그 예외가 전파되면 9만 9천 건이 볼모가 된다. R20은 "세고 건너뛰기"다.
  • 게이트웨이 장애: 3단계 PaymentGateway는 항상 응답했다. 실제 네트워크는 5%쯤 타임아웃이 난다. 재시도 없이 스킵하면 정상 주문 5%가 정산에서 빠진다. R21.
  • 출력 원자성: 3단계는 출력이 콘솔이었다. 파일을 쓰다 죽으면 회계 시스템이 반쪽 파일을 읽는다. R24.

그리고 R26 — 이 레슨 자체의 요구다. 장애 시뮬레이션에 Random을 쓰면 실행마다 결과가 달라 학습자가 출력을 대조할 수 없다. 실패 여부를 주문 ID의 해시로 정하면 "어떤 주문이 몇 번째 시도에서 실패하는가"가 고정된다.