diff --git a/frontend/public/manual.html b/frontend/public/manual.html new file mode 100644 index 0000000..5643006 --- /dev/null +++ b/frontend/public/manual.html @@ -0,0 +1,334 @@ + + +
+ + +소액 RTGS(실시간총액결제) 프로토타입 · 7개 서비스 안내 · Active-Active-Active 복원력 설계
++ 본 포탈은 소액 RTGS(Real-Time Gross Settlement, 실시간총액결제) 프로토타입의 운영·관리 콘솔입니다. + 거래는 단일 전역 순번기가 입구에서 순번을 부여하고, 각 센터가 그 순번대로 동일하게 재생(결정론적 처리)하며, + 원장(PostgreSQL)이 잔액을 강한 일관성으로 확정합니다. 3센터 Active-Active-Active 구성에서 + 정족수(2/3)와 펜싱으로 split-brain을 차단하는 것이 설계의 핵심입니다. +
++ 시스템은 명품 브랜드를 코드네임으로 쓰는 7개 서비스로 구성됩니다. 포탈 화면에는 이 중 + 주요 6개가 카드로 표시되고, 전역 순번기(Sequencer)는 업무 흐름도의 진입 노드로 나타납니다. + 각 서비스가 무슨 일을 하고, 카드에 표시되는 숫자가 무엇을 뜻하는지 이 문서에서 설명합니다. +
+ +
+ 상단 바의 ● n/7 UP은 7개 서비스 중 정상 가동 중인 수를 나타냅니다.
+ 각 서비스는 DB의 service_heartbeat에 주기적으로 살아있음을 기록하고(헤드리스 포함),
+ 관리 서비스가 이를 읽어 UP/STALE/DOWN을 판정합니다.
+
+ 자동갱신 5s 체크 시 5초마다 상태·지표를 다시 불러옵니다. + 새로고침으로 즉시 갱신할 수도 있습니다. + 카드의 처리 건수는 DB 집계(원장) 기준이라 관리자 콘솔에서 초기화하면 자연히 0으로 돌아갑니다. +
+ +한 건의 이체는 아래 순서로 처리됩니다. 각 노드는 담당 서비스이며, 포탈 흐름도에서 색 테두리로 실시간 상태를 함께 보여줍니다.
++ 전역순번(Sequencer) 부여 → 관문 인증(Gucci) → 접수(Chanel) → 저널/센터 동기화(Dior) → + 결제·원장(Hermes) → 처리 동기화·완결(Prada) → 결과통보(Chanel). +
+ +
+ 시스템의 단일 진입 순서 결정자입니다. 접수된 요청에 전역순번(global_seq)을 부여해
+ 단일 파티션 저널에 발행하면, 모든 센터가 이 순서를 그대로 재생해 동일한 결과를 만듭니다(결정론적 처리).
+ 재기동 시 MAX(global_seq)에서 이어서 발번하므로 순번 유실이 없습니다.
+
※ 순서 결정만 담당(상태 O). 분산·라우팅은 Gucci/GSLB(상태 X)가 맡아 역할을 분리합니다. + 포탈에서는 별도 카드 없이 흐름도의 진입 노드로 표시됩니다.
++ 참가기관과 시스템 사이의 대문입니다. 로그인 후 JWT(HS256)를 발급하고, 모든 요청의 인증·인가 + (역할 + 기관 바인딩)를 검사합니다. 기관별 유량제어로 코어·순번기를 보호하고(백프레셔), + nonce+timestamp로 재전송을 차단합니다. 처리 결과는 기관 콜백 URL로 재시도·ACK 방식으로 송부합니다. +
+| 카드 지표 | 의미 |
|---|---|
| 코어(샤넬) | Gucci가 바라본 코어(Chanel) 연결 상태 |
| 등록기관 | 당좌계좌가 등록된 참가기관 수 |
+ 참가기관의 결제의뢰 전문(ISO 20022 pacs.008)을 받는 접수 창구입니다. + 공식 XSD로 검증(XXE 차단)하고 원전문을 SHA-256 해시와 함께 저장한 뒤, 경량 명령문으로 만들어 + 입구 토픽에 발행합니다. 처리가 끝나면 pacs.002 결과통보 전문을 생성해 아웃박스에 적재합니다. +
+| 카드 지표 | 의미 |
|---|---|
| 누적 접수 | 지금까지 접수된 거래 건수(원장 집계) |
| 접수율 | 초당 접수 건수(TPS, 최근 갱신 구간 기준) |
+ 전역순번 저널을 소비해 원장에 거래를 PDNG(대기) 상태로 기록합니다. 결제(Hermes)와 병행해 + 저널을 읽으면서 모든 센터의 접수 상태를 동일하게 맞추는 동기화 역할을 합니다. +
+| 카드 지표 | 의미 |
|---|---|
| 메모리 | 프로세스 사용 메모리(MB) — 런타임 자원 지표 |
| 가동 | 프로세스 가동 시간(초) |
+ 실제 잔액을 움직이는 결제 엔진입니다. 저널을 순번대로(동시성 1) 소비하며 순서를 교정하고, + 잔액 연산 전에 선저널(write-ahead)로 순번을 확정한 뒤 송신·수신 기관 당좌계좌를 차/대변 처리합니다 + (PostgreSQL 강한 일관성 트랜잭션 → 이중지급 0·총액 보존). 정산이 반영되면 ACSP 결과를 발행합니다. + 선저널 덕분에 엔진이 죽었다 살아나도 Kafka 오프셋 재생으로 무손실 승계됩니다. +
+| 카드 지표 | 의미 |
|---|---|
| 결제완료(ACCC) | 최종 완결된 거래 건수(원장 집계) |
| 평균 처리 | 정산 1건당 평균 소요시간(ms) — 런타임 지표 |
| 미결(대기) | 접수됐으나 아직 완결·반려되지 않은 건수(전체 − ACCC − RJCT) |
+ 정산 결과를 소비해 완결 규율을 적용합니다. 과반(정족수) 센터가 동일 결과를 확정하면
+ 최종 상태 ACCC(입금처리완료)로 확정하고 조회 전용 사본을 남깁니다. 완결이 커밋되면
+ 결과통보(rtgs.notify)를 발행해 Chanel→Gucci를 통한 기관 통보로 이어집니다.
+
| 카드 지표 | 의미 |
|---|---|
| 완결(ACCC) | 최종 완결된 거래 건수 |
| 반려(RJCT) | 검증 실패·잔액 부족 등으로 반려된 건수 |
+ 시스템 관리·운영 서비스입니다. DB 초기화, 상태코드·기관·사용자 권한 관리, 헬스(하트비트) 집계,
+ 원장=저널=조회사본 대사(對査) 대시보드를 제공합니다. 스키마는 Flyway로 형상 관리하며 기동 시 자동 적용합니다.
+ (관리자 콘솔은 ADMIN JWT 필수, 테스트 계정 a / 1)
+
| 카드 지표 | 의미 |
|---|---|
| 총 거래 | 원장에 기록된 전체 거래 건수 |
| 최대순번 | 부여된 전역순번의 최댓값(MAX(global_seq)) |
한 건의 거래는 아래 상태를 따라 진행됩니다.
+| 상태 | 한글 | 담당 | 설명 |
|---|---|---|---|
RCVD | 접수 | Chanel | 전문 접수·검증 통과 |
ACTC | 순번 | Sequencer | 전역순번 부여 |
PDNG | 대기 | Dior | 원장에 대기 기록(접수 동기화) |
ACSP | 정산반영 | Hermes | 당좌 차/대변 반영 |
ACCC | 입금처리완료 | Prada | 과반 확정 · 최종 완결 |
RJCT | 반려 | Chanel/Hermes | XSD·업무규칙 실패 또는 잔액부족·미등록기관 |
RCVD → ACTC → PDNG → ACSP → ACCC.
+ 검증·잔액 문제 시 RJCT로 종료됩니다.
+ | 서비스 | 포트 | 유형 |
|---|---|---|
| 🔢 Sequencer | 8090 | Headless JVM (논리) |
| 📥 Chanel | 8091 | Web (Tomcat) |
| 🔄 Dior | 8092 | Headless JVM (논리) |
| 💰 Hermes | 8093 | Headless JVM (논리) |
| ✅ Prada | 8094 | Headless JVM (논리) |
| 🛡️ Gucci | 8095 | Web (Tomcat) |
| 🛠️ Louis Vuitton | 8099 | Web (Tomcat) |
| 운영/관리 콘솔 (Frontend) | 5174 | React + Vite |
| PostgreSQL (원장) | 5433 | RDBMS |
| Kafka (입구/저널/결과/통보) | 9092 | KRaft |
| Elasticsearch / Logstash / Kibana | 9200 / 5000 / 5601 | ELK 로그 |
| 약어 | 의미 |
|---|---|
| RTGS | Real-Time Gross Settlement — 실시간총액결제 |
| A-A-A | Active-Active-Active — 3센터 동시 가동 |
| BMI | Business Message Identifier — 거래식별자 22자리(영업일8+기관4+일련10) |
| 저널 | 전역순번이 부여된 처리 명단(Kafka 단일 파티션) |
| 정족수 | Quorum(N/2+1). 3센터=2 |
| 선저널 | Write-ahead journal — 잔액연산 전 순번 확정(무손실 승계) |
| pacs.008 / pacs.002 | ISO 20022 결제의뢰 / 결과통보 전문 |
| TPS | Transactions Per Second — 초당 처리 건수 |
시스템관리(LouisVuitton)·포탈 상태 조회는 ADMIN 로그인이 필요합니다.
+{err}
} +본격 사용 전 초기 비밀번호를 변경해야 합니다.
+{msg}
} + {err &&{err}
} +| {ko} | )}
|---|
| - {timeCols.includes(k) ? fmtTs(r[k]) : String(r[k] ?? '-')} - | )}
시스템관리(LouisVuitton) 콘솔은 ADMIN 로그인이 필요합니다.
테스트 계정: a / 1
{err}
} -본격 사용 전 초기 비밀번호를 변경해야 합니다.
-{err}
} -⚠ 제어 비활성화(rtgs.control.enabled=false) — 상태 조회만 가능
} + {!services && 상태 수집 대기…} + {services && ( +| 상태 | 서비스 | 포트 | PID | 제어 | +
|---|---|---|---|---|
| + {s.status === 'UP' ? '🟢 UP' : '🔴 DOWN'} + {s.status === 'UP' && s.ageMs != null && · {Math.round(s.ageMs / 1000)}s} + | +{s.name} | +:{s.port} | +{s.pid ?? '-'} | ++ {s.controllable ? ( + + + + + + + ) : 선행 필수(스크립트로 기동)} + | +
| {f.reachable ? '🟢 UP' : '🔴 DOWN'} | +{f.name} (인프라) | +:{f.port} | +- | +선행 필수(스크립트로 기동) | +
{svcLog.lines.join('\n') || '(로그 없음)'}
+ | {labels[k] ?? k} | {k} | @@ -219,13 +244,69 @@ export default function App() {
{prettyXml(rawXml)}
- | 단계 | +서비스 | +처리시각 (YYYYMMDDHH24MISS) | +
|---|---|---|
| {s.emoji} {s.label} | +{s.svc} | +{has ? fmtTs(v) : '—'} | +
{prettyXml(rawXml)}
+ : (원문 pacs.008 없음 — 접수 단계에서 반려되었거나 미저장)
)} + + {msgTab === '002' && (notifs.length > 0 + ? notifs.map((n, i) => ( +{prettyXml(String(n.pacs002))}
+ : (pacs.002 전문 없음)
} +(결과통보 없음 — 아직 미완결이거나 접수 단계 반려)
)} +(원문 전문 없음 — 접수 단계에서 반려되었거나 미저장)
}{err}
} +| {ko} | )}
|---|
| + {timeCols.includes(k) ? fmtTs(r[k]) : String(r[k] ?? '-')} + | )}