Skip to content

Repository files navigation

Financial Mock Server

금융 API 연동 기능을 개발하고 테스트하기 위한 Spring MVC 기반 목 서버입니다.

실제 CODEF API를 매번 호출하지 않고, 로컬 MySQL의 mock 데이터를 조회해 안정적인 금융 응답을 제공합니다. 정상 응답뿐 아니라 빈 데이터, 토큰 만료, 호출 제한 같은 시나리오 응답도 함께 테스트할 수 있습니다.

목적

  • 외부 금융 API 호출 없이 자산/거래/카드/대출 응답 테스트
  • 사용자별 scenarioKey 기반 목 데이터 분기
  • 정상 데이터는 DB 원천 테이블에서 조회해 응답 조립
  • 오류/빈 데이터 등 특수 케이스는 fixture JSON으로 응답
  • 실제 서비스 DB와 분리된 목 서버 전용 데이터 관리

현재 DB 기준

현재 코드가 조회하는 기준 스키마는 src/main/resources/db/schema-v2.sql입니다.

기존 schema.sql, seed.sql, init.sql에는 구버전 mock_codef_* 구조가 남아 있습니다. 현재 매퍼와 서비스는 주로 v2의 도메인 분리 테이블을 조회합니다.

DB 구조

DB는 크게 두 영역으로 나뉩니다.

1. 목 응답 제어 영역

요청을 어떤 사용자, 어떤 API, 어떤 시나리오로 처리할지 결정하는 테이블입니다.

  • mock_user: 테스트 사용자. scenario_key로 사용자를 식별합니다.
  • mock_scenario: NORMAL, EMPTY_DATA, TOKEN_EXPIRED, RATE_LIMITED 같은 응답 시나리오입니다.
  • mock_api_endpoint: 목 서버가 인식하는 API endpoint 목록입니다.
  • mock_scenario_assignment: 사용자 또는 endpoint별 시나리오 배정 정보입니다.
  • mock_api_response_fixture: NORMAL이 아닌 시나리오에서 반환할 고정 JSON 응답입니다.
  • mock_api_call_log: 요청/응답 호출 이력을 저장합니다.

2. 금융 원천 데이터 영역

정상 시나리오에서 실제 응답을 조립할 때 조회하는 데이터입니다.

  • financial_institution: 금융기관 마스터입니다. 은행, 카드사, 증권사, 페이머니 제공자를 포함합니다.
  • bank_account: 입출금 계좌입니다.
  • bank_transaction: 입출금 계좌 거래내역입니다.
  • card: 카드 목록입니다.
  • card_approval: 카드 승인내역입니다.
  • card_bill: 카드 청구서입니다.
  • pay_money: 페이머니/간편결제 잔액입니다.
  • deposit_account: 예적금 계좌입니다.
  • deposit_transaction: 예적금 거래내역입니다.
  • loan_account: 대출 계좌입니다.
  • loan_transaction: 대출 상환/거래내역입니다.
  • securities_account: 증권 계좌입니다.
  • securities_holding: 증권 보유 종목입니다.
  • securities_transaction: 증권 거래내역입니다.

ERD 요약

erDiagram
    mock_user ||--o{ mock_scenario_assignment : has
    mock_user ||--o{ bank_account : owns
    mock_user ||--o{ card : owns
    mock_user ||--o{ pay_money : owns
    mock_user ||--o{ deposit_account : owns
    mock_user ||--o{ loan_account : owns
    mock_user ||--o{ securities_account : owns

    financial_institution ||--o{ bank_account : provides
    financial_institution ||--o{ card : provides
    financial_institution ||--o{ pay_money : provides
    financial_institution ||--o{ deposit_account : provides
    financial_institution ||--o{ loan_account : provides
    financial_institution ||--o{ securities_account : provides

    bank_account ||--o{ bank_transaction : has
    card ||--o{ card_approval : has
    card ||--o{ card_bill : has
    deposit_account ||--o{ deposit_transaction : has
    loan_account ||--o{ loan_transaction : has
    securities_account ||--o{ securities_holding : has
    securities_account ||--o{ securities_transaction : has

    mock_api_endpoint ||--o{ mock_api_response_fixture : has
    mock_scenario ||--o{ mock_api_response_fixture : groups
    mock_api_endpoint ||--o{ mock_api_call_log : records
Loading

응답 처리 흐름

요청 수신
-> method/path로 mock_api_endpoint 조회
-> scenarioKey로 mock_user 조회
-> 사용자 또는 endpoint에 배정된 mock_scenario 확인
-> NORMAL 시나리오면 금융 원천 테이블 조회 후 응답 조립
-> NORMAL이 아니면 mock_api_response_fixture.response_json 반환
-> mock_api_call_log 저장

scenarioKey는 query parameter 또는 X-Scenario-Key header로 전달할 수 있습니다. 값이 없으면 서비스에서 기본 테스트 사용자를 사용합니다.

특정 오류 시나리오를 강제로 사용하려면 query parameter scenario 또는 X-Mock-Scenario header에 mock_scenario.scenario_code 값을 전달합니다.

공통 응답 형식

모든 API 응답은 공통 envelope 구조를 사용합니다.

{
  "code": "SUCCESS",
  "message": "조회 성공",
  "data": {},
  "traceId": "generated-trace-id",
  "timestamp": "server-time"
}

주요 시나리오:

  • NORMAL: DB 원천 데이터 기반 정상 응답
  • EMPTY_DATA: 빈 데이터 응답
  • TOKEN_EXPIRED: 인증 토큰 만료 응답
  • RATE_LIMITED: 외부 API 호출 제한 응답

현재 구현된 API

자산 API

  • GET /api/v1/assets/accounts: 은행 계좌 목록 조회
  • GET /api/v1/assets/stocks: 증권 계좌 요약 및 보유 종목 조회
  • GET /api/v1/assets/loans: 대출 목록 조회
  • GET /api/v1/assets/payMoney: 페이머니 목록 조회

원천 금융 API

  • GET /api/v1/accounts/{accountId}/transactions: 은행 계좌 거래내역 조회
  • GET /api/v1/cards: 카드 목록 조회
  • GET /api/v1/cards/{cardId}/approvals: 카드 승인내역 조회

CODEF 호환 API

  • POST /codef/v1/account/balance: CODEF 호환 계좌 잔액 조회

DB에는 있으나 아직 API가 없는 데이터

다음 테이블은 v2 DB와 seed에는 있지만, 현재 컨트롤러/매퍼 API가 아직 열려 있지 않습니다.

  • card_bill: 카드 청구서
  • deposit_account: 예적금 계좌
  • deposit_transaction: 예적금 거래내역
  • loan_transaction: 대출 상환/거래내역
  • securities_transaction: 증권 거래내역

추가 후보 API:

  • GET /api/v1/assets/dashboard
  • GET /api/v1/accounts/banks
  • GET /api/v1/cards/{cardId}/bills
  • GET /api/v1/deposits
  • GET /api/v1/deposits/{depositId}/transactions
  • GET /api/v1/loans/{loanId}/transactions
  • GET /api/v1/securities/{accountId}/transactions
  • GET /api/v1/transactions

Seed 데이터

v2 seed 기준 파일은 src/main/resources/db/seed-v2.sql입니다.

포함 데이터:

  • 시나리오: NORMAL, EMPTY_DATA, TOKEN_EXPIRED, RATE_LIMITED

  • 테스트 사용자:

    • demo-normal-user
    • demo-empty-user
  • 금융기관 (34곳 — 탕탕 앱 InstitutionCatalog 전기관: 은행9·카드6·증권5·대출8·페이머니6):

    코드 이름 구분
    0004 KB국민은행 BANK
    0088 신한은행 BANK
    0090 카카오뱅크 BANK
    0020 우리은행 BANK
    0092 토스뱅크 BANK
    0081 하나은행 BANK
    0011 NH농협은행 BANK
    0089 케이뱅크 BANK
    0003 IBK기업은행 BANK
    0381 KB국민카드 CARD
    0301 신한카드 CARD
    0361 BC카드 CARD
    0364 삼성카드 CARD
    0366 현대카드 CARD
    0371 롯데카드 CARD
    0218 KB증권 SECURITIES
    0240 삼성증권 SECURITIES
    0243 한국투자증권 SECURITIES
    0247 NH투자증권 SECURITIES
    0261 교보증권 SECURITIES
    CP_KB KB캐피탈 LOAN
    CP_HYUNDAI 현대캐피탈 LOAN
    CP_SHINHAN 신한캐피탈 LOAN
    CP_HANA 하나캐피탈 LOAN
    CP_WOORI 우리금융캐피탈 LOAN
    SB_SBI SBI저축은행 LOAN
    SB_OK OK저축은행 LOAN
    SB_WELCOME 웰컴저축은행 LOAN
    PAY_KB KB Pay PAY_MONEY
    PAY_KAKAO 카카오페이 PAY_MONEY
    PAY_NAVER 네이버페이 PAY_MONEY
    PAY_TOSS 토스페이 PAY_MONEY
    PAY_PAYCO 페이코 PAY_MONEY
    PAY_CPANG 쿠팡페이 PAY_MONEY

    기관 코드는 소비처(탕탕 앱)의 InstitutionCatalog 와 같아야 합니다. 앱은 계좌 응답의 institutionCode 로 "사용자가 고른 기관"과 대조해 거르므로, 코드가 어긋난 계좌는 조회돼도 화면에서 통째로 버려집니다. 2026-08-11 에 0101(KB국민카드) → 0381, 0301(구 KB증권) → 0218(KB증권)으로 정정했습니다. 2026-08-19 에 나머지 13개 기관(은행 4·카드 5·증권 4)을 추가해 카탈로그와 완전히 맞췄습니다. 0301 은 카탈로그 기준으로 원래부터 신한카드이며, 지금은 그 정체로 정식 등록되어 있습니다. 2026-08-20 에 LOAN 업권(캐피탈 5·저축은행 3) 8곳을 추가했습니다. 그 전까지는 LOAN 타입 기관이 하나도 없어 대출 계좌가 전부 BANK 기관(0004)에 잘못 연결돼 있었고, institutionCodeCP_*/SB_* 형식으로 나가지 않아 앱의 InstitutionCatalog.isLoanCode() 매칭이 항상 실패했습니다. 2026-08-20 에 PAY_MONEY 업권도 5곳(카카오·네이버·토스·페이코·쿠팡페이) 추가했습니다. 추가로 pay_money.provider_code 시드값이 'KB_PAY'(오타)로 들어가 있었습니다 — 기관 조인 키는 PAY_KB로 맞는데 API 응답에 실리는 provider_code 컬럼만 따로 틀려 있어, InstitutionCatalog.isPayMoneyCode()/아이콘 매칭이 항상 실패했고 계좌 연동 시 기관 선택 코드(PAY_KB)와 비교가 어긋나 최초 동기화에서 KB Pay 가 아예 저장되지 않는(0건) 문제까지 있었습니다. 'PAY_KB' 로 정정했습니다.

  • 정상 사용자용 샘플 데이터 (demo-normal-user 기준. 은행·카드·증권은 19개 기관 전체에 계좌가 있습니다):

    • 은행 계좌 13개 (9개 기관 전체) 및 계좌별 거래내역 2건씩 — 기관 선택 화면에는 은행이 9곳 뜨는데 계좌가 KB 하나뿐이라 다른 기관을 고르면 조회 결과가 0건이던 문제를 해소했습니다(2026-08-11, 2026-08-19 은행 4곳 추가로 9곳 전체 커버)
    • 카드 6장 (6개 기관 전체), 카드별 승인내역/청구서 포함(2026-08-19 카드 5곳 추가)
    • 페이머니
    • 예적금 계좌 및 거래내역
    • 대출 계좌 및 상환내역
    • 증권 계좌 5개 (5개 기관 전체), 보유 종목·증권 거래내역 포함(2026-08-19 증권 4곳 추가)
  • 빈 데이터/토큰 만료 fixture 응답

scenario_key='2' (거래내역 카테고리 분류 테스트 전용)

별도 파일 src/main/resources/db/seed-v2-scenario2.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario2.sql 순서로 적용해야 합니다.

은행 계좌 1개만 두고, 2026-04-012026-08-31(153일) 매일 25건씩 db/seed_category.sql 기준 소분류 44개를 전부 커버하는 거래내역을 채웁니다. 날짜·슬롯 기반 결정론적 MOD 연산으로 생성해 재실행해도 같은 결과가 나옵니다(멱등).

scenario_key='3' (카드 승인/은행 정합성 검증 전용)

별도 파일 src/main/resources/db/seed-v2-scenario3.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario3.sql 순서로 적용해야 합니다.

scenario_key='2' 가 카드 없이 거래내역 카테고리 다양성만 다뤘다면, 이 시나리오는 카드 승인내역(card_approval)과 은행 입출금(bank_transaction) 두 소스를 합쳐 거래를 감지하는 탕탕 앱의 실제 동작을 재현합니다. 은행 계좌 1개 + 신용카드 1장(card_type_code='01') + 체크카드 1장(card_type_code='02')을 두고, 소비를 3갈래로 나눠 기록합니다:

  • 그룹 A (자동이체, 12개 소분류) — 카드 없이 bank_transaction 에 매월 1회 직접 기록 (월세·관리비·공과금·통신비·구독료·보험료·금융상품 등)
  • 그룹 B (체크카드, 나머지 32개 소분류 중 ~30%)card_approval 1행 + bank_transaction 1행을 같은 correlationId 로 묶어 "같은 사건의 두 소스 표현"을 재현
  • 그룹 C (신용카드, 나머지 32개 소분류 중 ~70%)card_approval 에만 개별 소비를 기록하고, bank_transaction 에는 그 달 신용카드 승인합계와 정확히 같은 금액의 "카드 이용대금" 1건만 다음달 14일에 기록(정산행의 challengeCategoryNULL — 이미 card_approval 로 잡힌 소비가 이중계산되지 않도록 함). card_bill 도 같은 합계로 월별 1건씩 생성됩니다.

2026-04-012026-08-31(153일) 매일 25건의 소비 이벤트(그룹 B 는 이벤트 1건당 row 2개) + 그룹 A 월 1회 자동이체로 44개 소분류를 전부 커버합니다. 날짜·슬롯 기반 결정론적 MOD 연산으로 생성해 재실행해도 같은 결과가 나옵니다(멱등 — 로컬 검증 시 재실행 전/후 행 수·잔액 동일 확인).

scenario_key='4' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario4.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario4.sql 순서로 적용해야 합니다.

scenario_key='3' 과 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고 (004909******4004, 9490-****-****-4401, 5210-****-****-4402) 나머지 로직·검증 결과는 scenario 3 과 동일합니다(카드 정합성 로직을 여러 사용자로 병렬 테스트할 때 사용). 상세 구조는 바로 위 scenario_key='3' 절을 참고하세요.

scenario_key='5' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario5.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario5.sql 순서로 적용해야 합니다.

scenario_key='3'/'4' 와 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고 (004909******5005, 9490-****-****-5501, 5210-****-****-5502) 나머지 로직·검증 결과는 scenario 3/4 와 동일합니다(카드 정합성 로직을 여러 사용자로 병렬 테스트할 때 사용). 상세 구조는 scenario_key='3' 절을 참고하세요. 로컬 검증 결과: card_approval 538건 · bank_transaction 235건 · card_bill 5건, 44개 소분류 전부 커버, MIN(balance_after) 611,200원(마이너스 없음), 재실행 전/후 행 수 동일(멱등).

scenario_key='6' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario6.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario6.sql 순서로 적용해야 합니다.

scenario_key='3'/'4'/'5' 와 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고 (004909******6006, 9490-****-****-6601, 5210-****-****-6602), scenario5 가 scenario3 의 MOD 계수를 그대로 재사용해 소비 패턴이 사실상 같았던 것과 달리 이 시나리오는 scenario4 처럼 계수를 새로 골라 날짜별 카테고리·금액·체크/신용 배정이 실제로 다르게 나옵니다. 상세 구조는 scenario_key='3' 절을 참고하세요. 로컬 검증 결과: card_approval 538건 · bank_transaction 235건 · card_bill 5건, 44개 소분류 전부 커버, 신용카드 월별 정산 금액이 그 달 card_approval 합계와 정확히 일치(이중계산 없음), 체크카드 쌍은 correlationId 기준으로 양쪽 금액 전부 일치, MIN(balance_after) 1,085,700원(마이너스 없음), 재실행 전/후 행 수 동일(멱등).

scenario_key='7' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario7.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario7.sql 순서로 적용해야 합니다.

scenario_key='3'/'4'/'5'/'6' 과 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고(004909******7007, 9490-****-****-7701, 5210-****-****-7702), scenario4/6 처럼 is_large/is_checkcard/small_bc/large_bc/daily_count 의 곱셈 계수를 3/4/5/6 어느 것과도 겹치지 않는 새 값으로 골라 날짜별 카테고리·금액·체크/신용 배정이 실제로 다르게 나옵니다. 상세 구조는 scenario_key='3' 절을 참고하세요. 로컬 검증 결과: card_approval 533건 · bank_transaction 229건 · card_bill 5건, 44개 소분류 전부 커버, 신용카드 월별 정산 금액이 그 달 card_approval 합계와 정확히 일치(이중계산 없음, 정산행 challengeCategory 는 JSON null), 체크카드 쌍은 correlationId 기준으로 양쪽 금액 전부 일치, MIN(balance_after) 1,750,000원(마이너스 없음), 재실행 전/후 행 수 동일(멱등).

scenario_key='8' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario8.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario8.sql 순서로 적용해야 합니다.

scenario_key='3'/'4'/'5'/'6'/'7' 과 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고(004909******8008, 9490-****-****-8801, 5210-****-****-8802), scenario4/6/7 처럼 is_large/is_checkcard/small_bc/large_bc/daily_count 의 곱셈 계수를 3/4/5/6/7 어느 것과도 겹치지 않는 새 값으로 골라 날짜별 카테고리·금액·체크/신용 배정이 실제로 다르게 나옵니다. 상세 구조는 scenario_key='3' 절을 참고하세요. 로컬 검증 결과: card_approval 535건 · bank_transaction 234건 · card_bill 5건, 44개 소분류 전부 커버, 신용카드 월별 정산 금액이 그 달 card_approval 합계와 정확히 일치(이중계산 없음, 정산행 challengeCategory 는 JSON null), 체크카드 쌍은 correlationId 기준으로 양쪽 금액 전부 일치, MIN(balance_after) 646,900원(마이너스 없음), 재실행 전/후 행 수 동일(멱등).

scenario_key='9' (카드 승인/은행 정합성 검증 — 병렬 사용자)

별도 파일 src/main/resources/db/seed-v2-scenario9.sql 로 분리돼 있습니다(2026-08-19 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario9.sql 순서로 적용해야 합니다.

scenario_key='3'/'4'/'5'/'6'/'7'/'8' 과 완전히 동일한 그룹 A/B/C 구조(계좌 1개, 신용카드 1장 + 체크카드 1장, 결정론적 MOD 생성 로직)를 그대로 재사용하는 독립된 사용자입니다 — 계좌/카드 번호만 다르고(004909******9009, 9490-****-****-9901, 5210-****-****-9902), scenario4/6/7/8 처럼 is_large/is_checkcard/small_bc/large_bc/daily_count 의 곱셈 계수를 3/4/5/6/7/8 어느 것과도 겹치지 않는 새 값으로 골라 날짜별 카테고리·금액·체크/신용 배정이 실제로 다르게 나옵니다. 상세 구조는 scenario_key='3' 절을 참고하세요. 초기에 골랐던 large idx 계수(97/101)는 로컬 검증에서 고액군 15개 중 2개(주유/충전·숙박)가 153일 동안 한 번도 안 뽑히는 걸 발견해 139/109 로 교체했습니다(고액군은 전체 이벤트의 ~6%뿐이라 표본이 작아 계수에 따라 특정 잔차가 통째로 비는 경우가 생길 수 있음 — 계수를 바꿀 때는 반드시 44개 소분류 커버리지를 다시 확인할 것). 로컬 검증 결과: card_approval 524건 · bank_transaction 230건 · card_bill 5건, 44개 소분류 전부 커버, 신용카드 월별 정산 금액이 그 달 card_approval 합계와 정확히 일치(이중계산 없음, 정산행 challengeCategory 는 JSON null), 체크카드 쌍은 correlationId 기준으로 양쪽 금액 전부 일치, MIN(balance_after) 747,400원(마이너스 없음), 재실행 전/후 행 수 동일(멱등).

scenario_key='-1' (실거래 카드내역 기반 카테고리 분류 테스트)

별도 파일 src/main/resources/db/seed-v2-scenario-1.sql 로 분리돼 있습니다(2026-08-22 추가). seed-v2.sql 이 넣는 financial_institution(신한은행 0088, 신한카드 0301)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario-1.sql 순서로 적용해야 합니다.

다른 카테고리 시나리오(2~9)는 모두 MOD 기반 결정론적 절차 생성이었지만, 이 시나리오는 실제 신한카드 체크카드 승인내역 두 건을 그대로 가공한 실거래 기반 데이터입니다. 두 원본은 서로 반대 방향으로 날짜를 이동해 하나의 시나리오로 합쳤습니다:

  • 소스 1(원본 2026-03~05, 104건 중 결제확정 96건) → "+3개월" 이동(3월→6월, 4월→7월, 5월→8월). ID 접두어 SN1-B-/SN1-CORR-.
  • 소스 2(원본 2026-0608, 74건 중 결제확정 68건) → "-3개월" 이동(6월→3월, 7월→4월, 8월→5월). ID 접두어 SN1-B2-/SN1-CORR2-. 실제로는 68월 데이터이지만 시나리오 요청에 따라 소스 1과 반대 방향으로 이동했습니다(두 소스 모두 원본 승인번호가 서로 겹치지 않음).

합치면 목 시나리오 기준 2026-03-01~2026-08-31(6개월) 을 커버합니다. 신한은행 계좌 1개 + 신한 체크카드 1장(3560-****-****-9101) + 신한 신용카드 1장(4906-****-****-9102, 구조 요구사항 충족용이며 실거래 없음)을 두고, 부분취소·승인취소 원장(소스1 8건 + 소스2 6건)은 실제 청구되지 않아 제외했습니다(일자·시각은 원본 그대로, 말일 초과 시 clamp — 두 데이터셋 모두 실제로 clamp 가 발동하는 케이스는 없었음).

두 원본 모두 100% 체크카드 결제 기록이라 그룹 A(자동이체)·그룹 C(신용카드 소비)에 해당하는 실거래가 없습니다 — LG U+ 통신요금 자동이체(두 소스 합쳐 6건)도 원본상 체크카드로 결제됐으므로 그룹 B로 그대로 처리했고, 신용카드는 빈 카드(승인·청구서 없음)로만 존재합니다. 그룹 B(체크카드 소비) 164건은 card_approval 1행 + bank_transaction 1행을 correlationId 로 묶었고, 원본 승인번호가 이미 전역 유일해 approval_no/original_transaction_id 를 그대로 재사용했습니다. 원본에 급여성 입금이 없어 계좌 시작 잔액 800,000원 + 매월(3~8월) 25일 1,000,000원("급여")을 추가했습니다(월 최대 소비가 약 32만원 수준이라 다른 시나리오보다 낮춤). 계좌 개설일/카드 발급일은 최초 거래(2026-03-01)보다 앞선 2026-02-25 로 뒀습니다.

가맹점명은 44개 소분류 표(scenario_key='2'/'4' 기준)에 매핑했고, 표에 정확히 대응하는 항목이 없는 PC방·코인노래방·볼링장류는 레저/운동시설(mcc 7997)로, 업종이 불명확한 가맹점(에스씨케이컴퍼니· 에프앤피컴퍼니·소노인터내셔널·데이터에듀·AL-GO·신선지엠 등)은 이름·거래 패턴 기반으로 가장 가까운 소분류에 추정 매핑했습니다(상세 근거는 seed-v2-scenario-1.sql 파일 상단 주석 참고). 로컬 검증 결과: card_approval 164건 · bank_transaction 170건 · card_bill 0건(신용카드 실거래 없음), 14개 소분류 등장(음식점/외식 48·편의점 47·레저 26·카페/간식 17·택시/모빌리티 8·통신비 6· 온라인쇼핑 3·뷰티 3·운동시설/앱·게임/패션/온라인 강의/장보기·마트/관광·여행상품 각 1건), 거래일자 2026-03-01~2026-08-31 범위 내 확인, MIN(balance_after) 529,700원(마이너스 없음), bank_account.balance 가 마지막 거래 balance_after(5,362,030원)와 일치, 재실행 전/후 행 수 동일(멱등), 기존 소스1 단독 버전(96/99행)에 소스2를 추가 적용해도 소스1 쪽 키가 충돌 없이 갱신됨을 확인.

⚠️ 이 파일은 실제 사용자 본인의 신한카드 체크카드 승인내역(가맹점명·이용시각 등)을 원본으로 하며, 날짜만 이동하고 가맹점명·금액은 그대로 시드 SQL에 포함되어 있습니다. 저장소를 외부에 공유/푸시할 경우 실제 소비 위치·패턴이 노출될 수 있으니 주의하세요.

scenario_key='-2' (실거래 계좌내역 기반 카테고리 분류 테스트)

별도 파일 src/main/resources/db/seed-v2-scenario-2.sql 로 분리돼 있습니다(2026-08-22 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario-2.sql 순서로 적용해야 합니다.

scenario_key='-1'과 달리 원본이 "카드사 승인내역"이 아니라 KB국민은행 계좌 거래내역조회(승인 번호·매입구분 필드가 없는 엑셀, 총 642행, 조회기간 2026-02-232026-08-22)입니다. 전 거래를 원본 시각 그대로 +14일(2주) 이동해 **2026-03-092026-09-03** 을 커버합니다(월말 clamp가 필요 없는 단순 날짜 이동). 원본 642행 중 시드에 반영한 것은 그룹 B 333건(체크카드 201 + 카드를 거치지 않고 계좌에서 바로 빠져나간 간편결제성 "FBS 출금" 112 + "오픈뱅킹출금 카카오T포인트" 20 — 사용자가 이 계좌직결제 항목들도 그룹 B처럼 처리하도록 확정)뿐이고, 나머지는 제외했습니다:

  • 취소·환불 쌍 22행(가승인 후 취소된 카카오T택시 10쌍 + Amazon_AWS 1쌍) — 실제 청구되지 않음.
  • 신용카드 대금 월별 합계 출금 10건(KB국민카드 9건 + 현대카드 1건) — 이 계좌가 최소 2장의 신용카드 대금을 결제하고 있다는 증거지만, 원본이 계좌 거래내역서라 그 밑의 개별 카드 승인 원장이 전혀 없습니다. 개별 card_approval 없이 월별 합계만 넣으면 이중계산 검증을 통과할 수 없어 그룹 C는 완전히 비우고 이 10건은 드롭했습니다(신용카드 실거래 없으면 그룹 C· card_bill 모두 생성하지 않는 원칙 적용).
  • 소비가 아닌 항목(개인 송금·ATM/CD 입출금·이자·체크카드 캐시백·환급 등) 187건과, 가맹점이 특정되지 않는 카카오페이/모바일티머니 충전성 FBS 출금 119건.

원본에는 scenario_key='-1'과 마찬가지로 월세·통신비·보험료 같은 순수 계좌 자동이체(그룹 A)에 해당하는 실거래가 전혀 없습니다. 가맹점명은 44개 소분류 표(scenario_key='2'/'4' 기준)에 매핑했고, PC방·코인노래방·오락실류는 레저(mcc 7997), PG사/결제대행사명만 있는 항목(NICE결제 대행·이니시스)과 업종 불명 상호명은 온라인쇼핑(mcc 5399)으로 추정 매핑했습니다(전체 저확신 매핑 목록과 근거는 seed-v2-scenario-2.sql 파일 상단 주석 참고, 사용자에게 표로 제시 후 확인 받음). 원본에 급여성 입금이 없어 계좌 시작 잔액 700,000원 + 매월(3~8월) 25일 900,000원("급여")을 추가했습니다(9월은 대상 기간이 9/3까지 사흘뿐이라 생략). 계좌 개설일/카드 발급일은 최초 거래 (2026-03-09)보다 앞선 2026-03-05 로 뒀습니다.

로컬 검증 결과: card_approval 333건 · bank_transaction 339건 · card_bill 0건(신용카드 실거래 없음), 16개 소분류 등장(편의점 95·레저 76·카페/간식 54·온라인쇼핑 32·택시/모빌리티 26· 음식점/외식 19·배달앱 6·약국 6·주차/통행료 4·장보기/마트 4·취미 4·패션 3·생활용품/뷰티/경조사· 선물/병원 각 1건), 거래일자 2026-03-09~2026-09-03 범위 내 확인, 체크카드/계좌직결제 쌍은 correlationId 기준 양쪽 금액 전부 일치(불일치 0건), MIN(balance_after) 414,040원(마이너스 없음), bank_account.balance 가 마지막 거래 balance_after(3,477,870원)와 일치, 재실행 전/후 행 수 동일(멱등).

⚠️ 이 파일은 실제 사용자 본인의 KB국민은행 계좌 거래내역(가맹점명·이용시각 등)을 원본으로 하며, 날짜만 이동하고 가맹점명·금액은 그대로 시드 SQL에 포함되어 있습니다. 원본의 실제 계좌번호·실명은 시드에 반영하지 않고 가상 값으로 대체했습니다. 저장소를 외부에 공유/푸시할 경우 실제 소비 위치·패턴이 노출될 수 있으니 주의하세요.

scenario_key='-3' (실거래 계좌내역 기반 카테고리 분류 테스트, 2번째 계좌 데이터)

별도 파일 src/main/resources/db/seed-v2-scenario-3.sql 로 분리돼 있습니다(2026-08-22 추가). seed-v2.sql 이 넣는 financial_institution(IBK기업은행 0003, BC카드 0361)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario-3.sql 순서로 적용해야 합니다.

scenario_key='-2'와 마찬가지로 원본이 "카드사 승인내역"이 아니라 IBK기업은행 계좌 거래내역 조회(엑셀, 승인번호·매입구분 필드 없음, 총 540행, 조회기간 2026-02-232026-08-22)입니다. 사용자가 "2주씩 미뤄달라"고 명시적으로 요청해 월 단위 이동 없이 전 거래를 원본 시각 그대로 +14일 이동해 **2026-03-092026-09-05** 를 커버합니다(날짜 단순 덧셈이라 말일 clamp 불필요). 원본 540행 중 시드에 반영한 것은 그룹 A 6건 + 그룹 B 412건뿐이고, 나머지 122건은 제외했습니다(모두 사용자 확인 후 확정):

  • 취소·정정 쌍 22행(카카오T택시_가승인 7쌍 + 카카오T일반택시(법인) 1쌍 + ㈜스마트파이브 1쌍 + 모바일 티머니 충전 1쌍 + 네이버페이/정정 1쌍, 거래일시·금액 완전 일치 확인) — 실제 청구되지 않음.
  • 롯데카드 신용카드 대금 출금 9건(약 130만원) — 개별 카드 승인 원장이 원본에 전혀 없어 이중계산 검증을 통과할 수 없으므로 scenario_key='-2'와 동일하게 그룹 C는 완전히 비우고 드롭했습니다 (신용카드 실거래 없으면 그룹 C·card_bill 모두 생성 안 함 원칙, 사용자 확인 완료).
  • 카카오페이 충전성 펌뱅킹 출금 43건 — 간편결제 앱 충전이라 가맹점 미특정, 제외.
  • 개인 간 송금성 이체 41건(총 6,439,441원, 그중 본인 명의 이체 12건 4,673,641원 포함) — 소비가 아닌 계좌 이동이라 전부 제외(사용자가 "전부 제외, 급여 새로 합성" 선택).
  • 포인트/캐시백 6건 + 이자 1건 — 소비가 아니라 제외.

원본에 삼성생명 보험료 자동이체 6건(펌이체, 매월 5~6일 1회, 각 19,334원)만은 카드를 거치지 않는 순수 계좌 자동이체라 그룹 A(보험료, mcc 6300)로 반영했습니다. IBK 계열은 카탈로그에 자체 카드사 행이 없어 카드 발급사는 BC카드(0361)로 가정했습니다(사용자 확인 완료). 신용카드는 구조 요구사항 충족용 빈 카드(실거래 없음)로만 생성했습니다.

가맹점명은 44개 소분류 표(scenario_key='2'/'4' 기준)에 매핑했고, 120개 가맹점 중 27개는 상호명만 있어 업종을 특정하기 어려워 가장 가까운 소분류로 추정 매핑했습니다(PC방·코인노래방·오락실류 → 레저, 네이버페이 → 온라인쇼핑, 업종 불명 회사명 다수 → 온라인쇼핑, 스터디카페류 → 학원 등 — 전체 목록과 근거는 seed-v2-scenario-3.sql 파일 상단 주석 참고, 사용자에게 표로 제시 후 "제안된 기본값으로 진행" 확인 받음). 원본에 급여성 입금이 없어(개인 간 송금은 전부 제외) 계좌 시작 잔액 700,000원 + 매월(3~8월) 25일 1,000,000원("급여")을 추가했습니다(9월은 대상 기간이 9/5까지 닷새뿐이라 생략).

로컬 검증 결과: card_approval 412건 · bank_transaction 424건(그룹A 6 + 그룹B 412 + 급여 6) · card_bill 0건(신용카드 실거래 없음), 19개 소분류 등장(카페/간식 113·편의점 82·음식점/외식 71· 대중교통 46·온라인쇼핑 29·레저 21·앱·게임 13·택시/모빌리티 10·반려동물 7·뷰티 4·취미/숙박/학원/ 생활용품 각 2·도서/시험·자격증/병원/약국/경조사·선물/영화·공연·전시/주차·통행료/온라인 강의 각 1건 + 보험료 6건), 거래일자 2026-03-09~2026-09-05 범위 내 확인, 체크카드 쌍은 correlationId 기준 양쪽 금액 전부 일치(불일치 0건), MIN(balance_after) 347,766원(마이너스 없음), bank_account.balance 가 마지막 거래 balance_after(2,308,184원)와 일치, 재실행 전/후 행 수 동일(멱등), scenario_key='-1'/'-2' 등 다른 시나리오 데이터에 영향 없음(각각 164건/333건 card_approval 그대로 유지) 확인.

⚠️ 이 파일은 실제 사용자 본인의 IBK기업은행 계좌 거래내역(가맹점명·이용시각 등)을 원본으로 하며, 날짜만 이동하고 가맹점명·금액은 그대로 시드 SQL에 포함되어 있습니다. 원본의 실제 계좌번호·실명은 시드에 반영하지 않고 가상 값으로 대체했습니다. 저장소를 외부에 공유/푸시할 경우 실제 소비 위치·패턴이 노출될 수 있으니 주의하세요.

scenario_key='-4' (실거래 계좌내역 기반 카테고리 분류 테스트, 4번째 계좌 데이터)

별도 파일 src/main/resources/db/seed-v2-scenario-4.sql 로 분리돼 있습니다(2026-08-22 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario-4.sql 순서로 적용해야 합니다.

scenario_key='-2'와 같은 형식의 KB국민은행 계좌 거래내역조회(엑셀, 승인번호·매입구분 필드 없음, 총 202행, 조회기간 2026-05-232026-08-22)입니다. -2의 원본 조회기간(2026-02-232026-08-20)과 상당 부분 겹치는 동일 계좌의 최신 재조회본으로 보입니다(사용자 확인 완료, 의도된 재사용). 2주씩 미뤄달라는 기존 요청과 동일하게 월 단위 이동 없이 전 거래를 원본 시각 그대로 +14일 이동2026-06-06~2026-09-05 를 커버합니다(날짜 단순 덧셈이라 말일 clamp 불필요). 원본 202행 중 시드에 반영한 것은 그룹 A 22건 + 그룹 B 91건 + 그 외 실거래 입금 64건이고, 나머지 25건은 제외했습니다(모두 사용자 확인 후 확정):

  • 체크카드 취소 쌍 4행(카카오T택시_가승인 1쌍 + 인터넷상거래 1쌍, gubun='취소'/'취소된거래') — 실제로 청구되지 않음.
  • 간편결제 지갑 충전성 출금(FBS 출금) 16건, 전부 카카오페이/네이버페이충전 — 실제 최종 가맹점 미특정, 제외.
  • 캐시백/환불성 카드입금 3건(KB체크할인·KB체크취소) — 신규 지출이 아니라 제외.
  • 결산이자 1건은 소비가 아니지만 실제 잔액에 영향을 준 거래라 challengeCategory=NULL로 bank_transaction에만 반영(제외하지 않음).

이 원본에는 원래 상정했던 "가맹점 지출" 외에 지인·법인 실명이 찍히는 계좌 이체가 다수 섞여 있어(사용자와 사전 확인 후 항목별로 다르게 처리):

  • FBS입금(13건) + 전자금융(43건) = 56건, 전부 개인·법인 실명 입금 — 실명을 지우고 '지인 입금'으로 익명화한 뒤 challengeCategory=NULL인 순수 입금으로 반영.
  • 스마트출금 15건(토스 지인 송금) — 실명을 지우고 '지인 송금'으로 익명화해 그룹 A(카드 미경유 계좌 직접 출금, challengeCategory=NULL)로 편입.
  • 현금IC 7건(롯데마트몰수지·다이소 소액 결제) — 카드 상품이 아니라 계좌 직결 IC칩 결제라 card_approval 없이 그룹 A로 편입하되, 실제 가맹점 소비라 challengeCategory는 정상 매핑.
  • 인터넷입금이체 6건('사단법인사피엔스4...' 매월 15일 20만원+5만원=25만원 정기 입금) — 개인이 아니라 법인/단체명이라 실명 노출 우려가 낮아 그대로 유지하고 '정기수입'으로 반영.

신용카드 실거래는 원본에 전혀 없어(전부 체크카드 채널) 그룹 C는 완전히 비우고 card_bill도 만들지 않았습니다(최소 구성 원칙에 따른 빈 신용카드 1장만 생성).

가맹점명은 44개 소분류 표(scenario_key='2'/'4' 기준)에 매핑했고, 30개 가맹점 중 12개는 상호명만 있어 업종을 특정하기 어려워 가장 가까운 소분류로 추정 매핑했습니다(미니돌어린이대공원·가챠오션· 앨리스프랜즈·쿄우마·퍼니랜드럭키팝·보보랜드 → 레저(자녀 동반 오락시설 추정), 헥토파이낸셜· NICE결제대행·KCP·이니시스·카카오페이_NICE·인터넷상거래·오스카·롯데글로벌로지스 → 온라인쇼핑, sweetspot·레브레드 → 카페/간식 — 전체 근거는 seed-v2-scenario-4.sql 파일 상단 주석 참고, 사용자에게 표로 제시 후 "제안대로 진행" 확인 받음). 원본의 실거래 입금(지인 입금 56건 3,296,449원 + 정기수입 6건 750,000원 + 이자 708원)만으로 매월 지출을 넉넉히 웃돌아, -1/-2/-3/-5와 달리 별도 급여를 새로 추가하지 않았습니다.

로컬 검증 결과: card_approval 91건 · bank_transaction 177건(그룹A 22 + 그룹B 91 + 지인 입금 56 + 정기수입 6 + 이자 1) · card_bill 0건(신용카드 실거래 없음), 10개 소분류 등장(레저 40· 온라인쇼핑 17·편의점 15·장보기/마트 12·카페/간식 8·배달앱 2·경조사/선물·대중교통·생활용품· 택시/모빌리티 각 1건 + challengeCategory=NULL 79건), 거래일자 2026-06-06~2026-09-05 범위 내 확인, 체크카드 쌍은 correlationId 기준 양쪽 금액 전부 일치(불일치 0건), MIN(balance_after) 226,200원(마이너스 없음), bank_account.balance 가 마지막 거래 balance_after(2,370,379원)와 일치, 재실행 전/후 행 수 동일(멱등), scenario_key='-1'/'-2'/'-3'/'-5' 등 다른 시나리오 데이터에 영향 없음(각각 164건/333건/412건/247건 card_approval 그대로 유지) 확인.

⚠️ 이 파일은 실제 사용자 본인의 KB국민은행 계좌 거래내역(가맹점명·이용시각 등)을 원본으로 하며, 날짜만 이동하고 가맹점명·금액은 그대로 시드 SQL에 포함되어 있습니다. 원본의 실제 계좌번호·실명은 시드에 반영하지 않고 가상 값으로 대체했고, 지인·법인 실명이 찍힌 개인 간 송금·이체는 전부 익명화하거나(개인) 그대로 유지(법인/단체명만, 낮은 식별 위험) 처리해 제3자 실명 노출 문제를 최소화했습니다. 저장소를 외부에 공유/푸시할 경우 실제 소비 위치·패턴이 노출될 수 있으니 주의하세요.

scenario_key='-5' (실거래 계좌내역 기반 카테고리 분류 테스트, 3번째 계좌 데이터)

별도 파일 src/main/resources/db/seed-v2-scenario-5.sql 로 분리돼 있습니다(2026-08-22 추가). seed-v2.sql 이 넣는 financial_institution(KB국민은행 0004, KB국민카드 0381)에 의존하므로 schema-v2.sqlseed-v2.sqlseed-v2-scenario-5.sql 순서로 적용해야 합니다.

scenario_key='-2'/'-3'과 마찬가지로 원본이 "카드사 승인내역"이 아니라 KB국민은행 계좌 거래내역 조회(엑셀, 승인번호·매입구분 필드 없음, 총 588행, 조회기간 2026-02-232026-08-22)입니다. 사용자가 "2주씩 미뤄달라"고 명시적으로 요청해 월 단위 이동 없이 전 거래를 원본 시각 그대로 +14일 이동해 **2026-03-092026-09-05** 를 커버합니다(날짜 단순 덧셈이라 말일 clamp 불필요). 원본 588행 중 시드에 반영한 것은 그룹 A 17건 + 그룹 B 247건뿐이고, 나머지 324건은 제외했습니다(모두 사용자 확인 후 확정):

  • 체크카드 취소·환불 쌍 10행(놀유니버스티켓-문화 1쌍 + 카카오T택시_가승인 2쌍 + 네이버페이 2쌍, 거래일시·금액 완전 일치) — 실제로 청구되지 않음.
  • 신용카드(국민카드 "KB카드출금") 월별 합계 출금 7건 — 개별 카드 승인 원장이 원본에 전혀 없어 이중계산 검증을 통과할 수 없으므로 scenario_key='-2'/'-3'과 동일하게 그룹 C는 완전히 비우고, 이 7건은 challengeCategory=NULL 인 **그룹 A(카드 미연결 순수 계좌출금)**로 편입했습니다(사용자가 "그룹 C 생략, 그룹 A로 처리" 선택).
  • 간편결제 지갑 충전성 거래 225건(FBS출금·스마트출금·FBS입금·오픈뱅킹출금, 대부분 삼성월렛머니· 카카오페이·PAYCO·GSPay 앞) — 실제 최종 가맹점 미특정, 제외.
  • 비소비성 개인 자금 흐름 82건(전자금융·ATM입금·스마트입금·인터넷입금이체·카드입금 — 실업급여성 입금·반복 입금·지인 간 P2P 송금·ATM 현금입금·K-패스 환급금 등) — 소비가 아닌 계좌 이동이라 전부 제외하고 급여성 입금으로 대체했습니다(사용자가 "제외하고 급여성 입금으로 대체" 선택 — 제3자 실명 노출 문제도 함께 해소).
  • 결산이자 2건 + 금결원PG출금 1건 — 소비가 아니라 제외.

원본에 SKT 통신비 자동이체 10건(지로출금)만은 카드를 거치지 않는 순수 계좌 자동이체라 그룹 A(통신비, mcc 4814)로 반영했고, 위 국민카드 대금 출금 7건과 합쳐 그룹 A는 총 17건입니다. 신용카드는 구조 요구사항 충족용 빈 카드(실거래 없음)로만 생성했습니다.

가맹점명은 44개 소분류 표(scenario_key='2'/'4' 기준)에 매핑했고, 100개 가맹점 중 13개는 상호명만 있어 업종을 특정하기 어려워 가장 가까운 소분류로 추정 매핑했습니다((주)글림아티스트 → 뷰티, (주)백패커 → 온라인쇼핑(아이디어스 추정), 다다닷·코코일라·몽글몽글·크림슨파더·타래퀸대학로점 → 카페/간식, 미니돌어린이대공원 → 자녀, (주)이너부스 → 취미, 청킹·홈스테드대학로점 → 음식점/외식, 투파인드피터혜화점 → 레저, 네이버페이/카카오페이/이니시스류 PG성 결제 → 온라인쇼핑 — 전체 근거는 seed-v2-scenario-5.sql 파일 상단 주석 참고, 사용자에게 표로 제시 후 "제안된 기본값으로 진행" 확인 받음). 원본에 급여성 입금이 없어(개인 간 송금은 전부 제외) 계좌 시작 잔액 700,000원 + 매월(3~8월) 25일 900,000원("급여")을 추가했습니다(9월은 대상 기간이 9/5까지 나흘뿐이라 생략).

로컬 검증 결과: card_approval 247건 · bank_transaction 270건(그룹A 17 + 그룹B 247 + 급여 6) · card_bill 0건(신용카드 실거래 없음), 19개 소분류 등장(카페/간식 111·음식점/외식 51·편의점 15· 온라인쇼핑 12·앱·게임 12·레저 8·영화·공연·전시 6·배달앱 5·뷰티 5·약국 4·생활용품 4·OTT 4·병원 3· 도서 2·택시/모빌리티 2·취미/장보기·마트/자녀 각 1건 + 통신비 10건), 거래일자 2026-03-09~2026-09-04 범위 내 확인, 체크카드 쌍은 correlationId 기준 양쪽 금액 전부 일치(불일치 0건), MIN(balance_after) 395,580원(마이너스 없음), bank_account.balance 가 마지막 거래 balance_after(3,530,715원)와 일치, 재실행 전/후 행 수 동일(멱등), scenario_key='-1'/'-2'/'-3' 등 다른 시나리오 데이터에 영향 없음(각각 164건/333건/412건 card_approval 그대로 유지) 확인.

⚠️ 이 파일은 실제 사용자 본인의 KB국민은행 계좌 거래내역(가맹점명·이용시각 등)을 원본으로 하며, 날짜만 이동하고 가맹점명·금액은 그대로 시드 SQL에 포함되어 있습니다. 원본의 실제 계좌번호·실명은 시드에 반영하지 않고 가상 값으로 대체했습니다(개인 송금 상대방 실명이 포함된 거래는 전부 제외해 제3자 실명 노출 문제를 해소했습니다). 저장소를 외부에 공유/푸시할 경우 실제 소비 위치·패턴이 노출될 수 있으니 주의하세요.

개발 환경

  • Java 17
  • Spring MVC 5
  • Gradle
  • MyBatis
  • MySQL 8

데이터베이스 설정

기본 데이터베이스 이름은 financial_mock입니다.

CREATE DATABASE IF NOT EXISTS financial_mock
  DEFAULT CHARACTER SET utf8mb4
  DEFAULT COLLATE utf8mb4_unicode_ci;

로컬 DB 접속 정보는 src/main/resources/application.properties에서 관리합니다.

jdbc.url=jdbc:log4jdbc:mysql://localhost:3306/financial_mock
jdbc.username=root
jdbc.password=1234

디렉터리 구조

src/main/java/com/financial/mockserver
  config/              Spring 설정
  controller/          API controller
  domain/              mock 응답 제어용 내부 모델
  dto/                 API 응답 DTO
  mapper/              MyBatis mapper interface
  service/             서비스 인터페이스 및 구현체
  support/             공통 응답/trace helper

src/main/resources
  db/schema-v2.sql          현재 DB schema 기준
  db/seed-v2.sql            현재 seed 데이터 기준
  db/seed-v2-scenario2.sql  scenario_key='2' 거래내역 카테고리 테스트 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario3.sql  scenario_key='3' 카드 승인/은행 정합성 테스트 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario4.sql  scenario_key='4' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario5.sql  scenario_key='5' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario6.sql  scenario_key='6' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario7.sql  scenario_key='7' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario8.sql  scenario_key='8' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario9.sql  scenario_key='9' 카드 승인/은행 정합성 테스트, 병렬 사용자 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario-1.sql scenario_key='-1' 실거래 카드내역 기반 카테고리 분류 테스트 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario-2.sql scenario_key='-2' 실거래 계좌내역 기반 카테고리 분류 테스트 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario-3.sql scenario_key='-3' 실거래 계좌내역 기반 카테고리 분류 테스트, 2번째 계좌 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario-4.sql scenario_key='-4' 실거래 계좌내역 기반 카테고리 분류 테스트, 4번째 계좌 (seed-v2.sql 이후 적용)
  db/seed-v2-scenario-5.sql scenario_key='-5' 실거래 계좌내역 기반 카테고리 분류 테스트, 3번째 계좌 (seed-v2.sql 이후 적용)
  db/schema.sql             구버전 mock_codef_* schema
  db/seed.sql               구버전 seed
  db/init.sql               구버전 통합 실행 스크립트
  mapper/              MyBatis XML mapper
  application.properties
  mybatis-config.xml

documents/
  financial-mock-erd.svg
  IMPLEMENTATION_GUIDE.md
  API/기능 명세 참고 문서

구현 메모

  • domain 패키지는 금융 도메인 객체가 아니라 mock 응답 제어용 모델 중심입니다.
  • 금융 테이블은 현재 MyBatis XML에서 응답 DTO로 직접 매핑합니다.
  • 정상 시나리오는 DB 테이블 조회 결과로 응답을 조립합니다.
  • 오류/빈 데이터 같은 특수 시나리오는 fixture JSON을 반환합니다.
  • 실제 서비스 DB와 목 서버 DB를 섞지 않습니다.
  • 민감한 인증정보나 실제 계좌번호는 저장하지 않고, 마스킹된 테스트 값만 사용합니다.

참고 문서

  • documents/IMPLEMENTATION_GUIDE.md
  • documents/financial-mock-erd.svg
  • documents/CPR_기능명세서-v8.xlsm
  • documents/탕탕_API_연동규격_정의서_v1.0.xlsm

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages