LabHub
시작하기
배우기 러닝패스 코스

EAI 중간 계층 만들기

거래코드로 길을 정하는 라우터

LabHub 에서 이어서 보기

목표

현업의 인터페이스 목록을 라우팅 표(데이터)로 정제하고, 전문 헤더만 보고 목적지를 정하는 라우터를 규칙 우선순위(ORG > EXACT > 긴 PREFIX > NONE)대로 만든다.

왜 중요한가

허브의 라우팅이 틀리면 오류가 나는 대신 전문이 조용히 다른 시스템으로 간다. 그래서 규칙을 코드가 아니라 표로 두고, 겹칠 때 누가 이기는지를 행 순서가 아니라 코드로 명시하고, 어떤 규칙이 맞았는지를 감사 로그로 남긴다. 라우팅 불가를 삼키지 않고 E101 응답으로 돌려주는 것도 허브의 책임이다 — 삼키면 보낸 채널이 타임아웃까지 기다린다.

단계

  1. /opt/lab/fixtures/eaimw/route/interfaces.csv/opt/lab/fixtures/eaimw/route/ROUTING.md 2절을 읽고 /root/eaimw/route/routes.csv 를 만든다. 머리글 tx_code,target,mode,timeout_ms. 상태가 운영 인 행만, 같은 거래코드는 버전(정수)이 가장 큰 행 하나, 거래코드·대상은 공백을 떼고 대문자, mode 는 SYNC/ASYNC, timeout_ms 는 초×1000 정수. 접두어 규칙(CD*)도 그대로 싣고, tx_code 의 바이트 순서(LC_ALL=C sort)로 정렬한다.
  2. /root/eaimw/route/router.py 를 만든다. python3 router.py --routes <표> lookup <거래코드> 가 정확 일치 행을 찾아 JSON 한 줄 {"target": ..., "rule": "EXACT", "mode": ..., "timeout_ms": 정수} 를 출력하고 0 으로 끝난다. 없으면 {"target": null, "rule": "NONE"}종료 코드 3. 표에 접두어 행이 있어도 죽지 않아야 한다. --routes 를 생략하면 /root/eaimw/route/routes.csv.
  3. 접두어 규칙을 더한다. 거래코드가 CD*CD시작하면 rulePREFIX. 정확 일치가 접두어보다, 긴 접두어가 짧은 접두어보다 이긴다. 표의 행 순서와 무관해야 한다.
  4. 기관 규칙을 더한다. lookup <거래코드> --rcv-org <기관> 에서 기관이 100 이 아니면 거래코드와 무관하게 {"target": "FEP", "rule": "ORG"} 로 0 으로 끝난다. --rcv-org 를 생략하면 자행(100)이다.
  5. python3 router.py --routes <표> route <전문파일> 을 더한다. 공용 라이브러리 lhstd.parse 로 헤더를 읽어 TX_CODE·RCV_ORG 로 결정하고, 4단계 JSON 에 guid·tx_code·rcv_org 를 더해 한 줄로 출력한다(종료 코드는 lookup 과 같다). 형식이 틀린 전문이면 첫 줄 E102 <사유>, 종료 코드 2.
  6. route <전문파일> --reply <경로> 를 더한다. 결정이 NONE 이면 lhstd.reply 로 응답코드 E101 인 응답 전문을 그 경로에 쓰고 종료 코드 3. 라우팅이 된 전문에는 파일을 만들지 않는다.
  7. 전역 옵션 --audit <경로> 를 더한다. 주어지면 route 의 결정마다(NONE 포함) 그 파일에 JSON 한 줄을 덧붙인다 — 키 ts(결정 시각)·guid·tx_code·rcv_org·rule·target. 주지 않으면 아무것도 쓰지 않는다.
  8. 수신함 /opt/lab/fixtures/eaimw/route/inbox/ 전체를 5단계의 route 로 돌려 /root/eaimw/route/dispatch.csv 를 만든다. 머리글 file,tx_code,rule,target, 파일 이름순. 형식 오류는 파일,,E102,, NONE 은 target 을 비운다.

참고

인터페이스 목록을 라우팅 표로 정제한다

/opt/lab/fixtures/eaimw/route/interfaces.csv 에서 운영 중인 최신 버전만 골라 /root/eaimw/route/routes.csv(tx_code,target,mode,timeout_ms)를 만든다.

순서가 중요합니다 — 먼저 상태가 운영인 행만 남기고, 그다음 거래코드(공백 제거·대문자)마다 버전을 int 로 바꿔 가장 큰 행을 고릅니다. 버전 9 와 10 이 함께 있는 코드가 있습니다. 타임아웃에는 1.5 같은 소수도 있습니다.

정확 일치 라우터

/root/eaimw/route/router.py 의 lookup 이 표에서 정확히 같은 거래코드를 찾아 JSON 으로 답하고, 없으면 NONE 과 종료 코드 3 으로 끝난다.

csv.DictReader 로 표를 읽어 거래코드 → 행 사전을 만듭니다. 끝이 * 인 행은 이 단계에서는 건너뜁니다. 표 경로는 --routes 로 받습니다 — 채점기가 자기 표를 넘깁니다. 목적지를 찾지 못한 것은 오류가 아니라 결과이므로 JSON 을 출력한 뒤 3 으로 끝냅니다.

접두어 규칙 — 긴 것이 이긴다

끝이 * 인 행을 접두어 규칙으로 다룬다. 정확 일치 > 긴 접두어 > 짧은 접두어, 표의 행 순서와 무관하게.

접두어 목록을 길이 내림차순으로 정렬해 두면 처음 맞는 것이 가장 긴 것입니다. '처음 맞는 행' 을 파일 순서로 고르면 누군가 표를 정렬하는 순간 결과가 바뀝니다. startswith 로 비교하세요 — in 은 가운데에 있어도 맞습니다.

기관 규칙이 먼저다

lookup 에 --rcv-org 를 더해, 수신기관이 100 이 아니면 거래코드와 무관하게 FEP(rule ORG)로 보낸다.

ORG 는 1순위라 표를 찾기 전에 봅니다. 표에 없는 거래코드라도 대외 기관 앞이면 NONE 이 아니라 FEP 입니다. --rcv-org 의 기본값을 자행 100 으로 두면 앞 단계의 호출이 그대로 동작합니다.

전문 헤더로 라우팅한다

route <전문파일> 이 lhstd.parse 로 헤더를 읽어 결정 JSON(guid·tx_code·rcv_org 포함)을 내고, 형식 오류는 E102 와 종료 코드 2 로 거절한다.

open(파일, 'rb') 로 읽어 lhstd.parse 에 넘기면 TX_CODE·RCV_ORG·GUID 가 나옵니다. 송신기관(SND_ORG)이 아니라 수신기관을 봐야 합니다 — 보험사가 우리에게 보낸 전문은 대외계로 가면 안 됩니다. lhstd.FrameError 를 잡아 E102 로 끝내세요.

라우팅 불가를 E101 로 돌려준다

route 에 --reply <경로> 를 더해, NONE 이면 E101 응답 전문을 그 경로에 쓰고 종료 코드 3 으로 끝난다.

lhstd.reply(헤더, 'E101') 이 거래코드·GUID 를 유지하고 기관을 맞바꾼 응답 전문(bytes)을 만들어 줍니다. 파일은 'wb' 로 씁니다. 라우팅이 된 전문에는 만들지 않습니다.

라우팅 결정을 감사 로그로 남긴다

전역 옵션 --audit <경로> 가 주어지면 route 결정마다(NONE 포함) ts·guid·tx_code·rcv_org·rule·target 을 담은 JSON 한 줄을 덧붙인다.

open(경로, 'a') 는 덧붙이고 'w' 는 지우고 씁니다. 감사 로그는 지워지면 안 됩니다. 목적지만 남기면 '왜 거기로 갔나' 에 답할 수 없습니다 — 어느 규칙이 맞았는지(rule)가 핵심입니다.

수신함 30건을 배분한다

수신함 전체를 route 로 돌려 /root/eaimw/route/dispatch.csv(file,tx_code,rule,target)를 만든다.

파일마다 route 를 돌려 종료 코드로 가릅니다 — 2 는 형식 오류, 3 은 NONE 입니다. 결과를 목적지별로 세어 보면 한쪽으로 몰린 곳이 보입니다. 형식이 틀린 전문의 거래코드를 억지로 적지 마세요.