외화자산관리시스템개발

19 minute read




외화 자산 관리 시스템

1. 기능정의

1-1. Must Have (핵심 MVP)

1) 사용자별 외화 지갑 (통화별 잔액 관리)

  • 개발 포인트
    • 사용자 계정 1명 기준 (멀티 유저 구조는 설계만)
    • 통화는 ISO 코드 기반 (USD, JPY, EUR 등)
  • 세부 기능
    • 통화 지갑 생성
    • 환전 기능
    • 통화별 잔액 조회
    • 잔액 증감 처리
    • 수동 입금 / 출금
    • 거래 사유 메모
    • 잔액 검증
    • 출금 시 잔액 부족 방지
  • 데이터
    • Wallet
    • WalletTransaction

      2) 한국수출입은행 환율정보 외부 API 연동

  • 개발 포인트
    • 외부 API → 내부 DTO 변환
    • 캐싱 필수 (API 남용 방지)
  • 세부 기능
    • 오늘 기준 환율 조회
    • 통화별 매매기준율 저장
    • API 실패 시 예외 처리
    • 최근 스냅샷 있으면 fallback

      3) 기준 통화(KRW/USD) 자산 환산

  • 개발 포인트
    • 계산 로직 정확성 + 소수점 처리
  • 세부 기능
    • 기준통화 선택 (KRW / USD)
    • 전체 자산 합계 계산
    • 통화별 환산 금액 반환

1-2. Should Have

1) 환율 스냅샷 저장 (히스토리)

  • 개발 포인트
    • “하루 1회” 기준으로 단순화
  • 세부 기능
    • 일자별 환율 스냅샷 저장
    • 통화별 환율 조회 (날짜 기준)
    • 스냅샷 중복 저장 방지
  • 데이터
    • ExchangeRateSnapshot
    • 기준일
    • 통화
    • 환율

      2) 환율 변동에 따른 손익(P/L) 추적

  • 개발 포인트
    • 실현 손익 ❌
    • 평가 손익(valuation P/L) 만 계산
  • 세부 기능
    • 기준일 대비 현재 자산 가치 차이 계산
    • 통화별 P/L
    • 전체 P/L 합계
    • 증감률(%) 계산

1-3. Could-Have

1) AI 요약 리포트 (LLM API 기반)

  • 입력 데이터
    • 최근 7일 or 14일 환율 스냅샷
    • 통화별 변동률
    • 사용자 보유 비중
  • 기능 분해
    • 환율 변화 요약 : “최근 7일간 USD/KRW는 +1.8% 상승”
    • 변동 원인 템플릿 요약 : (고정 문구 + 데이터 삽입) (예: 글로벌 금리, 달러 강세 등)
    • 사용자 자산 영향 설명 : “현재 포트폴리오에 긍정적/중립적”
    • 예측처럼 보이지만 예측 아님 (오를 것이다가 아닌 변동성이 유지되고 있다 는 정도로 표현)

2. 개발 일정표

  • 기간: 2026/01/26(월) ~ 2026/02/23(월) 4주
  • 평일: 월·화·수·목 → 2시간
  • 주말: 토요일,일요일 → 10시간

    주차별 목표

주차 기간 주차 목표
1주차 1/26 ~ 1/31 기획·설계·환경 세팅 완료
2주차 2/2 ~ 2/7 Must Have 전부 구현
→ 외화 지갑 + 환율 + 자산 환산
3주차 2/9 ~ 2/14 Should Have 구현
→ 환율 히스토리 + 손익(P/L)
4주차 2/16 ~ 2/23 Could Have + 완성도
→ AI 요약 리포트 + 포트폴리오

1주차 : 기획·설계·환경 세팅 완료

날짜 요일 시간 일정
1/26 2h 프로젝트 목표 정의
기능 범위 확정(Must/Should/Could)
1/27 2h 전체 아키텍처 설계
(레이어 구조 / 책임 분리)
1/28 2h ERD 설계(핵심 엔티티 도출)
1/29 2h DB 스키마 확정
인덱스·유니크키 정의
1/31 10h 프로젝트 세팅
• Spring Boot 생성
• 패키지 구조/환경 분리
• 공통 모듈(exception, logging)

2주차 : Must Have 구현

날짜 요일 시간 일정
2/2 2h ERD 설계 보완
2/3 2h API 설계
2/4 2h 유저 api 개발
2/5 2h 지갑서비스 api 개발
2/7 10h 멘토링 및 보완사항 반영

3주차 : Must Have, Should Have 구현

날짜 요일 시간 일정
2/9 2h 한국 수출입은행 환율정보 API 연동 및 개발
2/10 2h 한국 수출입은행 환율정보 API 연동 및 개발
2/11 2h 평가 손익 api 개발
2/12 2h kafka , 쿠버네티스 관련 개념이해 및 공부
2/14 10h 멘토링 및 보완사항 반영 Kafka 연동 및 경험

4주차 : Could Have + 완성도

날짜 요일 시간 일정
2/16 2h AI 리포트 데이터 집계
2/17 2h AI 요약 프롬프트 설계
2/18 2h LLM API 연동
2/19 2h AI 요약 리포트 API
2/21 10h 리팩토링
에러/로그 정리
2/23 2h README 완성
데모 시나리오 정리

3. 기술스택

  • Java 17
  • Spring Boot
  • Spring Data JPA (Hibernate)
  • MySQL 8
  • Flyway (DB 마이그레이션)
  • Validation (Jakarta Validation) : 금액>0, 통화코드, 날짜 범위 같은 입력 검증을 어노테이션으로 깔끔하게 처리.
  • OpenAPI(Swagger) : API 명세 자동화
  • JUnit5 + Spring Boot Test : P/L 계산, 출금 잔액 검증 같은 핵심 로직
  • Docker + Compose
  • Kafka

4. ERD 구조

users

  • 서비스 사용자 기본 정보 테이블
  • 멀티유저 구조를 위한 루트 엔티티로, 지갑·리포트 등 모든 사용자 소유 데이터의 기준이 됨
  • MVP 단계에서는 단일 사용자만 있어도 확장에 문제없음
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 사용자 식별자 1 자동 증가, 양수
email VARCHAR(255) N UQ 로그인/식별용 이메일 user@domain.com 유니크, 공백 불가
name VARCHAR(100) Y   사용자 이름(표시용) 홍길동 길이 제한
created_date DATETIME N   최초등록 일시 2026-01-26 21:10:00 자동 세팅
updated_date DATETIME N   수정 일시 2026-01-27 09:10:00 업데이트 자동

wallets

  • 사용자별 통화 지갑(통화별 잔액) 정보를 저장
  • 사용자당 통화코드(USD, JPY 등) 기준으로 지갑은 1개만 생성 가능
  • 현재 잔액을 빠르게 조회하기 위한 잔액 스냅샷 역할을 겸함
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 지갑 식별자 10 자동 증가
user_id BIGINT UNSIGNED N FK 소유 사용자 id 1 존재하는 users.id
currency_code CHAR(3) N UQ 통화 코드 USD ISO 4217, 3자리 대문자
balance DECIMAL(18,6) N   현재 잔액 1000.000000 0 이상 권장, 음수 허용 여부 정책 필요
created_date DATETIME N   최초등록 일시 2026-01-28 21:00:00 자동
updated_date DATETIME N   수정 일시 2026-01-29 21:00:00 자동

wallet 외화지갑 거래 구조

  • wallet_events: “사용자가 한 번 실행한 행위(입금/출금/환전)” = 이력 1건(헤더)
  • wallet_transactions: 그 행위 때문에 실제로 각 지갑에 찍히는 “원장 라인” = 상세 이력 1~N건
  • 입금: 지갑 1개만 변함 → transactions 1건
  • 출금: 지갑 1개만 변함 → transactions 1건
  • 환전: 지갑 2개가 동시에 변함 → transactions 2건 (from 통화 지갑 DEBIT 1건 + to 통화 지갑 CREDIT 1건)

wallet_events

  • 지갑 변동의 “행위/사건”을 기록하는 테이블
  • 환전, 입금, 출금 등의 행위를 업무단위 한 건으로 표현하기 위함
컬럼명 타입 NULL Key 설명 예시 검증/제약
id BIGINT UNSIGNED N PK 이벤트 ID 5001 AUTO_INCREMENT
user_id BIGINT UNSIGNED N FK/IDX 사용자 ID 1 users.id 존재
type ENUM(‘DEPOSIT’,’WITHDRAW’,’EXCHANGE’) N IDX 이벤트 유형 EXCHANGE enum 제한
external_source VARCHAR(50) Y   외부 출처(은행/수동 등) BANK 길이 제한
memo VARCHAR(255) Y   이벤트 메모(요약) KRW→USD 환전 길이 제한
idempotency_key VARCHAR(64) Y UQ 중복요청 방지 키(권장) req_20260207_001 유니크
occurred_date DATETIME N IDX 발생 시각 2026-02-07 12:00:00 필수
created_date DATETIME N   생성 시각 2026-02-07 12:00:01 DEFAULT
updated_date DATETIME N   수정 시각 2026-02-07 12:00:01 ON UPDATE

wallet_transactions

  • 외화 지갑의 입금/출금/환전 상세 내역을 기록하는 원장 테이블
  • 모든 잔액 변경의 근거 데이터로, 추적·검증·감사에 핵심적인 역할
  • 각 거래마다 balance_after를 저장해 거래 후 잔액 상태를 명확히 유지
컬럼명 타입 NULL Key 설명 예시 검증/제약
id BIGINT UNSIGNED N PK 거래(라인) ID 90001 AUTO_INCREMENT
event_id BIGINT UNSIGNED N FK/IDX 소속 이벤트 ID 5001 wallet_events.id 존재
wallet_id BIGINT UNSIGNED N FK/IDX 대상 지갑 ID 10 wallets.id 존재
direction ENUM(‘CREDIT’,’DEBIT’) N   증감 방향 DEBIT enum 제한
amount DECIMAL(18,6) N   증감 금액 200.000000 > 0
balance_after DECIMAL(18,6) N   거래 후 잔액 1200.000000 계산 결과와 일치
created_date DATETIME N IDX 생성 시각 2026-02-07 12:00:01 DEFAULT
updated_date DATETIME N   수정 시각 2026-02-07 12:00:01 ON UPDATE

exchange_rate_snapshots

  • 환율을 하루 단위로 저장하기 위한 환율 스냅샷 메타 정보(헤더)
  • 기준일, 기준통화, 환율 타입 조합으로 스냅샷을 구분하고 중복 저장을 방지
  • 외부 환율 API를 실제로 조회한 시각을 기록해 데이터 신뢰도를 관리
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 스냅샷 id 1 자동 증가
base_date DATE N UQ 기준일 2026-02-10 날짜 필수
base_currency ENUM(‘KRW’,’USD’) N UQ 기준 통화 KRW KRW/USD만 허용
rate_type ENUM(‘BASE’,’TT_BUY’,’TT_SELL’) N UQ 환율 타입 BASE MVP는 BASE만 사용 권장
source VARCHAR(100) N   제공처 KEXIM 기본값
created_date DATETIME N   최초등록 일시 2026-02-10 09:01:02 자동

exchange_rate_snapshots_detail

  • 특정 환율 스냅샷에 포함된 통화별 환율 상세 데이터
  • 예: 기준통화 KRW 기준으로 USD, JPY, EUR 등의 환율 값 저장
  • 환율 히스토리 조회 및 평가 손익(P/L) 계산의 핵심 데이터 소스
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 아이템 id 10 자동 증가
snapshot_id BIGINT UNSIGNED N FK/UQ 스냅샷 id 1 존재하는 snapshots.id
quote_currency CHAR(3) N UQ 대상 통화 USD ISO 4217 3자리
rate DECIMAL(18,6) N   환율 1300.120000 0 초과
created_date DATETIME N   최초등록 일시 2026-01-28 21:00:00 자동

ai_reports (Optional)

  • AI가 생성한 환율 변동 요약 리포트를 저장하는 테이블
  • 최근 N일간 환율 변화와 사용자 자산 영향에 대한 설명을 기록
  • 계산된 변동률·지표를 함께 저장해 리포트 재사용 및 비교가 가능
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 리포트 id 1 자동 증가
user_id BIGINT UNSIGNED N FK 사용자 id 1 users.id 존재
base_currency ENUM(‘KRW’,’USD’) N   기준 통화 KRW 제한 enum
window_days INT N   분석 구간(일) 7 1~31 권장
from_date DATE N IDX 시작일 2026-02-01 to_date 이하
to_date DATE N IDX 종료일 2026-02-07 from_date 이상
content_md LONGTEXT N   요약 본문(Markdown) ### 요약 ... 공백 불가
metrics_json JSON Y   계산 지표(변동률 등) { "usd_change": 1.2 } JSON 유효
model_name VARCHAR(100) Y   사용 모델 gpt-4.1-mini 선택
created_date DATETIME N   최초등록 일시 2026-02-17 22:10:01 자동

ERD

ERD

5. API 구조

  • services 하위에 Must Have, Should Have , Could Have 등 기능이되는 api 를 나누어 개발
  • libs/common-web/ : 공통 예외처리를 라이브러리화 하여 services에서 사용
  • libs/common-event/ :
  • `libs/common-kafka/ :
my_wallet/
├─ settings.gradle
├─ build.gradle
├─ docker-compose.yml
│
├─ services/                     # 실행 가능한 Spring Boot 애플리케이션
│  │
│  ├─ user-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/user
│  │     ├─ UserServiceApplication.java
│  │     ├─ controller/   # HTTP API 진입점, service 호출
│  │     ├─ service/      # 유스케이스/비즈니스 로직 계층
│  │     ├─ domain/       # 도메인 모델(엔티티) - DB 테이블(users)과 매핑되는 JPA Entity
│  │     ├─ dto/          # API 전용 데이터 구조 (Request-입력, Response-응답)
│  │     ├─ exception/    # 서비스 전용 에러 코드만 보관 - 실제 예외 처리기(Handler)는 common-web에 있음
│  │     └─ repository/   # 데이터 접근 - JPA를 통한 CRUD
│  │
│  ├─ wallet-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/wallet
│  │     ├─ WalletServiceApplication.java
│  │     ├─ controller/           # REST API
│  │     ├─ application/          # 유스케이스 (Command 중심)
│  │     ├─ domain/               # Wallet, WalletEvent, WalletTransaction
│  │     ├─ repository/
│  │     ├─ messaging/
│  │     │  ├─ outbox/             # Outbox 엔티티/퍼블리셔
│  │     │  └─ producer/           # Kafka 이벤트 발행
│  │     └─ config/
│  │
│  ├─ exchange-rate-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/exchange
│  │     ├─ ExchangeRateServiceApplication.java
│  │     ├─ controller/
│  │     ├─ application/
│  │     ├─ domain/               # Snapshot, SnapshotDetail
│  │     ├─ repository/
│  │     ├─ external/             # KEXIM client
│  │     ├─ messaging/
│  │     │  └─ producer/
│  │     └─ config/
│  │
│  ├─ valuation-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/valuation
│  │     ├─ ValuationServiceApplication.java
│  │     ├─ controller/
│  │     ├─ application/
│  │     ├─ domain/               # Portfolio, ValuationResult
│  │     ├─ repository/
│  │     ├─ messaging/
│  │     │  └─ consumer/           # wallet / snapshot 이벤트 구독
│  │     └─ config/
│  │
│  └─ report-service/
│     ├─ build.gradle
│     └─ src/main/java/com/mywallet/report
│        ├─ ReportServiceApplication.java
│        ├─ controller/
│        ├─ application/
│        ├─ domain/               # AiReport
│        ├─ repository/
│        ├─ messaging/
│        │  └─ consumer/
│        └─ config/
│
├─ libs/                          # 공통 라이브러리
│  │
│  ├─ common-web/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/common/web
│  │     ├─ exception/            # GlobalException, ErrorCode
│  │     ├─ response/             # ApiResponse<T>
│  │     └─ validation/           # @PositiveAmount, @CurrencyCode
│  │
│  ├─ common-event/               # ⭐ Kafka/HTTP 공통 "이벤트 계약"
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/common/event
│  │     ├─ wallet/
│  │     │  └─ WalletEventCreated.java
│  │     ├─ exchange/
│  │     │  └─ ExchangeRateSnapshotCreated.java
│  │     └─ BaseEvent.java         # eventId, occurredAt, version
│  │
│  └─ common-kafka/
│     ├─ build.gradle
│     └─ src/main/java/com/mywallet/common/kafka
│        ├─ config/               # Producer/Consumer 공통 설정
│        ├─ serializer/
│        └─ producer/             # KafkaTemplate 헬퍼
│
├─ infra/
│  └─ k8s/                        # ⭐ Kubernetes 매니페스트
│     ├─ base/
│     │  ├─ namespace.yaml
│     │  ├─ configmap.yaml
│     │  └─ secret.yaml
│     │
│     ├─ wallet-service/
│     │  ├─ deployment.yaml
│     │  ├─ service.yaml
│     │  └─ hpa.yaml
│     │
│     ├─ exchange-rate-service/
│     │  ├─ deployment.yaml
│     │  ├─ service.yaml
│     │  └─ cronjob-snapshot.yaml  # 하루 1회 환율 스냅샷
│     │
│     ├─ valuation-service/
│     │  ├─ deployment.yaml
│     │  └─ service.yaml
│     │
│     └─ report-service/
│        ├─ deployment.yaml
│        └─ service.yaml
│
└─ README.md

외화 자산 관리 시스템

1. 기능정의

1-1. Must Have (핵심 MVP)

1) 사용자별 외화 지갑 (통화별 잔액 관리)

  • 개발 포인트
    • 사용자 계정 1명 기준 (멀티 유저 구조는 설계만)
    • 통화는 ISO 코드 기반 (USD, JPY, EUR 등)
  • 세부 기능
    • 통화 지갑 생성
    • 환전 기능
    • 통화별 잔액 조회
    • 잔액 증감 처리
    • 수동 입금 / 출금
    • 거래 사유 메모
    • 잔액 검증
    • 출금 시 잔액 부족 방지
  • 데이터
    • Wallet
    • WalletTransaction

      2) 한국수출입은행 환율정보 외부 API 연동

  • 개발 포인트
    • 외부 API → 내부 DTO 변환
    • 캐싱 필수 (API 남용 방지)
  • 세부 기능
    • 오늘 기준 환율 조회
    • 통화별 매매기준율 저장
    • API 실패 시 예외 처리
    • 최근 스냅샷 있으면 fallback

      3) 기준 통화(KRW/USD) 자산 환산

  • 개발 포인트
    • 계산 로직 정확성 + 소수점 처리
  • 세부 기능
    • 기준통화 선택 (KRW / USD)
    • 전체 자산 합계 계산
    • 통화별 환산 금액 반환

1-2. Should Have

1) 환율 스냅샷 저장 (히스토리)

  • 개발 포인트
    • “하루 1회” 기준으로 단순화
  • 세부 기능
    • 일자별 환율 스냅샷 저장
    • 통화별 환율 조회 (날짜 기준)
    • 스냅샷 중복 저장 방지
  • 데이터
    • ExchangeRateSnapshot
    • 기준일
    • 통화
    • 환율

      2) 환율 변동에 따른 손익(P/L) 추적

  • 개발 포인트
    • 실현 손익 ❌
    • 평가 손익(valuation P/L) 만 계산
  • 세부 기능
    • 기준일 대비 현재 자산 가치 차이 계산
    • 통화별 P/L
    • 전체 P/L 합계
    • 증감률(%) 계산

1-3. Could-Have

1) AI 요약 리포트 (LLM API 기반)

  • 입력 데이터
    • 최근 7일 or 14일 환율 스냅샷
    • 통화별 변동률
    • 사용자 보유 비중
  • 기능 분해
    • 환율 변화 요약 : “최근 7일간 USD/KRW는 +1.8% 상승”
    • 변동 원인 템플릿 요약 : (고정 문구 + 데이터 삽입) (예: 글로벌 금리, 달러 강세 등)
    • 사용자 자산 영향 설명 : “현재 포트폴리오에 긍정적/중립적”
    • 예측처럼 보이지만 예측 아님 (오를 것이다가 아닌 변동성이 유지되고 있다 는 정도로 표현)

2. 개발 일정표

  • 기간: 2026/01/26(월) ~ 2026/02/23(월) 4주
  • 평일: 월·화·수·목 → 2시간
  • 주말: 토요일,일요일 → 10시간

    주차별 목표

주차 기간 주차 목표
1주차 1/26 ~ 1/31 기획·설계·환경 세팅 완료
2주차 2/2 ~ 2/7 Must Have 전부 구현
→ 외화 지갑 + 환율 + 자산 환산
3주차 2/9 ~ 2/14 Should Have 구현
→ 환율 히스토리 + 손익(P/L)
4주차 2/16 ~ 2/23 Could Have + 완성도
→ AI 요약 리포트 + 포트폴리오

1주차 : 기획·설계·환경 세팅 완료

날짜 요일 시간 일정
1/26 2h 프로젝트 목표 정의
기능 범위 확정(Must/Should/Could)
1/27 2h 전체 아키텍처 설계
(레이어 구조 / 책임 분리)
1/28 2h ERD 설계(핵심 엔티티 도출)
1/29 2h DB 스키마 확정
인덱스·유니크키 정의
1/31 10h 프로젝트 세팅
• Spring Boot 생성
• 패키지 구조/환경 분리
• 공통 모듈(exception, logging)

2주차 : Must Have 구현

날짜 요일 시간 일정
2/2 2h ERD 설계 보완
2/3 2h API 설계
2/4 2h 유저 api 개발
2/5 2h 지갑서비스 api 개발
2/7 10h 멘토링 및 보완사항 반영

3주차 : Must Have, Should Have 구현

날짜 요일 시간 일정
2/9 2h 한국 수출입은행 환율정보 API 연동 및 개발
2/10 2h 한국 수출입은행 환율정보 API 연동 및 개발
2/11 2h 평가 손익 api 개발
2/12 2h kafka , 쿠버네티스 관련 개념이해 및 공부
2/14 10h 멘토링 및 보완사항 반영 Kafka 연동 및 경험

4주차 : Could Have + 완성도

날짜 요일 시간 일정
2/16 2h AI 리포트 데이터 집계
2/17 2h AI 요약 프롬프트 설계
2/18 2h LLM API 연동
2/19 2h AI 요약 리포트 API
2/21 10h 리팩토링
에러/로그 정리
2/23 2h README 완성
데모 시나리오 정리

3. 기술스택

  • Java 17
  • Spring Boot
  • Spring Data JPA (Hibernate)
  • MySQL 8
  • Flyway (DB 마이그레이션)
  • Validation (Jakarta Validation) : 금액>0, 통화코드, 날짜 범위 같은 입력 검증을 어노테이션으로 깔끔하게 처리.
  • OpenAPI(Swagger) : API 명세 자동화
  • JUnit5 + Spring Boot Test : P/L 계산, 출금 잔액 검증 같은 핵심 로직
  • Docker + Compose
  • Kafka

4. ERD 구조

users

  • 서비스 사용자 기본 정보 테이블
  • 멀티유저 구조를 위한 루트 엔티티로, 지갑·리포트 등 모든 사용자 소유 데이터의 기준이 됨
  • MVP 단계에서는 단일 사용자만 있어도 확장에 문제없음
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 사용자 식별자 1 자동 증가, 양수
email VARCHAR(255) N UQ 로그인/식별용 이메일 user@domain.com 유니크, 공백 불가
name VARCHAR(100) Y   사용자 이름(표시용) 홍길동 길이 제한
created_date DATETIME N   최초등록 일시 2026-01-26 21:10:00 자동 세팅
updated_date DATETIME N   수정 일시 2026-01-27 09:10:00 업데이트 자동

wallets

  • 사용자별 통화 지갑(통화별 잔액) 정보를 저장
  • 사용자당 통화코드(USD, JPY 등) 기준으로 지갑은 1개만 생성 가능
  • 현재 잔액을 빠르게 조회하기 위한 잔액 스냅샷 역할을 겸함
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 지갑 식별자 10 자동 증가
user_id BIGINT UNSIGNED N FK 소유 사용자 id 1 존재하는 users.id
currency_code CHAR(3) N UQ 통화 코드 USD ISO 4217, 3자리 대문자
balance DECIMAL(18,6) N   현재 잔액 1000.000000 0 이상 권장, 음수 허용 여부 정책 필요
created_date DATETIME N   최초등록 일시 2026-01-28 21:00:00 자동
updated_date DATETIME N   수정 일시 2026-01-29 21:00:00 자동

wallet 외화지갑 거래 구조

  • wallet_events: “사용자가 한 번 실행한 행위(입금/출금/환전)” = 이력 1건(헤더)
  • wallet_transactions: 그 행위 때문에 실제로 각 지갑에 찍히는 “원장 라인” = 상세 이력 1~N건
  • 입금: 지갑 1개만 변함 → transactions 1건
  • 출금: 지갑 1개만 변함 → transactions 1건
  • 환전: 지갑 2개가 동시에 변함 → transactions 2건 (from 통화 지갑 DEBIT 1건 + to 통화 지갑 CREDIT 1건)

wallet_events

  • 지갑 변동의 “행위/사건”을 기록하는 테이블
  • 환전, 입금, 출금 등의 행위를 업무단위 한 건으로 표현하기 위함
컬럼명 타입 NULL Key 설명 예시 검증/제약
id BIGINT UNSIGNED N PK 이벤트 ID 5001 AUTO_INCREMENT
user_id BIGINT UNSIGNED N FK/IDX 사용자 ID 1 users.id 존재
type ENUM(‘DEPOSIT’,’WITHDRAW’,’EXCHANGE’) N IDX 이벤트 유형 EXCHANGE enum 제한
external_source VARCHAR(50) Y   외부 출처(은행/수동 등) BANK 길이 제한
memo VARCHAR(255) Y   이벤트 메모(요약) KRW→USD 환전 길이 제한
idempotency_key VARCHAR(64) Y UQ 중복요청 방지 키(권장) req_20260207_001 유니크
occurred_date DATETIME N IDX 발생 시각 2026-02-07 12:00:00 필수
created_date DATETIME N   생성 시각 2026-02-07 12:00:01 DEFAULT
updated_date DATETIME N   수정 시각 2026-02-07 12:00:01 ON UPDATE

wallet_transactions

  • 외화 지갑의 입금/출금/환전 상세 내역을 기록하는 원장 테이블
  • 모든 잔액 변경의 근거 데이터로, 추적·검증·감사에 핵심적인 역할
  • 각 거래마다 balance_after를 저장해 거래 후 잔액 상태를 명확히 유지
컬럼명 타입 NULL Key 설명 예시 검증/제약
id BIGINT UNSIGNED N PK 거래(라인) ID 90001 AUTO_INCREMENT
event_id BIGINT UNSIGNED N FK/IDX 소속 이벤트 ID 5001 wallet_events.id 존재
wallet_id BIGINT UNSIGNED N FK/IDX 대상 지갑 ID 10 wallets.id 존재
direction ENUM(‘CREDIT’,’DEBIT’) N   증감 방향 DEBIT enum 제한
amount DECIMAL(18,6) N   증감 금액 200.000000 > 0
balance_after DECIMAL(18,6) N   거래 후 잔액 1200.000000 계산 결과와 일치
created_date DATETIME N IDX 생성 시각 2026-02-07 12:00:01 DEFAULT
updated_date DATETIME N   수정 시각 2026-02-07 12:00:01 ON UPDATE

exchange_rate_snapshots

  • 환율을 하루 단위로 저장하기 위한 환율 스냅샷 메타 정보(헤더)
  • 기준일, 기준통화, 환율 타입 조합으로 스냅샷을 구분하고 중복 저장을 방지
  • 외부 환율 API를 실제로 조회한 시각을 기록해 데이터 신뢰도를 관리
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 스냅샷 id 1 자동 증가
base_date DATE N UQ 기준일 2026-02-10 날짜 필수
base_currency ENUM(‘KRW’,’USD’) N UQ 기준 통화 KRW KRW/USD만 허용
rate_type ENUM(‘BASE’,’TT_BUY’,’TT_SELL’) N UQ 환율 타입 BASE MVP는 BASE만 사용 권장
source VARCHAR(100) N   제공처 KEXIM 기본값
created_date DATETIME N   최초등록 일시 2026-02-10 09:01:02 자동

exchange_rate_snapshots_detail

  • 특정 환율 스냅샷에 포함된 통화별 환율 상세 데이터
  • 예: 기준통화 KRW 기준으로 USD, JPY, EUR 등의 환율 값 저장
  • 환율 히스토리 조회 및 평가 손익(P/L) 계산의 핵심 데이터 소스
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 아이템 id 10 자동 증가
snapshot_id BIGINT UNSIGNED N FK/UQ 스냅샷 id 1 존재하는 snapshots.id
quote_currency CHAR(3) N UQ 대상 통화 USD ISO 4217 3자리
rate DECIMAL(18,6) N   환율 1300.120000 0 초과
created_date DATETIME N   최초등록 일시 2026-01-28 21:00:00 자동

ai_reports (Optional)

  • AI가 생성한 환율 변동 요약 리포트를 저장하는 테이블
  • 최근 N일간 환율 변화와 사용자 자산 영향에 대한 설명을 기록
  • 계산된 변동률·지표를 함께 저장해 리포트 재사용 및 비교가 가능
컬럼명 타입 NULL Key 설명 예시 검증 규칙
id BIGINT UNSIGNED N PK 리포트 id 1 자동 증가
user_id BIGINT UNSIGNED N FK 사용자 id 1 users.id 존재
base_currency ENUM(‘KRW’,’USD’) N   기준 통화 KRW 제한 enum
window_days INT N   분석 구간(일) 7 1~31 권장
from_date DATE N IDX 시작일 2026-02-01 to_date 이하
to_date DATE N IDX 종료일 2026-02-07 from_date 이상
content_md LONGTEXT N   요약 본문(Markdown) ### 요약 ... 공백 불가
metrics_json JSON Y   계산 지표(변동률 등) { "usd_change": 1.2 } JSON 유효
model_name VARCHAR(100) Y   사용 모델 gpt-4.1-mini 선택
created_date DATETIME N   최초등록 일시 2026-02-17 22:10:01 자동

ERD

ERD

5. API 구조

  • services 하위에 Must Have, Should Have , Could Have 등 기능이되는 api 를 나누어 개발
  • libs/common-web/ : 공통 예외처리를 라이브러리화 하여 services에서 사용
  • libs/common-event/ :
  • `libs/common-kafka/ :
my_wallet/
├─ settings.gradle
├─ build.gradle
├─ docker-compose.yml
│
├─ services/                     # 실행 가능한 Spring Boot 애플리케이션
│  │
│  ├─ user-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/user
│  │     ├─ UserServiceApplication.java
│  │     ├─ controller/   # HTTP API 진입점, service 호출
│  │     ├─ service/      # 유스케이스/비즈니스 로직 계층
│  │     ├─ domain/       # 도메인 모델(엔티티) - DB 테이블(users)과 매핑되는 JPA Entity
│  │     ├─ dto/          # API 전용 데이터 구조 (Request-입력, Response-응답)
│  │     ├─ exception/    # 서비스 전용 에러 코드만 보관 - 실제 예외 처리기(Handler)는 common-web에 있음
│  │     └─ repository/   # 데이터 접근 - JPA를 통한 CRUD
│  │
│  ├─ wallet-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/wallet
│  │     ├─ WalletServiceApplication.java
│  │     ├─ controller/           # REST API
│  │     ├─ application/          # 유스케이스 (Command 중심)
│  │     ├─ domain/               # Wallet, WalletEvent, WalletTransaction
│  │     ├─ repository/
│  │     ├─ messaging/
│  │     │  ├─ outbox/             # Outbox 엔티티/퍼블리셔
│  │     │  └─ producer/           # Kafka 이벤트 발행
│  │     └─ config/
│  │
│  ├─ exchange-rate-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/exchange
│  │     ├─ ExchangeRateServiceApplication.java
│  │     ├─ controller/
│  │     ├─ application/
│  │     ├─ domain/               # Snapshot, SnapshotDetail
│  │     ├─ repository/
│  │     ├─ external/             # KEXIM client
│  │     ├─ messaging/
│  │     │  └─ producer/
│  │     └─ config/
│  │
│  ├─ valuation-service/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/valuation
│  │     ├─ ValuationServiceApplication.java
│  │     ├─ controller/
│  │     ├─ application/
│  │     ├─ domain/               # Portfolio, ValuationResult
│  │     ├─ repository/
│  │     ├─ messaging/
│  │     │  └─ consumer/           # wallet / snapshot 이벤트 구독
│  │     └─ config/
│  │
│  └─ report-service/
│     ├─ build.gradle
│     └─ src/main/java/com/mywallet/report
│        ├─ ReportServiceApplication.java
│        ├─ controller/
│        ├─ application/
│        ├─ domain/               # AiReport
│        ├─ repository/
│        ├─ messaging/
│        │  └─ consumer/
│        └─ config/
│
├─ libs/                          # 공통 라이브러리
│  │
│  ├─ common-web/
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/common/web
│  │     ├─ exception/            # GlobalException, ErrorCode
│  │     ├─ response/             # ApiResponse<T>
│  │     └─ validation/           # @PositiveAmount, @CurrencyCode
│  │
│  ├─ common-event/               # ⭐ Kafka/HTTP 공통 "이벤트 계약"
│  │  ├─ build.gradle
│  │  └─ src/main/java/com/mywallet/common/event
│  │     ├─ wallet/
│  │     │  └─ WalletEventCreated.java
│  │     ├─ exchange/
│  │     │  └─ ExchangeRateSnapshotCreated.java
│  │     └─ BaseEvent.java         # eventId, occurredAt, version
│  │
│  └─ common-kafka/
│     ├─ build.gradle
│     └─ src/main/java/com/mywallet/common/kafka
│        ├─ config/               # Producer/Consumer 공통 설정
│        ├─ serializer/
│        └─ producer/             # KafkaTemplate 헬퍼
│
├─ infra/
│  └─ k8s/                        # ⭐ Kubernetes 매니페스트
│     ├─ base/
│     │  ├─ namespace.yaml
│     │  ├─ configmap.yaml
│     │  └─ secret.yaml
│     │
│     ├─ wallet-service/
│     │  ├─ deployment.yaml
│     │  ├─ service.yaml
│     │  └─ hpa.yaml
│     │
│     ├─ exchange-rate-service/
│     │  ├─ deployment.yaml
│     │  ├─ service.yaml
│     │  └─ cronjob-snapshot.yaml  # 하루 1회 환율 스냅샷
│     │
│     ├─ valuation-service/
│     │  ├─ deployment.yaml
│     │  └─ service.yaml
│     │
│     └─ report-service/
│        ├─ deployment.yaml
│        └─ service.yaml
│
└─ README.md