데이터베이스 교과목 팀 프로젝트 · 2인 (Doo-Lee)

사망자 명의 금융거래
신속차단 시스템 데이터베이스

금융위원회가 2026년 9월 11일 시행한 제도를 은행 시스템 구조대로 MySQL에 설계했다. "사망신고 다음 날부터 입금 등 필수 거래를 제외한 모든 거래를 차단한다"는 정책을 애플리케이션 코드가 아니라 제약조건과 테이블로 표현하는 것이 이 설계의 목표다.

MySQL 8.0 5 schemas Java 17 / JDBC HikariCP InnoDB
30테이블
321컬럼
68외래키
42CHECK
17UNIQUE
24코드그룹
88코드값

산출물

브라우저에서 바로 열립니다

Interactive

운영 콘솔 시뮬레이터

거래를 전송하면 계정계·채널계·정보계를 오가며 실행되는 SQL이 9단계로 재생된다. 상단의 시스템 일시를 바꿔 차단개시 경계값(신고일 23:59:59 vs 다음날 00:00:00)을 직접 확인할 수 있고, FOR UPDATE를 끈 상태로 동시 출금을 돌려 갱신 손실을 재현해 볼 수 있다. DB 없이 동작한다.

처리 파이프라인DB 상태 뷰어 사망정보 수신 배치동시성 실험실 용어 12개
열기 →
Slides

발표 자료

31장. 용어 팝업 65개와 전체 ERD 탐색기가 들어 있다. 테이블을 클릭하면 각 컬럼이 왜 존재하는지, 외래키가 어디서 왔는지 확인할 수 있다.

E 키 → ERD 탐색기
열기 →
Report

락 · 데드락 실습 보고서

터미널 4개로 재현한 결과. 외래키 INSERT가 부모 행에 공유 락을 걸어 ERROR 1213이 나는 경로와, FOR UPDATE로 막는 과정을 단계별로 담았다.

데드락갱신 손실MVCC
열기 →
Diagram

전체 ERD

5개 스키마 30개 테이블과 관계선 전체. 계정계만 따로 본 핵심 ERD도 있다.

이미지 보기 →
Document

설계 의사결정 보고서

왜 그렇게 설계했는지를 8개 항목으로 정리했다. 복합 외래키, 이력 관리, 의도적 반정규화, 파티셔닝을 포기한 이유까지.

GitHub에서 보기 →
Code

Java 구현 가이드

JDBC + HikariCP로 판정 로직을 구현한 콘솔 애플리케이션. 계층 구조, 예외 설계, 트랜잭션과 데드락 재시도를 다룬다.

repository / service예외 3계층 커넥션 풀
GitHub에서 보기 →

스키마 구성

은행 시스템의 계층 구분을 데이터베이스 경계로 옮겼다

계정계
core_bank

고객·계좌·거래원장·사망차단·차단규칙. 돈이 실제로 움직이는 곳이다.

15 tables
대외계
ext_link

행정안전부 사망자 정보 파일 수신과 고객 매칭. 주민번호는 해시로만 맞춘다.

3 tables
채널계
channel

창구·ATM·앱에서 들어온 요청과 판정 결과, 응답. 거절된 요청도 남는다.

3 tables
정보계
info_mart

사망정보 조회 감사기록과 집계. 개인식별정보를 보관하지 않는다.

4 tables
공통
comm_code

코드값·응답코드·기관코드·영업일. 모든 스키마가 여기를 참조한다.

5 tables

설계에서 가장 공들인 지점

자세한 근거는 설계 의사결정 보고서에

01
차단개시일시를 애플리케이션이 계산하지 않는다

CHECK (block_start_dtm = TIMESTAMP(DATE_ADD(death_report_dt, INTERVAL 1 DAY))) 로 DB가 보장한다. 자바에서 한 번 더 계산하면 두 곳이 언젠가 어긋난다.

02
정책을 if문이 아니라 테이블 행으로

거래유형별 허용·차단을 block_rule이 보관하고 apply_from_dt ~ apply_to_dt로 버전을 관리한다. 정책이 바뀌어도 과거 거래는 그때의 규칙으로 판정된다.

03
코드값이 올바른 그룹의 코드인지까지 검사

생성 컬럼(GENERATED ALWAYS AS ('CUST_ST') STORED)을 만들어 (그룹, 코드) 복합 외래키를 건다. 존재하지 않는 코드도, 다른 그룹의 코드도 들어오지 못한다. 이런 컬럼이 35개다.

04
주민등록번호 평문을 저장하지 않는다

검색용 rrn_hash CHAR(64)와 암호문 rrn_enc VARBINARY(128)만 둔다. 해시 형식도 CHECK (rrn_hash REGEXP '^[0-9a-f]{64}$')로 강제한다.

05
파티셔닝을 포기하고 참조 무결성을 택했다

InnoDB는 파티션과 외래키를 함께 쓸 수 없다(ERROR 1506). 금융 데이터에서는 무결성이 먼저라고 보고, 대신 아카이브 테이블로 분리하는 방식을 택했다.

06
거절된 거래도 흔적을 남긴다

계정계 트랜잭션이 ROLLBACK되어도 채널계 로그는 남아야 한다. 그래서 업무 트랜잭션과 로그 트랜잭션을 분리했다.