# RTGS 프로토타입 워크플로우

> 로컬(1센터 DC1) RTGS 프로토타입의 전문 처리 흐름 · 서비스별 처리 · 데이터 흐름 정리
> 작성: 루비 · 담당: 양팀장님

---

## 1. 시스템 구성도

```
                          [참가기관 / 부하생성기(k6) / 조회·신청 콘솔(:5174)]
                                             │  pacs.008 (HTTP, XML)
                                             ▼
   ┌──────────────────────────── 1센터 (CENTER_ID=DC1) ────────────────────────────┐
   │                                                                                │
   │  ① Chanel(전문송수신) :8091                                                     │
   │     XSD검증 → 경량명령문(75B)+원전문해시 → 원전문 저장 → 입구 발행 → pacs.002 응답 │
   │        │ rtgs.inbound                         └→ raw_message(PostgreSQL)         │
   │        ▼                                                                        │
   │  ③ Sequencer(순번기) :8090   전역순번 부여 + 결정론적값 확정 → 저널 발행           │
   │        │ rtgs.journal (단일 파티션 = 전역 순서)                                   │
   │        ├───────────────┬───────────────────────────┐                            │
   │        ▼               ▼                           ▼                            │
   │  Dior(접수동기화)   Hermes(결제/원장엔진, cc=1)   (저널 구독)                      │
   │   PDNG 기록         순차소비→선저널→잔액이체→ACSP→결과발행                          │
   │        │               │ rtgs.result                                            │
   │        │               ▼                                                        │
   │        │           Prada(결과동기화)  과반확정→ACCC 최종확정                       │
   │        ▼               ▼               ▼                                        │
   │   ┌──────────────── PostgreSQL(:5433, 강한 일관성 원장) ────────────────┐        │
   │   │ account(잔액) · transfer(거래상태) · journal_log(선저널) ·           │        │
   │   │ settlement_view(조회사본) · raw_message(원전문) · app_user           │        │
   │   └────────────────────────────────────────────────────────────────────┘        │
   │                                                                                │
   │  ⑥ LouisVuitton(관리자) :8099  초기화·코드·사용자·대사   (← 콘솔 관리자 탭)
   │  ⑦ Gucci(외부 경계 관문) :8095  로그인·API인증·유량제어·재전송차단·결과콜백송부(→참가기관)        │
   └────────────────────────────────────────────────────────────────────────────────┘

   로그:  각 서비스(Logback) ──TCP:5000──▶ Logstash ──▶ Elasticsearch(:9200) ──▶ Kibana(:5601)
   메시지: Kafka(:9092, KRaft)  토픽: rtgs.inbound / rtgs.journal / rtgs.result / rtgs.notify
```

---

## 2. 자금이체 처리 워크플로우 (핵심)

### 흐름 요약
```
[신청] ORG_S가 pacs.008 전송
   └▶ [접수] Chanel : XSD검증·경량화·원전문저장 → 상태 RCVD → rtgs.inbound
        └▶ [순번] Sequencer : 전역순번+결정론적값 → 상태 ACTC → rtgs.journal(저널)
             ├▶ [접수동기화] Dior : 저널 소비 → PostgreSQL 원장에 PDNG 기록
             └▶ [청산·정산] Hermes : 저널 순차소비(cc=1)
                   → gap/역전 탐지·재정렬 → 선저널(write-ahead)
                   → 송신기관 당좌 −금액 / 수신기관 당좌 +금액 (강한 일관성 트랜잭션)
                   → 상태 ACSP → (커밋 후) rtgs.result 발행
                   └▶ [결과동기화] Prada : 결과 소비 → 과반(2/3) 확정
                         → 상태 ACCC(입금처리완료) 최종확정 + 조회사본 기록
                         → (커밋 후) rtgs.notify 발행
   └▶ [결과통보] Chanel(접수센터) : rtgs.notify 소비 → 최종 pacs.002 생성
         → 신청기관(송신) 앞 결과통보 + 수취기관 앞 입금통보(ACCC) → notification 아웃박스
```

### 단계별 상세 (각 서비스가 다루는 토픽/DB)

| 순서 | 서비스 | 입력 | 처리 | 출력 | 상태 |
|---|---|---|---|---|---|
| ① | **Chanel** | HTTP pacs.008 | XSD검증→경량명령문+원전문해시, 원전문 저장 | `raw_message` 저장, `rtgs.inbound` 발행, pacs.002 응답 | RCVD |
| ② | **Sequencer** | `rtgs.inbound` | 전역순번 부여 + 결정론적값(수신시각) 확정 | `rtgs.journal` 발행(저널) | ACTC |
| ③ | **Dior** | `rtgs.journal` | BMI 중복체크(upsert) | `transfer` PDNG 기록 | PDNG |
| ④ | **Hermes** | `rtgs.journal`(cc=1 순차) | 순서 탐지·교정 → 선저널 → 당좌계좌 차·대변(강한 일관성) | `account`·`journal_log`·`transfer`(ACSP), `rtgs.result` 발행 | ACSP |
| ⑤ | **Prada** | `rtgs.result` | 완결 규율(과반 확정) | `transfer`(ACCC)·`settlement_view`, (커밋 후) `rtgs.notify` 발행 | ACCC |
| ⑥ | **Chanel**(결과통보) | `rtgs.notify` | 최종 pacs.002 생성, 접수센터만 송부 | `notification`(신청기관+수취기관) | — |

> **핵심 원칙**: 어느 센터로 접수돼도 **단일 순번기**가 하나의 전역순번으로 줄 세우고, 저널(단일 파티션)을
> N센터가 **같은 순서로 결정론적 재생** → 세 센터 데이터가 항상 동일. 잔액 변경이 하나의 순번 줄로
> 직렬화되므로 "동시에 같은 계좌"가 없어 **이중지급 원천 차단**.

---

## 2.5 서비스별 처리 개념도 (참조)

| 서비스 | 개념도 |
|---|---|
| Chanel(전문송수신) | ![Chanel](chanel.png) |
| Dior(접수동기화) | ![Dior](dior.png) |
| Hermes(결제/원장엔진) | ![Hermes](hermes.png) |
| Prada(결과동기화) | ![Prada](prada.png) |

> 전체 업무 흐름은 ![업무 흐름도](2센터흐름도.png) 참조.

---

## 3. 상태 전이도 (TxSts)

```
   (접수)      (승인)        (대기)         (예약)         (완결)
   RCVD ──▶ ACTC ──▶ [PDNG] ──▶ ACSP ──────────▶ ACCC
    │Chanel   │Sequencer  │Dior     │Hermes(이체)   │Prada(과반확정)
    │
    └─(검증실패/잔액부족/미등록기관)─▶ RJCT (반려)
```
- **RCVD** 접수 / **ACTC** 승인(순번부여) / **PDNG** 대기(원장 기록) / **ACSP** 예약(결제 반영, 결과대기) / **ACCC** 입금처리완료(최종) / **RJCT** 반려

---

## 4. 데이터 흐름

**Kafka 토픽** (전 센터 공유 단일 클러스터 = 순서 공유)
- `rtgs.inbound` : Chanel → Sequencer (접수 원시)
- `rtgs.journal` : Sequencer → 전 센터(Dior/Hermes) (전역순번 저널, **단일 파티션**)
- `rtgs.result`  : Hermes → Prada (결제결과)
- `rtgs.notify`  : Prada → Chanel (완결 결과통보 트리거; 접수센터가 신청/수취기관 앞 pacs.002 송부)

**PostgreSQL 테이블** (센터별 원장, 강한 일관성)
- `account` 참가기관 당좌계좌 잔액 | `transfer` 거래 원장·상태 | `journal_log` 선저널
- `settlement_view` 조회 사본 | `raw_message` 원전문(pacs.008) | `notification` 결과통보 아웃박스 | `app_user` 사용자·권한

**로그(ELK)**: 서비스 Logback(JSON, service/center 필드) → Logstash(:5000) → ES `rtgs-logs-*` → Kibana

---

## 5. 관리자(LouisVuitton) 워크플로우

```
콘솔(:5174) "🛠 관리자" 탭 ──▶ louisvuitton(:8099) /admin/*
  · DB 초기화     : transfer/journal_log/settlement_view/raw_message TRUNCATE + 계좌 잔액 리셋
  · 코드 관리     : 참가기관(account) 마스터 CRUD + 상태코드 데이터사전
  · 사용자 권한   : app_user CRUD (ADMIN/ORG_S/ORG_R) — 로그인 강제는 후속
  · 대사 대시보드 : 상태별 건수·총액 보존 체크 + 서비스별 처리 현황(transfer/journal_log/settlement_view)
```

---

## 6. 개발 · 실행 워크플로우

**빌드** (JDK21로 — Gradle 8.10.2는 JDK26 미지원; `gradle.properties`에 고정)
```
cd C:\ai-dev\workspace\rtgs\backend
gradlew build           (EDR 파일락 시 재시도)
```
**기동/종료**
```
run-dc1.cmd                      : 네이티브 인프라(Postgres/Kafka) + 6개 서비스
infra\start-elk-native.cmd       : ES/Logstash/Kibana (로그)
run-frontend.cmd                 : 콘솔(:5174)
stop-dc1.cmd                     : 인프라 종료(데이터 보존)
```
**접속**: 콘솔 http://localhost:5174 · Kibana http://localhost:5601

**변경→반영**: 백엔드 = 재빌드(bootJar)+해당 서비스 재기동 / 프론트 = Vite HMR(자동)

---

## 6.5 Gucci(외부 경계 관문, :8095) 워크플로우

참가기관은 코어(Chanel:8091)에 직접 붙지 않고 **Gucci 관문**을 통한다(외부↔RTGS 북-남 경계).
전역 결제순서는 **Sequencer 단독**이며 Gucci는 관문/인증/유량제어/전달보장만 담당(순서 결정 아님).

```
참가기관 ──① 로그인(POST /gucci/auth/login, secret) ──▶ Gucci ── app_user.secret 대조 ──▶ JWT 발급
        ──② 이체신청(POST /gucci/pay/customer, Bearer+X-Nonce+X-Timestamp) ──▶ Gucci 가드:
              [JWT검증] → [역할 ORG_S/ADMIN] → [유량제어 50/10s] → [재전송 nonce/timestamp]
              → [기관바인딩: 토큰 org == 전문 DbtrAgt MmbId] → (통과) Chanel /pay/customer 프록시
        ◀── pacs.002(RCVD) ──

[완결 후 결과 콜백송부 — G2]
  Prada 완결 → Chanel notification 아웃박스(delivered=false)
     → Gucci DeliveryService(3s 폴링) → institution_endpoint 콜백 URL로 pacs.002 POST
        → 2xx ACK: delivered=true / 실패: attempts++ 재시도(max 5)
```
- 감사로그(인증·허용/거부·송부)는 ELK(service=gucci)로 수집.
- 헬스체크 `GET /gucci/health/centers`(관측). 다센터 정족수/펜싱·GSLB 라우팅은 G3(고사양 PC 이후).

---

## 7. 확장 워크플로우 (다센터 A-A-A, 향후)

```
                    ┌── DC1 (Chanel/Dior/Hermes/Prada + PostgreSQL rtgs_dc1)
[단일 Sequencer] ──저널(Kafka 공유)──┼── DC2 (동일 서비스 + rtgs_dc2)
                    └── DC3 (동일 서비스 + rtgs_dc3)
   · 컨슈머 그룹 센터별 분리(hermes-DC1/DC2/DC3) · 센터별 DB · 포트 오프셋
   · 정족수 2/3 자동전환 · 3센터 데이터 동일성 대사로 검증(개요 "3센터 동일순서 동일업무")
```
*필요 작업·자원은 개발일지 백로그 참조. 고사양 PC 이관 후 수월.*
