acquire-core-x/app/ui/metrics.js
hyeongwoo 12812a6c33 Wave L: 외부 연동·전문처리 (ISO8583 와이어·소켓 왕복·클리어링 파일, 패리티→~89%)
외부 카드망 연동(전문처리)을 실제 프로토콜로 구현 — 마이그레이션 최난이도 계층
(소켓·바이너리 전문·프레이밍·상태처리)이 실제로 동작.

■ ISO 8583 와이어 코덱 (common/acq_iso8583.c)
- 1차 비트맵(64bit) + DE 인코딩/파싱(PAN LLVAR·금액·STAN·RRN·응답코드·MID/TID 등).
- iso_build/iso_parse 왕복 무손실 검증(비트맵 7220000000C08000 정확).

■ 외부 카드망 시뮬레이터 (clients/acq_extsw.c, :9500)
- TCP 서버: 길이접두 프레이밍 + ISO 전문. 0200 수신→승인판정→0210 응답 조립
  (DE38 승인번호·DE39 응답코드). 금액임계/STAN으로 일부 거절(05).

■ 전문 왕복 드라이버 (clients/acq_netdrv.c)
- 실매입건→0200 조립→소켓 전송→0210 수신·파싱→mg_netlog 적재(RTT·응답코드).
- 실측: 200건 왕복 승인198/거절2/오류0, 0200→0210, 평균 RTT 0.3ms.

■ 클리어링 파일 교환 (clients/acq_clrfile.c)
- cl_presentment→고정폭 정산파일(/app/out/CLR_BC_YYYYMMDD.dat) HD/DT/TR+체크섬 생성,
  cl_clearing_file 등록. 실제 SFTP 배치 파일교환 대역. 샘플 파일 커밋.

■ 스키마·부팅·화면
- 74-netio.sql: mg_netlog(왕복로그)·cl_clearing_file(파일 레지스트리).
- entrypoint.sh: acq_extsw 부팅 자동기동(:9500).
- build.sh: 클라이언트에 libacqcommon.a(ISO 코덱) 링크.
- 시스템현황에 "외부망 전문 왕복"·"클리어링 파일 교환" 패널.

패리티 재채점 ≈89/100. 남은 ~11%는 상용회선·HSM·다중센터 DR 등 배포 인프라.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 14:59:36 +09:00

2 lines
4.2 KiB
JavaScript

/* 자동생성: tools/gen_metrics.py — 소스 실측 마이그레이션 난이도 지표. 손대지 말 것. */
window.METRICS={"SCALE":[{"k":"소스 파일 (.pgc/.c/.h)","v":4661,"u":"개"},{"k":"총 코드 라인","v":333517,"u":"LOC"},{"k":"온라인 서비스","v":1478,"u":"본"},{"k":"배치 잡","v":506,"u":"본"},{"k":"임베디드 SQL(EXEC SQL)","v":23879,"u":"블록"},{"k":"Tuxedo tpcall 호출","v":985,"u":"곳"},{"k":"전역 트랜잭션 tpbegin","v":1234,"u":"곳"},{"k":"UBF 버퍼 필드접근","v":47295,"u":"곳"},{"k":"DB 테이블","v":101,"u":"개"},{"k":"카피북 헤더(.h)","v":2223,"u":"개"}],"HAZARDS":[{"t":"Tuxedo ATMI (tpcall/tpservice/tpreturn)","n":985,"u":"호출","why":"Java·Spring에 1:1 대응 API가 없다. 서비스 호출 모델 자체를 REST/메시지로 재설계해야 하며, 문법 치환으로는 불가능."},{"t":"XA 2PC 전역 트랜잭션 (최대 6단 중첩)","n":1234,"u":"tpbegin","why":"형제 XA 브랜치 격리·2단계 커밋 의미론이 Spring @Transactional 경계와 다르다. 잘못 옮기면 교착·이중전기가 그대로 재현된다."},{"t":"ECPG 임베디드 SQL (호스트변수·커서·sqlca)","n":23879,"u":"블록","why":"EXEC SQL 블록마다 호스트변수 바인딩·sqlcode 분기·커서 수명을 JPA/MyBatis 의미로 옮겨야 한다. 자동 변환기가 가장 많이 깨지는 지점."},{"t":"UBF(FML32) 타입리스 버퍼","n":47295,"u":"필드접근","why":"필드ID 기반 동적 버퍼라 타입·필수여부가 컴파일타임에 없다. Java DTO로 옮기려면 47,000여 접근점의 계약을 사람이 복원해야 한다."},{"t":"카피북 공유(#include) 팬아웃","n":6921,"u":"참조","why":"한 카피북을 수십 프로그램이 공유해 구조체 변경이 전방위로 파급된다. 경계 없는 결합이라 모듈 단위 절단이 어렵다."},{"t":"전처리 매크로(#define)","n":2267,"u":"정의","why":"매크로가 코드 생성·분기를 숨겨 정적 분석을 방해한다. 전개 후에야 실제 로직이 드러난다."}],"TRACE":[{"root":"ACQUIRE","tree":{"svc":"ACQUIRE","mod":"ac","wr":["cm_log"],"children":[{"svc":"RECONCILE","mod":"rc","wr":["cm_log","ledger"],"children":[{"svc":"SETTLE","mod":"st","wr":["ledger","settlement"],"children":[{"svc":"ST_MDR","mod":"st","wr":["ledger"],"children":[{"svc":"LG_SETTLEPOST","mod":"lg","wr":["cm_log"],"children":[{"svc":"LG_BALCHK","mod":"lg","wr":["cm_log"],"children":[]}]}]}]}]}]},"stat":{"programs":6,"tables":3,"xa_branches":6,"tablelist":["cm_log","ledger","settlement"]}},{"root":"PAY_APPROVE","tree":{"svc":"PAY_APPROVE","mod":"py","wr":["cm_log","py_payout"],"children":[{"svc":"PAY_FILEGEN","mod":"py","wr":["cm_log","py_file","py_payout"],"children":[{"svc":"PAY_ACCTCHK","mod":"py","wr":["cm_log"],"children":[{"svc":"LG_POST","mod":"lg","wr":["cm_log"],"children":[{"svc":"LG_BALCHK","mod":"lg","wr":["cm_log"],"children":[]}]}]}]}]},"stat":{"programs":5,"tables":3,"xa_branches":5,"tablelist":["cm_log","py_file","py_payout"]}},{"root":"CL_DAILY","tree":{"svc":"CL_DAILY","mod":"cl","wr":["cm_log"],"children":[{"svc":"VL_SALES","mod":"vl","wr":[],"children":[{"svc":"RC_EXCEPTION","mod":"rc","wr":["cm_log"],"children":[{"svc":"CM_LOG","mod":"cm","wr":[],"children":[]}]}]},{"svc":"LG_CLOSE_LINK","mod":"lg","wr":["cm_log","lg_ledger_line"],"children":[{"svc":"CL_LOCK","mod":"cl","wr":["SET","cl_close_log","cl_period_lock","cm_log"],"children":[]}]}]},"stat":{"programs":6,"tables":5,"xa_branches":6,"tablelist":["SET","cl_close_log","cl_period_lock","cm_log","lg_ledger_line"]}}],"LEGACY":{"copybook_total":2223,"copybook_shared_max":138,"copybook_shared_name":"acq_common.h","macro_defs":2267,"goto":64,"userlog":17267,"sqlca_checks":18877,"embedded_sql_density":9.8},"ORACLE":{"asis_files":9,"asis_proc":7,"asis_plsql":2,"asis_loc":1827,"dialects":[{"t":"PL/SQL 패키지 호출 (pkg_x.proc)","n":18},{"t":"NVL / NVL2 널가드","n":60},{"t":"DECODE 다분기","n":16},{"t":"SYSDATE / SYSTIMESTAMP","n":42},{"t":"FROM DUAL","n":15},{"t":"시퀀스 .NEXTVAL","n":27},{"t":"ROWNUM 의사컬럼","n":6},{"t":"구식 외부조인 (+)","n":8},{"t":"CONNECT BY 계층질의","n":3},{"t":"WHENEVER SQLERROR 라벨분기","n":16},{"t":"TO_DATE / TO_CHAR 포맷","n":35},{"t":"RAISE_APPLICATION_ERROR","n":13}]}};