LabHub
배우기 러닝패스 코스

システム間連携 (EAI)

固定長ファイルインターフェースのパースと照合

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

고정길이 전문 파일을 레이아웃대로 파싱하고, 트레일러로 무결성을 검증하고, 인코딩 변환·완료 플래그·보관·대사까지 파일 인터페이스 한 사이클을 완성합니다.

왜 중요한가

파일 연동은 낡아 보이지만 대량 처리와 대사 가능성에서 여전히 최선입니다. 문제는 실패 방식이 조용하다는 것입니다. 전송 중 잘린 파일을 그대로 처리하면 오류 없이 절반만 반영되고, 그 사실은 월말 마감에 '숫자가 안 맞는다'로 발견됩니다. 완료 플래그 규약이 한쪽에만 있으면 배치가 매일 아무것도 처리하지 않으면서 아무 오류도 내지 않습니다. 조용히 아무 일도 안 하는 것이 가장 늦게 발견됩니다. 트레일러 검증과 대사는 그 조용한 실패를 시끄럽게 만드는 장치입니다.

단계

  1. /opt/lab/fixtures/eai/file/layout.md 를 읽고 /root/f/layout.csv 를 만듭니다. 첫 줄은 seq,field,start,length,type. start1부터 시작하는 위치이고, seq 순서대로 정렬합니다.
  2. /root/f/parse.sh 를 만듭니다. 인자 하나(데이터 파일)를 받아 D 로 시작하는 데이터 레코드만 아래 6개 필드를 파이프(|)로 구분해 출력합니다.
    SALE_DT|CUST_ID|CUST_NM|PROD_CD|QTY|AMT
    
    문자 필드의 앞뒤 공백은 제거하고, 숫자 필드의 앞자리 0 도 제거합니다. (REC_TYPE 은 출력하지 않습니다.) /opt/lab/fixtures/eai/file/SALES_20260801.dat 으로 실행한 결과를 /root/f/parsed.txt 에 저장하세요.
  3. /root/f/verify.sh 를 만듭니다. 인자 하나(데이터 파일)를 받아 트레일러의 건수와 금액 합계가 데이터 레코드와 일치하면 종료코드 0, 불일치면 첫 줄에 사유를 출력하고 0 이 아닌 종료코드로 끝냅니다.
    • SALES_20260801.dat → 통과해야 합니다
    • SALES_20260802.dat → 실패해야 합니다
  4. /opt/lab/fixtures/eai/file/SALES_EUCKR.dat 을 UTF-8 로 변환해 /root/f/SALES_utf8.dat 에 저장합니다. 변환 후 한글이 정상으로 읽혀야 합니다.
  5. /root/f/pick.sh 를 만듭니다. 인자 하나(디렉터리)를 받아 .ok 플래그 파일이 함께 있는 .dat 파일명만 한 줄에 하나씩 출력합니다. .ok 파일 자체는 출력하지 않습니다.
  6. /root/f/csvcheck.py 를 만듭니다. 인자 하나(CSV 파일)를 받아 rows=<데이터 행수> fields=<헤더 필드수> bad=<필드수가 다른 행수> 한 줄을 출력합니다. 따옴표 안의 콤마·줄바꿈을 올바르게 처리해야 합니다. /opt/lab/fixtures/eai/file/orders_quoted.csv 로 실행한 결과를 /root/f/csvcheck.txt 에 저장하세요.
  7. SALES_20260801.dat/root/f/archive/20260801/ 아래에 gzip 압축해 보관합니다. 원본 파일명에 .gz 가 붙은 형태여야 합니다.
  8. /root/f/recon.csv 를 만듭니다. 첫 줄은 item,source,target,diff,result. /opt/lab/fixtures/eai/file/SALES_20260801.dat(source)과 /opt/lab/fixtures/eai/file/SALES_20260801.csv(target)를 비교해 count 행과 amount 행 두 개를 채웁니다. result 는 일치하면 OK, 다르면 NG 입니다.

참고

레이아웃 정의 정리

/opt/lab/fixtures/eai/file/layout.md 를 읽고 /root/f/layout.csv 를 만듭니다. 첫 줄은 seq,field,start,length,type. start1부터 시작하는 위치이고, seq 순서대로 정렬합니다.

시작 위치는 1부터 셉니다. 앞 필드들의 길이 합에 1을 더하면 다음 필드의 시작 위치입니다. 마지막 필드의 끝이 전체 레코드 길이와 맞는지 검산하세요.

고정길이 파서

/root/f/parse.sh 를 만듭니다. 인자 하나(데이터 파일)를 받아 D 로 시작하는 데이터 레코드만 아래 6개 필드를 파이프(|)로 구분해 출력합니다.

SALE_DT|CUST_ID|CUST_NM|PROD_CD|QTY|AMT

문자 필드의 앞뒤 공백은 제거하고, 숫자 필드의 앞자리 0 도 제거합니다. (REC_TYPE 은 출력하지 않습니다.) /opt/lab/fixtures/eai/file/SALES_20260801.dat 으로 실행한 결과를 /root/f/parsed.txt 에 저장하세요.

cut 은 바이트 기준 -b 와 문자 기준 -c 가 다릅니다. 한글이 섞이면 이 차이가 결과를 바꿉니다. 숫자 필드의 앞자리 0 도 어떻게 처리할지 정해야 합니다.

트레일러 검증

/root/f/verify.sh 를 만듭니다. 인자 하나(데이터 파일)를 받아 트레일러의 건수와 금액 합계가 데이터 레코드와 일치하면 종료코드 0, 불일치면 첫 줄에 사유를 출력하고 0 이 아닌 종료코드로 끝냅니다.

검증은 처리 전에 해야 합니다. 처리 중에 하면 이미 절반이 반영된 상태가 됩니다. 건수와 합계 둘 다 봐야 합니다.

인코딩 변환

/opt/lab/fixtures/eai/file/SALES_EUCKR.dat 을 UTF-8 로 변환해 /root/f/SALES_utf8.dat 에 저장합니다. 변환 후 한글이 정상으로 읽혀야 합니다.

받은 파일이 깨져 보이면 먼저 인코딩을 의심합니다. 국내 대외 연동에서는 한글이 2바이트로 떨어지는 인코딩이 아직 쓰입니다.

완료 플래그 선별

/root/f/pick.sh 를 만듭니다. 인자 하나(디렉터리)를 받아 .ok 플래그 파일이 함께 있는 .dat 파일명만 한 줄에 하나씩 출력합니다. .ok 파일 자체는 출력하지 않습니다.

플래그가 없는 파일은 아직 전송 중일 수 있습니다. 인자로 디렉터리를 받아 처리 대상만 출력하도록 만드세요.

CSV 인터페이스 검증

/root/f/csvcheck.py 를 만듭니다. 인자 하나(CSV 파일)를 받아 rows=<데이터 행수> fields=<헤더 필드수> bad=<필드수가 다른 행수> 한 줄을 출력합니다. 따옴표 안의 콤마·줄바꿈을 올바르게 처리해야 합니다. /opt/lab/fixtures/eai/file/orders_quoted.csv 로 실행한 결과를 /root/f/csvcheck.txt 에 저장하세요.

CSV 는 따옴표 안에 콤마와 줄바꿈이 들어갈 수 있습니다. 단순 분할로는 필드 수가 틀립니다. 표준 파서를 쓰세요.

처리 후 보관

SALES_20260801.dat/root/f/archive/20260801/ 아래에 gzip 압축해 보관합니다. 원본 파일명에 .gz 가 붙은 형태여야 합니다.

날짜별 디렉터리로 나눠야 한 디렉터리에 파일이 수십만 개 쌓이지 않습니다. 텍스트는 압축 효과가 큽니다.

대사표 작성

/root/f/recon.csv 를 만듭니다. 첫 줄은 item,source,target,diff,result. /opt/lab/fixtures/eai/file/SALES_20260801.dat(source)과 /opt/lab/fixtures/eai/file/SALES_20260801.csv(target)를 비교해 count 행과 amount 행 두 개를 채웁니다. result 는 일치하면 OK, 다르면 NG 입니다.

건수만 맞으면 안심하기 쉽지만, 한 건이 빠지고 다른 한 건이 두 번 들어가면 건수는 맞습니다. 합계도 함께 보세요.