Initialize RTGS prototype repository

3센터 A-A-A RTGS 실시간총액결제 프로토타입 최초 버전관리 시작.
- backend: Kotlin/Gradle 멀티모듈(sequencer, common, 채널/센터 모듈)
- frontend: Vite + TS
- infra: docker-compose, prometheus/grafana, ELK 네이티브 스크립트
- loadtest(k6), sim(장애/순서/정합성 시나리오), docs(PoC 보고서/복원력방안)
This commit is contained in:
rtgs
2026-07-15 15:37:32 +09:00
commit 58ca23b5d9
140 changed files with 11832 additions and 0 deletions

View File

@@ -0,0 +1,234 @@
# RTGS 프로토타입 개발일지
> 대상: 한국은행 소액RTGS(실시간총액결제) 프로토타입 — 로컬(포터블 Windows) 자체 개발
> 목적: 클라우드 PoC(1~3차)에서 검증한 아키텍처의 **업무기능을 로컬에서 완결 개발·테스트**
> 작성: 루비 · 담당: 양팀장님(한국은행 RTGS시스템팀)
> 위치: `C:\ai-dev\workspace\rtgs`
---
## 0. 한눈에 보기
| 구분 | 내용 |
|---|---|
| 기술 스택 | Kotlin 2.0.20 · Spring Boot 3.3.4 · JDK 21(Temurin) · Gradle 8.10.2 |
| 아키텍처 | 전역 순번기(Sequencer) + 저널 순차처리 + 강한 일관성 원장(PostgreSQL) · N센터 확장형 |
| 서비스(6) | Sequencer · Chanel(전문송수신) · Dior(접수동기화) · Hermes(결제/원장엔진) · Prada(결과동기화) · LouisVuitton(관리자) |
| 인프라 | **네이티브 포터블**(Docker 아님): Kafka(KRaft) · PostgreSQL · Elasticsearch/Logstash/Kibana |
| 전문 | ISO20022 pacs.008(요청)/pacs.002(응답), BMI 22자리 식별자 |
| 상태머신 | RCVD→ACTC→PDNG→ACSP→ACCC (실패 RJCT) |
---
## 1. 일자별 상세 내역
### 📅 2026-07-08 (1일차) — 분석 · 설계 · 개발환경 · 골격 개발
**분석**
- 워크스페이스 현황 파악(acs 기존 프로젝트, rtgs는 docs만 있는 빈 폴더)
- 설계 자료 정독: PoC 1·2·3차 결과보고 PDF, "RTGS ActiveActive 복원력방안"(과제⑧ v2.0), 리뷰어/저자 의견, 프로젝트 개요
- acs와 **포트/compose 비충돌** 원칙 확인
**설계 결정**
- 언어 Kotlin, 로컬 인프라 실물 경량 스택, 센터는 1센터 시작·N센터 확장 구조
- 복원력방안 반영: **전역 순번기 / 원장=RDB(PostgreSQL) 강한 일관성 / 정족수 / 저널 결정론적 재생 / 선저널 / 완결 규율**
- 원장은 RDB, 인메모리(Hazelcast)는 코어 연산, 문서형(MongoDB)은 원전문/조회사본으로 역할 분리(설계)
**설치 (포터블, `C:\ai-dev\apps`)**
- **JDK 21 (Temurin 21.0.11)** — Gradle 8.10.2가 JDK26 미지원이라 별도 설치. `env.cmd``JDK21_HOME` 추가(전역 JAVA_HOME은 jdk-26 유지)
- **Gradle 8.10.2** — `GRADLE_HOME` 추가, 캐시는 `home\gradle`
**개발 (backend 멀티모듈)**
- Gradle Kotlin DSL 멀티모듈 구성(common/sequencer/chanel/dior/hermes/prada) + Gradle Wrapper 생성
- **common 모듈**: `TxSts`(상태머신), `CoreMessage`(경량명령문+SHA-256), `JournalEntry`(전역순번+결정론적값), `BmiGenerator`(22자리), `QuorumContext`(정족수), ISO20022 DTO(Pacs008/Pacs002)+코덱, `XmlValidator`(XSD), 토픽/맵/테이블 상수 → **빌드·단위테스트 통과**
- **5개 서비스** 구현(Sequencer 순번부여·저널발행, Chanel 접수·검증·경량화·응답, Dior 접수동기화, Hermes 순차소비·선저널·이체·결과발행, Prada 완결) → **빌드 성공**
- infra: `docker-compose.yml`(초안, Kafka/PostgreSQL/MongoDB) + `postgres-init.sql`(참가기관 19개 시드)
- loadtest: `pacs008.k6.js`(정상/스파이크), 샘플 전문
- 실행 스크립트(run-dc1/stop-dc1), React(Vite) 프론트엔드 스캐폴드
- ※ 일 사용한도 초과로 `kotlin("plugin.jpa")` 적용 직후 중단
### 📅 2026-07-09 (2일차) — 통합 · 인프라 전환 · 검증 · 고도화
**환경 이슈 해결**
- IDE(VS Code Java확장)가 JDK26으로 import 실패 → `gradle.properties``org.gradle.java.home=jdk-21` 고정, `.vscode/settings.json` 지정, wrapper 8.10.2 복원
- `kotlin("plugin.jpa")`를 common에 적용(JPA 엔티티 open/no-arg) → **전체 빌드 성공**
- 사내 EDR 파일락으로 Gradle 캐시 이동 실패 → **재시도**로 통과(Maven/git과 동일 계열)
**Docker → 네이티브 전환 (중대 전환점)**
- Docker Desktop 실행 시 **"Virtualization support not detected"** — 회사 PC의 CPU 가상화 차단(BIOS/정책). Docker(WSL2) 사용 불가 판정
- **Docker 대신 네이티브 포터블 인프라로 전환**(이 PC의 포터블 철학에 오히려 부합):
- **Kafka 3.8.1**(KRaft 단일노드, :9092) 설치·기동. Windows bat의 `wmic`(제거됨) 호출 실패 → `KAFKA_HEAP_OPTS` 사전 설정으로 우회
- **PostgreSQL 16.4**(바이너리, :5433) initdb·기동, DB `rtgs` + 스키마/시드
- **MongoDB 7.0.14** 설치했으나 **WiredTiger 체크포인트가 EDR 파일락에 걸려 반복 크래시(exit 14)** → 원전문/조회사본 저장을 **PostgreSQL로 이전**(raw_message/settlement_view). MongoDB는 미사용
**E2E 검증 성공**
- 비웹 서비스 ObjectMapper 빈 누락(spring-web 부재) 수정 → 5서비스 기동
- pacs.008 1건(1001→1002 150원): 접수 RCVD → **최종 ACCC**, 송신 150/수신 +150, transfer·journal_log·settlement_view·raw_message 전 계층 대사 일치, **19계좌 총액 190억 보존(이중지급 0)**
**ELK 로그관리 구축**
- Elasticsearch 8.15.2 설치·기동 → **EDR 환경 생존 검증 통과**(Lucene은 WiredTiger보다 견고)
- Kibana 8.15.2, Logstash 8.15.2 설치. 서비스 공통 `logback-spring.xml`(logstash-logback-encoder, TCP :5000) → Logstash → ES `rtgs-logs-*` → Kibana. 5개 서비스 로그 수집 확인
**k6 부하테스트 + 버그 2건 발견·수정**
- k6 0.56.0 설치, 30 rps×15초 부하
- **버그① ACSP 잔류 레이스**: Hermes가 결과를 트랜잭션 커밋 *전* 발행 → Prada가 커밋 전 읽음 → **커밋 후 발행(publish-after-commit)** 으로 수정
- **버그② 중복키 ERROR**: Dior/Hermes가 원장 같은 행 동시 INSERT → **원자적 upsert(ON CONFLICT)** 로 수정, 기존 ERROR 로그 정리
**프론트엔드 개선**
- **자금이체 신청 폼**(송신/수신 드롭다운·금액→RCVD→ACCC 자동조회·잔액갱신)
- 거래조회 **한글 항목명**(DB 컬럼 코멘트=데이터 사전 기반) · 상태 한글값 · 시각 `YYYYMMDDHH24MISS` · **원문 pacs.008** 표시
**관리자(LouisVuitton) 서비스 신규** (3차 PoC 미구현분)
- `louisvuitton` 서비스(:8099) + 콘솔 "🛠 관리자" 탭
- 기능: **DB 초기화**, **코드(참가기관) 관리**, **사용자 권한 관리**(app_user, ADMIN/ORG_S/ORG_R — 로그인 강제는 후속), **대사 대시보드**(서비스별 처리 현황)
**개인화**
- 어시스턴트 이름 "루비"(Louis Vuitton 줄임), 사용자 호칭 "양팀장님" — 메모리 저장
### 📅 2026-07-10 (3일차) — 세션 재개 · 문서화 · 고도화(순번영속화·정식ISO·검증하니스)
- 세션 종료 후에도 **네이티브 프로세스 전부 생존** 확인(인프라·5+1 서비스), 데이터(거래·총액 190억) 보존. **프론트엔드(Vite)만 재기동**
- 개발 문서 3종 작성: **개발일지 / 워크플로우 / 테스트 시나리오 갱신**
**고도화 ① Sequencer 전역순번 영속화 (2-1, 정합성 개선)**
- 문제: 순번기 카운터가 인메모리라 재기동 시 1로 리셋 → journal_log(global_seq PK) 충돌/스테일
- 해결: 기동 시 `@PostConstruct`에서 원장의 `MAX(global_seq)`(journal_log·transfer) 조회 → 그 다음부터 발번(high-water mark 복원). sequencer에 JDBC(:5433) 추가
- 검증: 재기동 후 실제 이체가 **globalSeq=943**(복원 max 942의 다음)으로 처리 — 리셋 없음 확인
**고도화 ② 정식 ISO20022 XSD 적용 (2-2, 실제 전문 검증)**
- iso20022.org 공식 XSD 도입: **pacs.008.001.08**(접수)·**pacs.002.001.10**(결과통보) → `common/resources/iso20022/xsd/`
- 전문 모델을 실제 구조로 전환: `Document/FIToFICstmrCdtTrf`(GrpHdr: MsgId/CreDtTm/NbOfTxs/SttlmInf=CLRG, CdtTrfTxInf: PmtId/EndToEndId·IntrBkSttlmAmt@Ccy·ChrgBr=SLEV·Dbtr/DbtrAcct/DbtrAgt(ClrSysMmbId/MmbId)·CdtrAgt·Cdtr/CdtrAcct)
- 파서를 **DOM 방식**(지역명 기준·네임스페이스 견고·XXE 차단)으로 재작성, pacs.002 응답은 정식 네임스페이스 템플릿 생성
- 샘플 5종·프론트 신청폼 XML·공통 테스트 전면 정합. 검증: 공식 XSD로 정상 4건 통과, `badformat`(ChrgBr=ZZZZ) → `cvc-enumeration-valid` 반려
- 적용: sequencer·chanel 재빌드·재기동(나머지 4서비스는 CoreMessage/JournalEntry 불변이라 무중단)
**고도화 ③ 검증 하니스 sim/ (S1/S2/S4)**
- `sim/`(Git Bash): `s1_consistency`(정합성)·`s2_failover`(무손실 승계)·`s4_order`(순서 재정렬)·`reconcile.sql`·`lib.sh`·`README.md`
- **결과 전건 PASS**: S1(20건 총액보존·원장=사본), S2(30건 투입 중 Hermes 강제종료·재기동, 유실 0), S4(seq 965→966→964 역전주입 → 964,965,966 순서기록·전건 ACCC)
**고도화 ④ 결과통보(이체결과 송부) Chanel 이관**
- Gucci 후보 기능 검토 결과, "이체신청기관앞 이체결과 송부"는 Chanel 헌장(접수+통보)에 맞아 **Chanel로 이관**
- 신규 토픽 `rtgs.notify`: **Prada**가 완결(ACCC/RJCT) 후 발행(publish-after-commit) → **Chanel**이 소비
- Chanel: 접수센터(originCenter)만 최종 pacs.002 생성 → **신청기관(송신) 결과통보**(항상)·**수취기관 입금통보**(ACCC만) → `notification` 아웃박스 기록. 조회 API `/notifications`, `/notifications/{bmi}`
- 검증: ACCC(1003→1008)=APPLICANT+BENEFICIARY 2건, RJCT(9990 미등록)=APPLICANT 1건(사유 포함) 확인
- Gucci 잔여 범위(관문/인증/헬스체크 등)는 요건 정의 후 착수
**고도화 ⑤ Gucci(외부 경계 관문) 신규 — 로컬 단계 G1·G2**
- 6개 후보 기능 검토 후 **관문 계층으로 한정**(순서결정=Sequencer, 통보=Chanel로 이미 분담). 신규 `backend/gucci`(:8095)
- **G1 인증 관문**: 로그인(app_user.secret 대조) → **JWT(HS256 자체구현)** 발급 · 인증된 리버스프록시(→Chanel) · 가드[JWT검증·역할·**기관바인딩**(토큰org=전문송신)·**유량제어**(50/10s)·**재전송차단**(nonce+timestamp)] · 감사로그(ELK) · 헬스체크
- **G2 결과 콜백송부(전달보장)**: Chanel 아웃박스(delivered=false) → Gucci `DeliveryService`(3s 폴링)가 `institution_endpoint` 콜백으로 pacs.002 POST → 2xx ACK시 확정, 실패시 재시도(max5). 데모 sink + 레지스트리 관리(admin)
- 검증: curl E2E(로그인/정상pay/무토큰401/기관불일치403/재전송400/관리자accounts/변조401) + 가드 단위테스트 통과. G2: 등록기관 즉시송부·미등록 재시도→등록→송부성공 확인
- app_user.secret·notification.attempts·institution_endpoint 스키마 추가, run-dc1.cmd에 Gucci 기동 추가 → **7개 서비스 아키텍처 완성**
- (남은 것) 프론트 Gucci 경유 로그인 UI(선택), G3(센터간 헬스/펜싱/GSLB)=다센터 단계
**보안 강화 A2 — 비밀키 BCrypt 해시**
- `app_user.secret` 평문 → **BCrypt+솔트 해시** 저장. Gucci `AuthService``PasswordEncoder.matches`로 대조
- `SecretMigrator`(ApplicationRunner): 기동 시 평문(비 BCrypt) 시크릿을 자동 해시 승격(멱등). spring-security-crypto 도입
- 검증: DB secret `$2a$10$…`(60자), 원 시크릿 로그인 200·오답 401
**A4 — Flyway 스키마 형상관리 도입**
- 수기 SQL/ALTER → **Flyway** 단일 출처. 현재 스키마를 `louisvuitton/.../db/migration/V1__baseline.sql`로 이관, LouisVuitton이 실행
- `baseline-on-migrate`**기존 운영 DB는 baseline(무변경)**, 신규 빈 DB는 V1부터 생성. 인프라 스크립트는 빈 DB만 생성(스키마는 Flyway). 구 `postgres-init.sql`은 legacy 표시
- 검증: `flyway_schema_history`에 baseline(1)+V2 기록, 운영 DB 무변경 확인
**A1 — 관리자 로그인(Gucci JWT 재사용, 옵션1)**
- LouisVuitton `/admin/**`**JWT 인터셉터**(role ADMIN 필수). Gucci 발급 토큰을 동일 서명키로 **검증만** 수행
- Gucci: 로그인 응답에 `mustChangePassword` 추가 + **비밀번호 변경 API**(`/gucci/auth/change-password`)
- **V2 마이그레이션**: `must_change_password` 컬럼 + **테스트관리자 a/1**(ADMIN)
- 프론트: 관리자 탭 **로그인 화면**(a/1) + Bearer 전송 + 초기암호변경 화면 + 로그아웃, vite proxy `/gucci`
- 검증(프론트 프록시 경유): a/1→ADMIN 로그인, `/admin/summary` 토큰有 200·無 401, ORG_S 401, 비번변경 왕복(1→12→1)
**Gucci 요건 검토(설계 방향 합의)**
- 양팀장님 제시 6개 후보 기능을 **경계 관문 계층으로 재배치**: ①헬스체크=관측만(페일오버는 정족수+펜싱) ②센터간MQ=Kafka가 이미 담당(Gucci는 외부관문) ③기관로그인=Gucci인증+LouisVuitton권한마스터 ④API인증=JWT+서명/nonce/timestamp ⑤"API순서지정"=라우팅/유량제어(전역순번은 Sequencer 단독) ⑥이체결과송부=**Chanel 이관**
- 원칙 합의: **순서=Sequencer(리더선출)/분산=GSLB·Gucci(무상태)**. 로컬 단계 G1(인증관문)/G2(콜백송부)/G3(센터간)
**작업 분담 (양팀장님 지시)**
- **ACS 프로젝트의 개선·서버배포는 Codex에게 일임**, 루비는 **RTGS 전담**. 동일 workspace 병렬작업 → 포트 이미 분리(ACS 8080/5173/5432 ↔ RTGS 8090~8095/5174/5433), 공유 `env.cmd`·Gradle 캐시는 RTGS 관련만 수정, cold 빌드 순차
**문서 산출물 관리 체계 수립**
- **아키텍처 설계서** 신규 작성(`RTGS 아키텍처 설계서.md`) — OS-WAS-DB 스택 매트릭스 포함(Win11/JDK21.0.11/SpringBoot3.3.4 내장Tomcat/PostgreSQL16.4/Kafka3.8.1/ELK8.15.2/React18+Vite5+Node26/k6). **Mermaid 다이어그램**(컴포넌트·배포·상태·시퀀스) + 팀장님 참고 PNG(2센터흐름도·서비스png) 임베드
- **문서 운영방침**(양팀장님): 개발 중 `.md` → 완성 시 **PPT/PDF**(HWP 불필요). pandoc 확인(pptx 직접·pdf는 Edge인쇄), `docs/tools/convert.cmd` 작성. 다이어그램=Mermaid+참고PNG, UML.xlsx는 필요 시 추출
- **SW 산출물 관리대장**(`SW 산출물 관리대장.md`) 신규 — 과거 PoC의 코드-문서 드리프트 재발 방지. **단일 출처 원칙**(포트=run-dc1/yml·토픽=Constants·스키마=Flyway·데이터사전=DB COMMENT·API=Controller·전문=XSD), 변경유형→갱신문서 체크리스트, 정합성 점검 항목
**개선점 진단(루비 관점) → 우선순위 논의**
- A(즉시): A1 관리자무인증·A2 평문시크릿·A3 관문우회·A4 수기스키마 / B(운영전): B1 순번기SPOF·B2 정족수하드코딩·B3 head-of-line·B4 관측성·B5 헤드리스헬스·B6 테스트자동화·B7 TLS/암호화 / C(다센터·성능)
- **A1·A2·A4 완료**(위). A3=합의(부하테스트는 Chanel 직접 유지, 운영 전 차단). B군은 아래 결정대로 진행
**B6 — 테스트 실행 화면 (완료)**
- 관리자 콘솔에 **이체 대량생성** 섹션: BMI 시작번호·건수 입력 → 송/수신기관 랜덤·금액 1,000~1,000,000 랜덤, Chanel 직접 호출(관문 우회), 20건 동시배치, 진행/접수/반려 집계. k6 대체 간이도구
- 검증: 프론트 tsc 통과. (프론트 HMR 반영)
**B1/B2/B3 — 3센터 삼중화 방향 확정(설계 논의 중, 구현 예정)**
- 양팀장님 결정: 이전 PoC는 2센터, **이제부터 3센터 기준 삼중화 구조로 전환**
- B1 순번기: **durable-before-publish**(저널을 durable 저장 후 발행, 재기동 시 미발행분 재발행=outbox) + 리더선출·펜싱(에폭)
- B2 정족수: 결정론적 재생이므로 데이터 동기화는 불필요, 단 **완결(응답) 시 과반(2/3) 확정 대기**로 1센터 손실 안전. `confirmations` 하드코딩→센터별 ack 집계로
- B3 head-of-line: 영구 gap의 원인은 B1 유실 → B1 해결 시 소멸. 방어책=gap 타임아웃 시 **journal_log(durable)에서 결번 직접 pull**(skip 아님)
**B4 관측성(메트릭) + B5 서비스 헬스 (완료)**
- **B4**: 전 서비스 Micrometer + `/actuator/prometheus` 노출. 헤드리스 4종(Sequencer/Dior/Hermes/Prada)에 starter-web 추가→예약포트(8090/8092/8093/8094)에 actuator만 노출. 업무 메트릭: `rtgs.settlements`(status)·`rtgs.settle`(Timer)·`rtgs.journal.gap`(Hermes), `rtgs.finality`(status, Prada), 접수 TPS/지연=`http_server_requests`(Chanel), Kafka lag 자동. (Prometheus 서버/Grafana는 후속)
- **B5**: `common.ops.HeartbeatAutoConfiguration`(스프링 자동설정, `@AutoConfigureAfter` DataSource) → 전 서비스가 `service_heartbeat`(Flyway V3)에 주기 기록. LouisVuitton `/admin/health` + 관리자 대시보드 **🩺 서비스 상태**(UP/STALE, 헤드리스 포함). micrometer-registry-prometheus는 common으로 전파
- 검증: 7서비스 `/actuator/prometheus` 200, 하트비트 7건, 이체1건 후 settlements/finality/http 메트릭 증가, /admin/health 7 UP
- (교훈) 자동설정 `@ConditionalOnSingleCandidate(DataSource)``@AutoConfigureAfter(DataSourceAutoConfiguration)` 없으면 순서상 미적용. 헤드리스→web 전환으로 기동 ~13s(정상)
**B4 Prometheus 서버 설치 (완료)**
- 포터블 **Prometheus 3.13.0**(`apps\prometheus-3.13.0`, 데이터 `home\prometheus-data`, :9090) 설치. `infra\prometheus.yml`(7서비스 스크랩·5s)·`infra\start-prometheus.cmd`
- 검증: **7/7 타깃 up**, PromQL `rtgs_finality_total{status="ACCC"}` 조회 성공. README apps 표 등록
- (교훈) `start "title" cmd /k ""exe" args"` 중첩따옴표는 배치에서 실패 → `start "title" "exe" args` 형태로
**B4 Grafana 시각화 (완료)**
- 포터블 **Grafana 13.1.0**(`apps\grafana-13.1.0`, 데이터 `home\grafana-data`, :3000, 익명 Admin). `infra\start-grafana.cmd` + 프로비저닝(`infra\grafana\provisioning`: Prometheus 데이터소스 rtgs-prom + "RTGS Overview" 대시보드)
- 대시보드 패널: 접수 TPS/지연(p95)·정산 처리율/지연·Kafka consumer lag·JVM heap·완결 누계. 검증: 데이터소스·대시보드 프로비저닝 확인
- **관측성(B4/B5) 완료** — 로그(ELK)+메트릭(Prometheus/Grafana)+헬스(하트비트)
- (다음) **B1/B2/B3 3센터 삼중화**(durable-before-publish·정족수·gap pull) → **B7 암복호화+TLS**. C(다센터 실측)·성능은 **7/13(월) 고사양 PC 이관 후**(터미널 3개로 DC1~DC3 병렬 실측). D: pacs.7z를 전문 보강(BAH/pacs.002 검증) 착수 시 참조
---
## 2. 주요 의사결정·전환점 요약
| 결정/전환 | 이유 |
|---|---|
| JDK21 별도 설치 | Gradle 8.10.2가 JDK26 미지원 |
| **Docker → 네이티브 포터블** | 회사 PC CPU 가상화 차단(스펙 아닌 BIOS/정책). 포터블 철학과 부합 |
| **MongoDB → PostgreSQL** | MongoDB WiredTiger가 EDR 파일락에 크래시. 문서저장을 RDB로 대체(클라우드는 문서형 유지) |
| 원장 = RDB 강한 일관성 | 복원력방안 원칙(이중지급 방지엔 단일순번+강한일관성) |
| publish-after-commit | 결과발행을 커밋 후로 → Prada 완결 레이스 제거 |
| 원자적 upsert(ON CONFLICT) | Dior/Hermes 동시삽입 중복키 제거 |
| 정식 ISO20022 공식 XSD | 실제 전문 검증(pacs.008.001.08/002.001.10) |
| 결과통보 = Chanel | Chanel 헌장(접수+통보)에 부합 |
| Gucci = 외부 경계 관문만 | 순서=Sequencer, 분산=Gucci(무상태) 역할 분리 |
| **Flyway 스키마 형상관리** | 수기 SQL 드리프트 방지(코드-문서 정합성) |
| 관리자 로그인(JWT/BCrypt) | 관리자 무인증·평문시크릿 급소 제거 |
| **ACS=Codex / RTGS=루비** | 병렬 개발 분담(양팀장님 지시) |
| 문서: md→PPT/PDF, 다이어그램 Mermaid+PNG | 개발중 관리 용이, 완성시 정식 산출물 |
| **3센터 삼중화 전환** | 이전 PoC는 2센터, 본 개발은 3센터 A-A-A 기준 |
---
## 3. 현재 산출물
- **backend/**(Gradle 멀티모듈, **7서비스**): common + sequencer/chanel/dior/hermes/prada/**gucci**/louisvuitton
- **frontend/**(React+Vite): 운영 콘솔(이체신청·조회·계좌) + 관리자 탭(로그인·대사·초기화·코드·사용자·**테스트 실행**)
- **infra/**: 네이티브 기동 스크립트(start-infra-native[빈DB만 생성]·start-elk-native), init/postgres-init.sql(**legacy**), (참고용) docker-compose
- **DB 스키마**: **Flyway** `louisvuitton/.../db/migration/`(V1__baseline, V2__admin_login)
- **loadtest/**: k6, **sim/**: S1/S2/S4 하니스, **iso20022/**: 공식 XSD·샘플 5종
- **docs/**: 개요·보고서·개발일지·워크플로우·테스트시나리오·**아키텍처 설계서**·**SW 산출물 관리대장**·참고(2센터흐름도·서비스png·UML.xlsx)·tools/convert.cmd
- 포터블 앱: `C:\ai-dev\apps`(jdk-21, gradle, kafka, postgresql, elk, k6, nodejs 등)
## 4. 남은 과제 (백로그)
**완료(2026-07-10)**: ✅순번 영속화 ✅정식 ISO20022 XSD ✅sim S1/S2/S4 ✅결과통보 Chanel이관 ✅Gucci G1/G2(인증관문·콜백) ✅A2 BCrypt ✅A4 Flyway ✅A1 관리자로그인 ✅B6 테스트화면 ✅아키텍처설계서·관리대장 ✅**B4 메트릭(Micrometer/Prometheus 노출)** ✅**B5 서비스 헬스(하트비트 대시보드)** ✅**B4 Prometheus 서버(:9090)**
**진행/예정**:
- **B1/B2/B3 3센터 삼중화** — *설계 확정 + **코드 구현·빌드·단위테스트 완료(2026-07-13, 8코어 PC)***:
- **B1**: `V4__seq_outbox.sql`(SEQUENCE `global_seq_seq` + `journal_outbox`), `SequencerService` durable-before-publish + 재발행 스케줄러(@EnableScheduling). 순번기 전역 단일 리더(그룹 `sequencer`).
- **B2**: `prada/QuorumAggregator`(신규, 단위테스트 6) — `rtgs.result`=applied-ack 재활용(별도 토픽 불필요), `processedCenter` 집계 과반(2/3) → ACCC. origin Prada만 통보.
- **B3**: `hermes/GapBuffer`(신규, 단위테스트 6) + 타임아웃 스케줄러 → 단일파티션 근거 phantom skip, `rtgs.journal.gap.timeout` 지표.
- **설정공통화**: 원장/엣지 groupId 센터접미사 파라미터화(`hermes-${center-id}`…), 순번기만 단일그룹.
- **이관 산출물**: `run-dc2/dc3.cmd`, `infra/init-3centers-db.cmd`, `run-dc1.cmd`(3센터 모드), `docs/RTGS 3센터 이관·기동 체크리스트.md`.
- **남은 것**: 전체 3센터 21 JVM 기동·재해/복구 시나리오·성능 실측 = **고사양 PC 이관 후**(팀장님 테스트).
- **B4 관측성**: Micrometer + Prometheus(TPS/지연/consumer lag)
- **B5 헤드리스 헬스**: LouisVuitton 대시보드에 서비스 하트비트(DB)
- **B7 전문 암복호화 + TLS**: 기관 수신 ISO전문 복호화→처리, 통보 암호화 송부(성능테스트에 암복호화 포함)
- **다센터(DC2/DC3) 실행·S3/S5**: 고사양 PC 이관 후
- 프론트 Gucci 경유 로그인 UI(선택), Logstash 힙 256m, PC 백업/이관 체크리스트(다음주)
*본 일지는 개발 진행에 따라 계속 갱신.*