실동작 Enduro/X(오픈 Tuxedo) 카드 매입·정산 시스템 — 포지 마이그레이션 대상
Find a file
hyeongwoo-choi 7139fdd2fd docs: 상세 README (아키텍처·XA흐름·빌드/실행·검증·모듈·마이그레이션 매핑)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 23:09:39 +00:00
app 고도화: 전 모듈 dbio 25→40 · batch 17→22 세분화 (+432본, 전부 고유) 2026-07-19 14:37:10 +00:00
db/schema.d Phase 2b: 11개 모듈 전량 실동작 (333 서비스, 전서버 부팅) 2026-07-19 09:58:39 +00:00
docker Phase 2b: 11개 모듈 전량 실동작 (333 서비스, 전서버 부팅) 2026-07-19 09:58:39 +00:00
docs Phase 2a: 모듈서버 패턴 + 재사용 빌드시스템 (ac 모듈 38서비스 실동작) 2026-07-19 09:37:17 +00:00
slice Phase 1: 실동작 Enduro/X + PostgreSQL XA 매입 슬라이스 2026-07-19 09:16:12 +00:00
.gitignore 멀티모듈 인프라: schema.d/ 분리 + acq.fd 범용필드 (병렬 팬아웃 충돌회피) 2026-07-19 09:40:13 +00:00
README.md docs: 상세 README (아키텍처·XA흐름·빌드/실행·검증·모듈·마이그레이션 매핑) 2026-07-19 23:09:39 +00:00

acquire-core-x

실제로 동작하는 카드 매입·정산(acquiring & settlement) 레거시 시스템 — 오픈소스 TP 모니터 Enduro/X(open Tuxedo/ATMI) + ECPG/PostgreSQL + XA 2PC 위에서 tpcall 서비스와 배치가 진짜로 기동·트랜잭션 처리된다.

목적 — Klaro Forge 자율 마이그레이션 도구의 대형 전환 대상 픽스처. 이 C/ATMI 시스템(2,000+본)을 Java Spring Boot로 전환하는 시나리오를 검증한다. 컴파일만 되는 스텁이 아니라 상용급 TP 미들웨어에서 실제로 도는 시스템이라는 점이 핵심이다.


1. 스택

계층 실체 비고
TP 모니터 Enduro/X 7.0.12 (open Tuxedo/ATMI) tpservice/tpcall/tpadvertise/tpbegin/tpcommit, 소스빌드
전문 버퍼 UBF (≈ Tuxedo FML32) Bget/Bchg, 필드테이블 mkfldhdr
DB 접근 ECPG (EXEC SQL) → PostgreSQL 15 Pro*C 대응 오픈소스
분산 트랜잭션 XA 2PClibndrxxaecpg.so ECPG XA 스위치 tmsrv가 prepare/commit/rollback 조율
오케스트레이션 ndrxd + ndrxconfig.xml + app.ini(CCONFIG) 서버 그룹·서비스·RM 설정
컨테이너 docker compose (postgres + endurox app) 재현 가능한 단일 스택

주의(라이선스): Enduro/X 런타임은 AGPLv3(Mavimax). 내부 테스트 자산으로 사용. 상용 Tuxedo(Oracle)·Tmax ProFrame의 오픈소스 대응이며, 진짜 Tuxedo/Tmax는 사용하지 않는다.


2. 아키텍처

2.1 런타임 토폴로지

                 ┌──────────────────────── app 컨테이너 (Enduro/X) ─────────────────────────┐
  acqdrv  ─────▶ │  ndrxd (TP 모니터)                                                        │
 (client)        │   ├─ tmsrv (RM1 = PostgreSQL, XA 조율: prepare/commit/rollback)           │
   tpinit        │   ├─ cconfsrv / tpevsrv / cpmsrv (시스템 서버)                             │
   tpbegin       │   ├─ ac_svr  … 매입 30 서비스 (ACQUIRE, ACQ_DDC, ACQ_CANCEL …)            │
   tpcall  ─────▶│   ├─ au_svr  … 승인/한도 30    │  11개 "모듈 서버"                        │
   tpcommit      │   ├─ rc_svr  … 대사 30         │  각 서버가 자기 모듈의                    │
                 │   ├─ st_svr  … 정산/수수료 30  │  ~30 서비스를 tpadvertise               │
                 │   └─ … lg cl mm vl mg cm py    │  (총 333 서비스)                         │
                 │        │  EXEC SQL (ECPG, XA 스위치 libndrxxaecpg)                          │
                 └────────┼───────────────────────────────────────────────────────────────┘
                          ▼
                    PostgreSQL (db 컨테이너, max_prepared_transactions=100)
                    merchant · purchase · approval · settlement · ledger · … (75 테이블)

2.2 "모듈 서버" 패턴 (실제 Tuxedo 방식)

서비스 하나당 프로세스 하나가 아니라, 모듈 서버 1개가 그 모듈의 다수 서비스를 advertise한다. 서비스 로직은 파일 하나에 하나씩(svc/<SVCNAME>.pgc + 카피북 <SVCNAME>.h), 서버(<mod>_svr.pgc)는 얇은 디스패처(tpsvrinit에서 tpadvertise 테이블만). DB 접근은 dbio/*.pgc(정적 라이브러리로 링크), 배치는 독립 실행파일(batch/*.pgc).

2.3 XA 2PC 트랜잭션 흐름 (핵심)

client: tpbegin()                         # 글로벌 트랜잭션 시작
   └▶ tpcall("ACQUIRE")                    # ac_svr: EXEC SQL INSERT purchase  (XA 브랜치 A)
         └▶ tpcall("RECONCILE")            # rc_svr: EXEC SQL INSERT ledger    (XA 브랜치 B)
               └▶ tpcall("SETTLE")         # st_svr: EXEC SQL INSERT settlement(XA 브랜치 C)
client: tpcommit()
   └▶ tmsrv: xa_prepare(A,B,C) → xa_commit(A,B,C)   # 2단계 커밋, 원자적 확정

tpabort() 시 tmsrv가 세 브랜치를 모두 xa_rollback → DB에 아무것도 남지 않는다. ECPG XA 스위치가 tpopen()에서 연결을 열므로 EXEC SQL CONNECT가 없다. XA 브랜치 간에는 서로의 미커밋 행이 안 보이므로 각 서비스는 자기 테이블만 쓰는(owner-writes) 규율을 지킨다.


3. 디렉터리 구조

acquire-core-x/
├─ docker/
│  ├─ endurox.Dockerfile      # Enduro/X 소스빌드 (-DENABLE_POSTGRES=ON → libndrxxaecpg)
│  └─ docker-compose.yml      # postgres + endurox app (sysctl/ulimit 포함)
├─ db/
│  └─ schema.d/               # 00-base.sql + 모듈별 NN-<mod>.sql (75 테이블)
├─ app/
│  ├─ conf/                   # app.ini(CCONFIG), ndrxconfig.xml(생성), setapp.sh(XA env)
│  ├─ ubftab/acq.fd           # UBF 필드테이블 (전 모듈 공용)
│  ├─ build.sh                # 모듈 자동발견 빌드 + ndrxconfig 생성
│  ├─ entrypoint.sh           # 빌드 → ndrxd 기동
│  └─ src/<mod>/              # 11개 모듈 (ac au rc st py lg cl mm vl mg cm)
│     ├─ <mod>_svr.pgc        #   얇은 모듈 서버(디스패처)
│     ├─ svc/*.pgc + *.h      #   1서비스=1파일 + 카피북 (모듈당 30)
│     ├─ dbio/*.pgc + *.h     #   DB 접근 계층 (모듈당 ~40)
│     ├─ batch/*.pgc          #   XA 배치 (모듈당 ~22)
│     └─ run/*.sh             #   운영 기동 스크립트 (모듈당 ~17)
└─ docs/
   ├─ architecture.md         # 상세 아키텍처
   └─ service-catalog.md      # 서비스 카탈로그

4. 빌드 & 실행

docker compose -f docker/docker-compose.yml up -d --build     # postgres + endurox app 기동

빌드(전 모듈 ecpg→buildserver, ~240 배치 컴파일)는 수 분 걸린다. 완료되면 ndrxd가 11개 모듈 서버 + tmsrv를 부팅한다.

4.1 필수 런타임 요건 (없으면 ndrxd 부팅 실패 — 실측으로 규명)

POSIX 메시지큐/세마포어 한도 때문에 app 컨테이너에 반드시 필요 (compose에 이미 반영):

sysctls:
  fs.mqueue.msg_max:     "512"
  fs.mqueue.msgsize_max: "65536"
  fs.mqueue.queues_max:  "8192"     # 333 서비스 = 333+ 큐, 기본 256 초과
ulimits:
  msgqueue: 2147483648              # 큐 1개 = MSGMAX×MSGSIZEMAX, 다수 큐 → RLIMIT_MSGQUEUE 상향
  nofile:   65536

app.ini: NDRX_MSGMAX=50, NDRX_MSGSIZEMAX=16000 (큐당 메모리 축소). PostgreSQL: -c max_prepared_transactions=100 (XA 2단계 커밋용).


5. 검증 (실행 중인 시스템 확인)

C="docker compose -f docker/docker-compose.yml"

# 서버 프로세스 — 12개 전부 runok 이어야 함
$C exec app bash -lc '. /app/conf/setapp.sh; xadmin ppm'

# advertise된 서비스 — 333 AVAIL
$C exec app bash -lc '. /app/conf/setapp.sh; xadmin psc'

# 매입 거래 실행 (tpbegin → ACQUIRE→RECONCILE→SETTLE → tpcommit)
$C exec app bash -lc '. /app/conf/setapp.sh; /app/bin/acqdrv M0001 1000000'
#   >>> COMMIT OK: purchase_id=… fee=2500 net=997500 status=S

# DB 반영 + XA 정합성
$C exec db psql -U acq -d acq -c "select * from purchase; select * from settlement;"
$C exec db psql -U acq -d acq -c "select count(*) from pg_prepared_xacts;"   # 0 = 2PC 정상

검증 완료 상태: 12 서버 runok · 333 서비스 AVAIL · 매입체인 XA 원자 커밋(status=S) · pg_prepared_xacts=0(롤백 시 무잔존) · 전 .pgc 정규화-고유(클론 0).


6. 모듈 & 도메인

코드 모듈 대표 서비스
ac 매입(acquiring) ACQUIRE, ACQ_DDC/EDI/EDC, CANCEL/CORRECT, PARTIAL/INSTALL/FOREIGN, DUPCHK, WHT, TAXINV
au 승인/한도 AUTH, LIMIT_CHK/DEC/RST, STANDIN, FRAUD_DETECT, PREAUTH, DCC_QUOTE
rc 대사(reconcile) RECONCILE, RC_3WAY(승인·매입·입금), RC_TOLERANCE, RC_AMTDIFF, RC_AUTOFIX
st 정산/수수료 SETTLE, ST_MDR, ST_VANFEE, ST_NETTING, ST_VAT, ST_WHT, ST_PAYDATE(T+n)
py 지급(payment) PAY_FILEGEN(고정길이 전문), PAY_RESULT, PAY_SPLIT, PAY_XFERLINK
lg 원장(ledger) LG_POST, LG_DOUBLE(복식부기 차/대변), LG_BALCHK, LG_REVERSE, LG_TRIALBAL
cl 마감(closing) CL_DAILY/MONTHLY/QUARTER, CL_SNAPSHOT, CL_RECLOSE, CL_YEAREND
mm 마스터 MM_MERCH_REG/UPD, MM_FEERATE, MM_BIN, MM_LIMIT, MM_GRADE
vl 정합성검증 VL_SALES, VL_CARD, VL_AMOUNT, VL_ANOMALY, VL_REFINTEG
mg 전문게이트웨이 MG_ISO8583, MG_BITMAP, MG_STAN(채번), MG_ROUTE, MG_MAC
cm 공통 CM_CODE, CM_BIZDAY, CM_LUHN, CM_CRC, CM_FX, CM_SEQ

대표 tpcall 체인: ACQUIRE → RECONCILE → SETTLE(글로벌 XA, 매입→대사→정산→원장 반영).


7. 파일 통계

종류
전체 (git 추적) 2,052
프로그램 .pgc (svc 330 + dbio ~440 + batch ~240) 1,015
카피북/헤더 .h 817
기동/배치 스크립트 .sh 191
스키마 .sql 11
— 모듈 서버 11 · 서비스 330 · 배치 바이너리 242 · DB 테이블 75

.pgc는 정규화(식별자→X, 숫자→N, 공백제거) 후 md5 고유(클론 0) — 파일마다 실제 다른 로직.


8. 규명·해결한 실런타임 이슈 (재현 노트)

  1. gpgme 빌드의존 — Enduro/X tpbridgegpgme.h 요구 → libgpgme-dev 추가.
  2. atmitest 빌드깨짐DEFINE_DISABLETEST가 제외 안 함 → CMakeLists에서 add_subdirectory(atmitest) 제거.
  3. mqueue 한도fs.mqueue.queues_max(기본 256 < 333 서비스), RLIMIT_MSGQUEUE(큐당 5.6MB→0.8MB로 축소 + ulimit 상향).
  4. XA 브랜치 격리 — 형제 브랜치는 서로의 미커밋 행 불가시 → owner-writes 규율 + 서비스별 분리 서버.

9. 마이그레이션 타깃 매핑 (→ Spring Boot)

레거시 (Enduro/X) Spring Boot
tpservice / tpadvertise @Service 빈 + 메서드
tpcall(SVC) 빈 주입 호출(동기)
UBF Bget/Bchg (전문버퍼) DTO / record
tpbegin/tpcommit (XA) @Transactional (JTA 또는 단일 DB)
EXEC SQL / ECPG dbio MyBatis / JPA repository
커서 배치 Spring Batch
고정길이 전문 코덱(fixed-length)
ndrxconfig 서비스 등록 컴포넌트 스캔 / 라우팅
db/schema.d/*.sql Flyway

10. 검증 체크리스트

  • Enduro/X 소스빌드 (PostgreSQL XA 포함) → 이미지 acquire-x/endurox:7.0.12
  • ndrxd 부팅 (11 모듈서버 + tmsrv 전부 runok)
  • 커스텀 tpservice advertise + 실제 tpcall 왕복
  • ECPG XA 서비스 체인(매입→대사→정산) + 커밋 row psql 검증 + 롤백(prepared_xacts=0)
  • 2,000본+ 실동작 시스템 (2,052 파일 / .pgc 1,015본, 전 모듈 dbio·batch 세분화)
  • .pgc 정규화-고유 (클론 0)
  • Klaro Forge 마이그레이션 → Spring Boot (Phase 3, 예정)