Skip to content

fix : 파킹 카드 필드 V8 컬럼 연결 및 PRD A1~A3 리뷰 후속 정리 - #42

Draft
yuyeol3 wants to merge 7 commits into
yuyeol3/feat/prd-a1-a3from
yuyeol3/fix/parking-card-v8-fields
Draft

yuyeol3 wants to merge 7 commits into
yuyeol3/feat/prd-a1-a3from
yuyeol3/fix/parking-card-v8-fields

Conversation

@yuyeol3

@yuyeol3 yuyeol3 commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator

변경점 👍

#41(PRD A1~A3 이관) 위에 올리는 후속 PR입니다. 원본 PR(PNU-2026-AI-Hackathon/pnuai-c-07-finfin2#42) 리뷰에서 남은 항목을 처리합니다. #41이 먼저 머지되면 base를 main으로 바꿔주세요.

1. 파킹 카드 필드를 V8 컬럼과 연결 (f12559b)

#35에서 V8 마이그레이션으로 컬럼은 추가됐지만 엔티티에는 매핑되지 않은 상태였습니다.

  • ProductProperty에 maxRateApplicableMinAmount, maxRateApplicableMaxAmount, interestPaymentMethod를 매핑했습니다.
  • ParkingProductDto의 응답 필드를 바꿨습니다.
    • applicableLimit 삭제: 적금 전용 컬럼인 max_monthly_limit을 읽고 있었습니다.
    • maxRateApplicableMinAmount / maxRateApplicableMaxAmount 추가: 최고금리가 적용되는 잔액 범위로, 하한은 초과, 상한은 이하로 봅니다.
    • maxDepositAmount 추가: 적용 범위 정보가 없을 때 대신 표시할 최대 예치한도입니다.
    • interestPaymentMethod: "매일" 고정값 대신 공시 원문을 그대로 보냅니다.
  • 이 필드를 쓰는 곳은 Fin-FE에도 아직 없습니다.

2. 단기예치 상품 수를 상품 단위로 집계 (70e0237)

파킹통장은 옵션 단위인 parkingProducts.size()로 세고 있어서, 옵션이 여러 개인 상품이 중복으로 집계됐습니다. 예적금처럼 상품 ID로 distinct해서 셉니다. 지금 수집 데이터는 KFB 파킹이 상품당 옵션 1개라 실제 값은 달라지지 않습니다.

3. 정렬 테스트 정리 (b5888aa)

  • 기존 ShortTermSortingTest는 SearchService의 private 정렬 로직을 테스트 안에 복사해 두고 그 복사본을 검증하고 있었습니다. 그래서 탭B 은행 정렬의 reversed() 버그가 다시 생겨도 테스트가 통과했습니다.
    • collapseToBestPerProduct와 같은 방식으로, 정렬 메서드를 package-private static으로 열었습니다.
    • SearchServiceSortingTest(service 패키지)가 실제 메서드를 직접 호출합니다.
  • 호출하는 곳이 없던 sortedByAchievableRate와, 그 복사본을 검증하던 "탭D" 테스트 3개를 삭제했습니다. 실제 파킹 정렬은 ParkingProductServiceTest가 검증하고 있습니다.
  • LongTermSortingIntegrationTest를 추가해 searchUnified 결과로 탭B 정렬을 검증합니다.
    • 은행: 실수령액 내림차순
    • 정부: 환산수익률이 낮아도 기여금 총액이 크면 먼저
    • 상품명순으로 정렬하거나 정렬 기준을 잘못 잡으면 순서가 달라지도록 픽스처를 구성했습니다.

4. 코드 품질 정리 (ecc4e99, 06b9942, e794334)

코드 품질 리포트에서 #41(원본 PR 코드)이 main보다 나빠진 항목 중 범위가 작은 것들을 처리했습니다.

  • 호출하는 곳이 없는 코드 삭제: MatchScoreService.isGovBankConditionExcluded(PMD 지적), effectiveAmount 2개, SearchRequestDto.isShortTerm/isLongTerm(keywords), ProductCategoryEnum.fromKeyword, KeywordValueEnum.isShortTerm/isLongTerm. 실제 대분류 결정은 fromSaveTrm(getSaveTrm(keywords)) 경로만 쓰므로 CategoryRoutingTest도 그 경로를 검증하도록 바꿨습니다.
  • 인접 기간 배점 테스트 보강: 기존 테스트는 12개월 선택만, 그것도 "0 초과 20 미만"으로만 확인했습니다(isAdjacentPeriod 분기 29개 중 23개 미검증). 1·3·6·12·24·36개월 각각에서 바로 앞뒤 구간은 정확 매칭의 정확히 절반, 그 외는 0점인지 파라미터화 테스트 19개로 검증합니다.
  • MatchScoreService의 V2·TOP3 가중치 재분배 로직이 27줄 그대로 중복되어 있어 redistributeInactive로 합쳤습니다. TOP3 재분배는 직접 검증하는 테스트가 없어서 리팩터링 전에 특성화 테스트 2개를 먼저 추가했습니다.

로컬 기준 결과는 PMD 이슈 20건 → 18건, 중복 블록 2개 → 1개(main에 원래 있던 계산기 중복)입니다.

테스트 💻

  • 인접 기간 테스트는 6개월의 인접 구간을 일부러 틀리게 바꿨을 때 2개 케이스가 실패하는 것을 확인했습니다.
  • 정렬 테스트는 mutation 방식으로 확인했습니다. 원래의 reversed() 버그와 "정부상품을 환산수익률 우선으로 정렬" 변경을 일부러 넣었을 때 SearchServiceSortingTest 2개와 LongTermSortingIntegrationTest 2개가 실패합니다.
  • 파킹 DTO 테스트와 상품 수 테스트는 구현 전에 실패하는 것을 확인했습니다. 상품 수는 기대 4, 실제 5였습니다.
  • ./gradlew test(367개)와 ./gradlew integrationTest(125개)가 모두 통과합니다. 엔티티 매핑은 ddl-auto: validate로 V8 스키마와 일치하는 것을 확인했습니다.

비고 ✏

  • #37을 대체합니다. base PR의 마이그레이션 번호 변경(V7 → V9)에 맞춰 다시 올렸고, b192d2b에서 LongTermSortingIntegrationTest 주석의 번호만 고쳤습니다.
  • 미성년 기준이 age < 17로 구현되어 있습니다(원본 PR). PRD 기준과 맞는지 확인이 필요합니다.
  • KFB product_source 행은 Flyway 시드가 없고 수집기(Fin-API)가 첫 동기화 때 생성합니다. 그래서 Flyway만 적용된 테스트 DB에는 이 행이 없어 테스트 픽스처의 파킹 상품은 FSS 소스로 넣었습니다. 파킹 목록은 findByType(PARKING)으로 유형만 보므로 결과에는 영향이 없습니다.

- ProductProperty에 V8 컬럼(max_rate_applicable_min/max_amount, interest_payment_method) 매핑
- 최고금리 적용 한도: 적금 전용 max_monthly_limit 대신 적용 범위 하한/상한으로 응답
- 적용 범위가 없을 때 표시할 최대 예치한도(max_deposit_amount) 함께 응답
- 이자지급방식: "매일" 고정값 대신 공시 원문 사용
- SearchService 정렬 메서드를 package-private static으로 열고 SearchServiceSortingTest에서 직접 호출
  (복사한 로직을 검증하던 ShortTermSortingTest 대체, collapseToBestPerProduct와 같은 방식)
- 호출처 없는 sortedByAchievableRate와 그 복사본 테스트(탭D) 제거. 파킹 정렬은 ParkingProductServiceTest가 검증
- LongTermSortingIntegrationTest: searchUnified 결과로 탭B 은행(실수령액순)·정부(기여금총액순) 정렬 검증
- MatchScoreService.isGovBankConditionExcluded (PMD UnusedPrivateMethod)
- SearchRequestDto/DetailedOptionsDto.effectiveAmount, SearchRequestDto.isShortTerm/isLongTerm(keywords)
- ProductCategoryEnum.fromKeyword, KeywordValueEnum.isShortTerm/isLongTerm
실제 대분류 결정은 SearchService.determineCategory(fromSaveTrm(getSaveTrm(keywords)))만 쓰므로
CategoryRoutingTest도 그 경로로 검증하도록 바꿨다.
기존 테스트는 12개월 선택(24·10개월 상품)만, 그것도 "0 초과 20 미만"으로만 확인했다.
1·3·6·12·24·36개월 각각에 대해 바로 앞뒤 구간은 정확 매칭의 정확히 절반, 그 외는 0점인지 검증한다.
distributeWeights(V2)와 distributeTop3Weights가 같은 재분배 로직(미선택 축 가중치를 활성 축에 비례 배분)을
복사해 쓰고 있었다(CPD 27줄 중복). redistributeInactive로 합쳤다.
TOP3 재분배는 직접 검증하는 테스트가 없어 리팩터링 전에 특성화 테스트를 추가했다.
@github-actions

Copy link
Copy Markdown

Backend Code Health Report

Commit: b192d2b

Metric Current Base Change
Line Coverage 89.7% N/A —
Branch Coverage 73.4% N/A —
Code Health 92.8 (A) N/A —
Duplicated Lines 0.4% N/A —
High-complexity Methods 13 N/A —
PMD Issues 18 N/A —

Attention

  • src/main/java/apptive/fin/search/service/ProductDetailService.java:113 — Cognitive Complexity 27 / Cyclomatic Complexity 25
  • src/main/java/apptive/fin/myfin/service/MyFinService.java:216 — Cognitive Complexity 19 / Cyclomatic Complexity 10
  • src/main/java/apptive/fin/search/service/SearchService.java:176 — Cognitive Complexity 18
  • Duplicated block (16 lines): src/main/java/apptive/fin/calculator/service/DepositRateCalculator.java:46 ↔ src/main/java/apptive/fin/calculator/service/SavingRateCalculator.java:60

Warnings

  • Base branch snapshot unavailable: [Errno 2] No such file or directory: 'build/quality/baseline/metrics.json'

Informational report only — these metrics do not block merging.

@yuyeol3
yuyeol3 marked this pull request as draft October 26, 2026 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant