Skip to content

[ Refactor ] - 월간 AI 리포트 소비 집계 기준 정합성 수정 #160

Description

@bigwaveBigwave

배경

이슈 #140에서 미분석 거래를 매일 분류하여 TXN_ANALYSIS에 저장하는 일간 소비 분류 배치를 구현했습니다.

현재 처리 흐름은 다음과 같습니다.

매일 02:00
→ TXN_ANALYSIS가 없는 거래 조회
→ Spring 사전 분류 또는 FastAPI 소비 분류
→ 소비·비소비 분석 결과를 TXN_ANALYSIS에 저장

매월 1일 03:00
→ 전월 소비 데이터 집계
→ 월간 AI 리포트 생성

그러나 현재 월간 소비 집계는 #140에서 확정한 거래 유형별 TXN_ANALYSIS 저장 계약과 일부 일치하지 않습니다.

현재 MonthlyExpenseMapper에는 다음과 같은 기존 기준이 남아 있습니다.

  • LOAN 거래에 TXN_ANALYSIS가 생성되지 않는다는 전제
  • LOAN 정상 상환액 중 loan_interest_amount만 소비로 집계
  • INSTALLMENT 거래의 소비 금액 산정 시 in_amount가 아닌 out_amount 사용 가능성
  • LOANTXN_ANALYSIS 결과가 아닌 별도 SQL 조건으로 집계

#140 이후에는 ORDINARY, INSTALLMENT, LOAN 거래의 소비 여부와 카테고리, 지출 유형이 TXN_ANALYSIS에 저장되므로 월간 소비 집계도 해당 분석 결과를 기준으로 통일해야 합니다.

관련 이슈

목표

월간 AI 리포트 생성 시 대상 연월의 TXN_ANALYSIS 결과를 기준으로 총소비, 고정지출 및 카테고리별 소비를 일관되게 집계합니다.

예를 들어 2026년 7월 1일에 월간 배치가 실행되면 다음 범위의 데이터를 사용합니다.

targetYearMonth = 2026-06

조회 시작: 2026-06-01 이상
조회 종료: 2026-07-01 미만
2026-06-01 <= tran_date < 2026-07-01

확정 집계 계약

공통 포함 조건

월간 소비 집계에는 다음 조건을 만족하는 거래만 포함합니다.

TXN_ANALYSIS 존재
AND TXN_ANALYSIS.is_consumption = TRUE

TXN_ANALYSIS가 없거나 is_consumption = FALSE인 거래는 월간 소비에서 제외합니다.

계좌가 이후 비활성화되었더라도 과거 소비 내역이 누락되지 않도록 현재 계좌 활성 상태는 조회 조건으로 사용하지 않습니다.

거래 유형별 소비 금액

거래 유형 월간 소비 집계 금액
ORDINARY out_amount
INSTALLMENT in_amount
LOAN 정상 상환 out_amount

금액이 NULL인 경우에는 0으로 처리합니다.

ORDINARY

일반 출금 거래 중 TXN_ANALYSIS.is_consumption = TRUE인 거래의 out_amount를 소비로 집계합니다.

INSTALLMENT

적금·할부성 납입 거래는 거래 구조상 납입액이 in_amount에 저장되므로, TXN_ANALYSIS.is_consumption = TRUE인 거래의 in_amount를 소비로 집계합니다.

LOAN

정상 대출 상환 거래는 #140의 사전 분류 결과에 따라 다음과 같이 저장됩니다.

is_consumption = TRUE
category = FINANCE
expense_type = FIXED

월간 소비 집계에서는 정상 상환 거래의 out_amount 전체를 소비로 반영합니다.

대출 신규·실행·증액 등 비소비 거래는 다음과 같이 저장되므로 집계에서 제외됩니다.

is_consumption = FALSE
category = NULL
expense_type = NULL

따라서 월간 집계 SQL에서 대출 거래 여부를 키워드로 다시 판정하거나 loan_interest_amount만 별도로 합산하지 않습니다.

집계 항목

총소비

대상 연월의 소비 거래 금액을 거래 유형별 기준에 따라 합산합니다.

totalExpense
= ORDINARY 소비 out_amount 합계
+ INSTALLMENT 소비 in_amount 합계
+ LOAN 소비 out_amount 합계

고정지출

다음 조건을 만족하는 거래 금액을 거래 유형별 기준에 따라 합산합니다.

TXN_ANALYSIS.is_consumption = TRUE
AND TXN_ANALYSIS.expense_type = FIXED

카테고리별 소비

TXN_ANALYSIS.category를 기준으로 거래 유형별 소비 금액을 합산합니다.

GROUP BY TXN_ANALYSIS.category

소비 거래인데 카테고리가 NULL 또는 빈 값인 비정상 데이터가 존재하는 경우에는 기존 정책에 따라 ETC로 처리합니다.

다음 정합성을 만족해야 합니다.

총소비 금액
= 카테고리별 소비 금액 합계

월간 AI 리포트 연동 흐름

기존 월간 리포트 오케스트레이션의 연월 계산과 Client 호출 구조를 유지합니다.

MonthlyAiReportScheduler
→ MonthlyAiReportOrchestrationService.runLastMonthBatch()
→ Asia/Seoul 기준 전월 계산
→ MonthlyExpenseQueryClient.findMonthlyExpense(userId, targetYearMonth)
→ account-service 월간 소비 집계
→ 총소비·고정지출·카테고리별 소비 반환
→ AI 리포트 생성

예:

2026년 7월 1일 03:00 실행
→ targetYearMonth = 2026-06
→ 6월 1일 이상, 7월 1일 미만 거래 집계

전월 대비 소비 증감률 계산을 위해 기존과 같이 대상 월의 직전 월 데이터도 조회합니다.

현재 월: 2026-06
비교 월: 2026-05

구현 범위

account-service

  • MonthlyExpenseMapper의 거래 유형별 금액 계산 수정
  • TXN_ANALYSIS.is_consumption 기준으로 집계 조건 통일
  • LOAN 전용 이자 집계 및 키워드 판정 제거
  • 총소비 집계 수정
  • 고정지출 집계 수정
  • 카테고리별 소비 집계 수정
  • 반개구간 월 조회 조건 유지

ai-service

  • 기존 MonthlyAiReportOrchestrationService의 전월 계산 및 Client 호출 구조 유지
  • 대상 월과 비교 월 조회가 올바른지 회귀 테스트
  • 수정된 소비 집계 결과가 리포트의 다음 항목에 반영되는지 검증
    • totalExpense
    • availableFunds
    • expenseChangeRate
    • topCategories
    • FastAPI 요청의 categoryExpenses

제외 범위

이번 이슈에서는 다음 작업을 하지 않습니다.

  • 일간 소비 분류 규칙 변경
  • FastAPI 소비 분류 요청·응답 계약 변경
  • TXN_ANALYSIS 테이블 구조 변경
  • 월간 AI 리포트 Scheduler 실행 시간 변경
  • 월간 리포트 생성 대상 사용자 정책 변경
  • PDF 레이아웃 변경
  • 수동·자동 이메일 발송 로직 변경
  • 발송 이력 및 재시도 기능 추가
  • BFF API 계약 변경
  • 카카오톡 발송 기능 추가
  • 무관한 .idea 설정 변경

테스트 항목

월 범위

  • 7월 1일 실행 시 6월 1일 이상, 7월 1일 미만 거래 집계
  • 5월 31일 거래 제외
  • 6월 1일 거래 포함
  • 6월 30일 거래 포함
  • 7월 1일 거래 제외
  • 연말·연초 경계 처리
    • 2027년 1월 실행 시 2026년 12월 집계

소비 여부

  • TXN_ANALYSIS.is_consumption = TRUE 거래 포함
  • is_consumption = FALSE 거래 제외
  • TXN_ANALYSIS가 없는 거래 제외
  • 비활성 계좌의 과거 소비 거래 포함

거래 유형별 금액

  • ORDINARY 소비 거래의 out_amount 집계
  • INSTALLMENT 소비 거래의 in_amount 집계
  • LOAN 정상 상환 거래의 out_amount 전체 집계
  • LOAN 신규·실행·증액 비소비 거래 제외
  • 거래 유형별 대상 금액이 NULL인 경우 0 처리

집계 정합성

  • 총소비와 카테고리별 소비 합계 일치
  • expense_type = FIXED인 소비 거래만 고정지출에 포함
  • 비소비 거래가 총소비·고정지출·카테고리별 소비에 포함되지 않음
  • category가 비어 있는 소비 거래의 ETC 처리
  • 기존 일반 소비 카테고리 집계 회귀 검증

월간 AI 리포트

  • 대상 월 소비 조회 결과가 totalExpense에 반영
  • availableFunds = totalIncome - totalExpense 검증
  • 직전 월 소비와 비교한 expenseChangeRate 검증
  • 전체 카테고리가 FastAPI 요청에 전달되는지 검증
  • 상위 카테고리 및 기타 집계 결과 검증

완료 조건

  • 월간 집계가 #140의 TXN_ANALYSIS 저장 계약과 일치함
  • 대상 연월이 반개구간으로 정확하게 조회됨
  • ORDINARY, INSTALLMENT, LOAN의 소비 금액이 확정 계약대로 집계됨
  • 총소비와 카테고리별 소비 합계가 일치함
  • 고정지출이 TXN_ANALYSIS.expense_type 기준으로 계산됨
  • 기존 월간 AI 리포트 생성 흐름에 회귀 오류가 없음
  • account-service 및 ai-service 관련 테스트 통과
  • 전체 관련 빌드 성공
  • 무관한 파일 및 .idea 파일이 변경되지 않음

검증 명령

./gradlew :services:account-service:test
./gradlew :services:ai-service:test
./gradlew :services:account-service:build
./gradlew :services:ai-service:build

필요한 경우 전체 조립 상태도 확인합니다.

./gradlew :common:test \
  :services:account-service:test \
  :services:ai-service:test \
  :services:bff-service:test \
  :api:test \
  :api:war

참고 사항

현재 월 범위 계산과 오케스트레이션의 월별 소비 조회 호출은 이미 구현되어 있습니다.

이번 작업의 핵심은 오케스트레이션에 새로운 월 조회 구조를 추가하는 것이 아니라, account-service의 월간 소비 집계가 #140 이후의 TXN_ANALYSIS 계약과 일치하도록 수정하는 것입니다.

구현 완료 후 다음 문서도 함께 최신화합니다.

  • API 명세서
  • WBS
  • 기획안
  • 발표 PPT

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions