은행 현장의 언어 · 수신 파일의 형식 계약 · 실습
받은 파일을 적재하기 전에 돌려보내기
목표
상대 기관이 보내온 고정폭·CSV 수신 파일을 적재하기 전에 검사하고, 어긋나면 파일 전체를 거절하는 문지기 filegate.py 를 만든다. 판정은 기계가 읽는 보고서와 종료 코드, 그리고 상대에게 돌려줄 거절 파일로 남긴다.
왜 중요한가
적재한 뒤에 틀린 줄을 찾는 일은 문 앞에서 거절하는 일보다 언제나 비싸다. 이미 들어간 줄은 다른 배치가 물고 갔고, 되돌리려면 정정 전표와 사과 전화가 따라온다. 998건이 멀쩡해도 2건이 규격에서 어긋나면 그 파일은 한 줄도 넣지 않는다. 절반만 넣으면 상대의 트레일러와 우리 원장이 영영 맞지 않는다.
고정폭 파일의 폭은 글자 수가 아니라 바이트다. 한글 한 글자는 CP949 에서 2바이트, UTF-8 에서 3바이트라서, 인코딩이 바뀌면 줄 길이 자체가 달라진다. CSV 는 인용 안의 쉼표와 줄바꿈을 구분자로 세지 않아야 한다.
채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 자기가 만든 수신 파일을 차려 놓고 여러분의 스크립트를 실행해 판정과 오류 코드를 대조한다. 기관 코드와 건수, 금액은 실행마다 바뀐다.
단계
1. /root/bankfile/gen_inbound.py 를 만들어 실행해 /root/bankfile/inbound/ 에 상대 기관 네 곳의 하루치 파일 5개를 만든다.
2. /root/bankfile/filegate.py 가 CSV 수신 파일의 뼈대와 트레일러 건수·합계를 대조하고 보고서와 종료 코드를 내게 한다.
3. filegate.py 에 고정폭(.txt) 처리를 넣는다. 한 줄이 정확히 80바이트인지 글자 수가 아니라 바이트로 잰다.
4. filegate.py 가 규격과 다른 인코딩으로 온 파일을 ENC 로 거절하게 한다. 파일마다 읽은 인코딩을 보고서에 적는다.
5. filegate.py 의 CSV 파싱을 RFC 4180 대로 고친다. 인용된 쉼표와 줄바꿈은 필드 구분자가 아니다.
6. filegate.py 에 필드 단위 검증을 넣고, 거절한 파일마다 거절 파일을 남긴다. 오류가 하나라도 있으면 그 파일은 한 줄도 적재하지 않는다.
7. filegate.py 가 같은 기관·같은 일련번호의 재전송을 DUP 로 거절하게 한다. 해시가 같으면 resend, 다르면 conflict 다.
8. 자기 수신함을 처리해 /root/bankfile/gate_report.json 과 /root/bankfile/rejected/, /root/bankfile/receipt.md 를 남긴다.
참고
- 수신 규격: 이름은
IN-<YYYYMMDD>-<기관코드 6자리>-<꼬리>.txt또는.csv입니다..txt는 CP949 고정폭,.csv는 UTF-8 CSV 이고 줄 끝은 CRLF 입니다. - 고정폭은 한 줄이 정확히 80바이트입니다. H =
H(1) + 기관코드(6) + 파일일자(8) + 일련번호(3) + 공백(62). D =D(1) + 거래번호(12) + 수취인명(20) + 계좌(14) + 금액(13, 왼쪽 0 채움) + 공백(20). T =T(1) + 건수(6) + 합계(15) + 공백(58). 폭은 전부 바이트입니다. - CSV 레코드는
H,기관코드,파일일자,일련번호/D,거래번호,수취인명,계좌,금액/T,건수,합계입니다. - 필드 규격: 거래번호는
TR+ 숫자 10자리이고 파일 안에서 유일, 계좌는110-0000-00000, 금액은 1 이상 10000000000 미만의 정수, 수취인명은 비어 있지 않습니다. - 실행 계약:
python3 /root/bankfile/filegate.py --in <수신디렉터리> --report <보고서.json> --reject <거절디렉터리> - 보고서:
{"summary": "accept|reject", "accepted": [이름], "rejected": [이름], "files": [{"name", "verdict", "encoding", "records", "total", "sha256", "errors": [{"code", "line", "detail"}]}]}.records는 D 레코드 수,total은 금액 합입니다. - 오류 코드:
ENCWIDTHLAYOUTTRAILER_COUNTTRAILER_TOTALFIELDDUP. 파일 단위 오류의line은 0 입니다. 거래번호가 겹치면 뒤에 나온 줄을 가리킵니다. - 종료 코드: 전부 수용 0, 하나라도 거절 2, 수신 디렉터리를 못 읽으면 보고서 없이 3.
- 거절 파일: 거절된 파일마다
<거절디렉터리>/<파일이름>.reject.csv, 머리글은line,code,detail. - 직접 시험:
python3 /root/bankfile/filegate.py --in /root/bankfile/inbound --report /tmp/r.json --reject /tmp/rej; echo $? - 흔한 실수: 한글 이름을 글자 수로 채우기,
split(",")로 CSV 자르기, 오류 난 줄만 빼고 나머지를 적재하기, 문지기가 파일을 고쳐 주기.
단계 8개
- 하루치 수신함 만들기
- 명세의 건수와 합계부터 맞춰 보기
- 고정폭의 폭은 글자가 아니라 바이트다
- 규격과 다른 인코딩으로 온 파일 막기
- 인용 안의 쉼표는 구분자가 아니다
- 필드 검증과 거절 파일, 그리고 부분 적재 금지
- 다시 온 파일과 충돌한 파일 가르기
- 자기 수신함을 처리하고 수신 보고서 내기