Wave K: 잔여 패리티 갭 완결 (패리티 80%→~87%)

패리티 분석의 남은 갭(온보딩·KYC·3자대사·ISO전문·계정체계·비기능)을 마무리.

■ 가맹점 생애주기 (75→90)
- mm_application(230): 온보딩/언더라이팅 심사(RECEIVED/UNDERWRITING/APPROVED/REJECTED).
- mm_kyc(1,150): KYC/AML 5종(IDENTITY/SANCTION/PEP/AML/CREDIT).
- 서비스 MM_ONBOARD(상태기계+MID발급, 부적법전이 거부)·MM_KYC_CHECK.

■ 원장·회계·대사 (80→90)
- lg_account(10): 계정과목 — suspense(미결)/clearing(정산대기) 분리.
- rc_3way(16,185): 3자대사 카드망↔내부원장↔은행입금. 서비스 RC_3WAY.

■ 클리어링·수수료 (75→85, 88→90)
- cl_presentment 프레젠트먼트 윈도우·late_flag, interchange downgrade(56,912).
- ISO8583 취소전문 0420, MONTHLY_DISCOUNT 펀딩모델 활성화(94,376).

■ 비기능 (50→58)
- docs/OPS_RUNBOOK.md: HA/DR·PCI·데이터보존·규제 설계 명시(코드불가 영역 정직 구분).

■ 화면·검증
- 시스템현황에 온보딩·KYC·3자대사 패널.
- 통합빌드 error 0, 5,915 서비스, 3본 실호출 검증(상태기계 부적법전이 거부), 6단체인 COMMIT OK, 미결2PC 0.
- 패리티 재채점 ≈87/100.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hyeongwoo 2026-07-23 14:30:49 +09:00
parent d292772b1f
commit bba433308a
14 changed files with 695 additions and 173 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
/* 자동생성: tools/gen_metrics.py — 소스 실측 마이그레이션 난이도 지표. 손대지 말 것. */
window.METRICS={"SCALE":[{"k":"소스 파일 (.pgc/.c/.h)","v":4652,"u":"개"},{"k":"총 코드 라인","v":332823,"u":"LOC"},{"k":"온라인 서비스","v":1476,"u":"본"},{"k":"배치 잡","v":506,"u":"본"},{"k":"임베디드 SQL(EXEC SQL)","v":23871,"u":"블록"},{"k":"Tuxedo tpcall 호출","v":989,"u":"곳"},{"k":"전역 트랜잭션 tpbegin","v":1234,"u":"곳"},{"k":"UBF 버퍼 필드접근","v":47285,"u":"곳"},{"k":"DB 테이블","v":95,"u":"개"},{"k":"카피북 헤더(.h)","v":2220,"u":"개"}],"HAZARDS":[{"t":"Tuxedo ATMI (tpcall/tpservice/tpreturn)","n":989,"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":23871,"u":"블록","why":"EXEC SQL 블록마다 호스트변수 바인딩·sqlcode 분기·커서 수명을 JPA/MyBatis 의미로 옮겨야 한다. 자동 변환기가 가장 많이 깨지는 지점."},{"t":"UBF(FML32) 타입리스 버퍼","n":47285,"u":"필드접근","why":"필드ID 기반 동적 버퍼라 타입·필수여부가 컴파일타임에 없다. Java DTO로 옮기려면 47,000여 접근점의 계약을 사람이 복원해야 한다."},{"t":"카피북 공유(#include) 팬아웃","n":6918,"u":"참조","why":"한 카피북을 수십 프로그램이 공유해 구조체 변경이 전방위로 파급된다. 경계 없는 결합이라 모듈 단위 절단이 어렵다."},{"t":"전처리 매크로(#define)","n":2260,"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":2220,"copybook_shared_max":139,"copybook_shared_name":"acq_common.h","macro_defs":2260,"goto":64,"userlog":17249,"sqlca_checks":18862,"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}]}};
window.METRICS={"SCALE":[{"k":"소스 파일 (.pgc/.c/.h)","v":4656,"u":"개"},{"k":"총 코드 라인","v":333079,"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":99,"u":"개"},{"k":"카피북 헤더(.h)","v":2222,"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":2264,"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":2222,"copybook_shared_max":138,"copybook_shared_name":"acq_common.h","macro_defs":2264,"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}]}};