Skip to content

[HSC-416] Instant -> LocalDateTime 파싱 오류 수정#275

Merged
tkv00 merged 1 commit into
mainfrom
hotfix/HSC-416
Mar 31, 2026
Merged

[HSC-416] Instant -> LocalDateTime 파싱 오류 수정#275
tkv00 merged 1 commit into
mainfrom
hotfix/HSC-416

Conversation

@tkv00
Copy link
Copy Markdown
Contributor

@tkv00 tkv00 commented Mar 31, 2026

📝작업 내용


👀변경 사항


🎫 Jira Ticket

  • Jira Ticket: HSC-416

#️⃣관련 이슈


@tkv00 tkv00 added 🐛 fix 기능에 대한 버그 수정 🗂️ area: BE 백엔드 영역 🔥 priority: P0 즉시 처리 필요(서비스/데모 블로커) 🏷️ release 릴리즈 준비/버전 태깅/릴리즈 노트/릴리즈 브랜치 작업 release:patch 버전 patch bump: X.Y.(Z+1) deploy:api-server 배포 대상: customer-api labels Mar 31, 2026
@github-actions github-actions Bot added Infra Team ☁️ area: INFRA 인프라/운영/배포 영역 labels Mar 31, 2026
@github-actions github-actions Bot changed the title Instant -> LocalDateTime 파싱 오류 수정 [HSC-416] Instant -> LocalDateTime 파싱 오류 수정 Mar 31, 2026
@tkv00 tkv00 merged commit 731bdb8 into main Mar 31, 2026
10 checks passed
@github-actions
Copy link
Copy Markdown

🧪 Test Coverage Report (JaCoCo)

overall__line overall__branch changed__line changed__branch

기준(soft, workflow는 실패 안 함): Overall line 70% / branch 50%, Changed line 80% / branch 60% · Generated: 2026-03-31 21:27 UTC

Scope Line Branch Line Graph Branch Graph Verdict
Overall 40.5% 29.4% ████████░░░░░░░░░░░░ ██████░░░░░░░░░░░░░░ ⚠️⚠️
Changed 0.0% N/A ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░ ⚠️

Package line spark (sample): ▃▂▁▂▂▄▄·▇█▁▆▆▆·▆▁▁▆█▇▃▁▁▁██▁▁▃
Package branch spark (sample): ▃▁·▁▁·▁·▇··▅▆▅·▅▁▁▅▇▇▂▁·▁·█▁▁▁

📦 Package coverage (worst 10)

Rank Package Line Branch Lines Line Graph Branch Graph
1 site.holliverse.shared.monitoring 0.0% N/A 76 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
2 site.holliverse.customer.application.usecase.log 0.0% 0.0% 69 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
3 site.holliverse.customer.coupon.application 0.0% 0.0% 61 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
4 site.holliverse.infra.kafka.consumer 0.0% 0.0% 44 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
5 site.holliverse.customer.integration.fastapi 0.0% 0.0% 28 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
6 site.holliverse.customer.integration.external 0.0% 0.0% 28 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
7 site.holliverse.customer.application.usecase.counsel 0.0% 0.0% 14 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
8 site.holliverse.customer.coupon.web 0.0% 0.0% 12 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
9 site.holliverse.shared.config.runtime 0.0% N/A 11 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
10 site.holliverse.customer.web.util 0.0% 0.0% 8 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░

🧨 Lowest coverage classes (worst 10)

Rank Class Line Branch Lines Line Graph Branch Graph
1 site.holliverse.customer.application.usecase.log.UserLogService 0.0% 0.0% 52 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
2 site.holliverse.shared.monitoring.CustomerMetrics 0.0% N/A 50 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
3 site.holliverse.infra.kafka.consumer.RecommendationKafkaConsumer 0.0% 0.0% 44 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
4 site.holliverse.customer.application.usecase.recommendation.RecommendationKafkaConsumeUseCase 0.0% 0.0% 42 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
5 site.holliverse.admin.application.usecase.CalculateLogChurnScoreService 0.0% 0.0% 38 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
6 site.holliverse.admin.application.usecase.CalculateChurnScoreService 0.0% 0.0% 37 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
7 site.holliverse.customer.coupon.application.UseMemberCouponUseCase 0.0% 0.0% 34 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
8 site.holliverse.admin.application.usecase.ChurnRiskReason$ReasonCode 0.0% 0.0% 31 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
9 site.holliverse.customer.integration.fastapi.FastApiRecommendationClient 0.0% 0.0% 28 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
10 site.holliverse.customer.integration.external.AdminLogFeaturesClient 0.0% 0.0% 28 ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░
🧩 Changed files coverage breakdown (1 files)
File Line Branch Lines Verdict Line Graph Branch Graph
src/main/java/site/holliverse/admin/application/usecase/HandleLogFeatureUseCase.java 0.0% N/A 14 ⚠️ ░░░░░░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░

🔎 HTML 리포트: Actions → Artifacts → jacoco-html · XML: jacoco-xml

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

이번 PR은 HandleLogFeatureUseCase에서 Instant를 LocalDate로 변환하는 로직을 resolveBaseDate 메서드로 분리하여 개선하였습니다. 다만, request.timeStamp()가 null일 경우 resolveBaseDate 내부에서는 방어되지만 LogFeatureEvent 생성 시에는 null이 그대로 전달되어 잠재적인 NullPointerException 발생 위험이 식별되었습니다. 또한, 하드코딩된 타임존 문자열을 상수로 관리하고 불필요한 Optional 처리를 제거하여 로직을 단순화할 것을 권장합니다.

Comment on lines 36 to 41
calculateLogChurnScoreService.calculateAndStore(
request.memberId(),
LocalDate.from(request.timeStamp()),
resolveBaseDate(request.timeStamp()),
List.of(new LogFeatureEvent(
resolveEventId(request),
request.timeStamp(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

🛡️ Code Review Report

1. 🔍 요약 (Summary)

InstantLocalDate로 변환하는 과정에서 발생하는 파싱 오류를 수정하였습니다. 다만, null 처리 로직의 불일치로 인한 잠재적 NullPointerException 위험이 발견되었습니다.

2. 🛑 Blocking Issues (Must Fix)

  • [위반 규칙]: 로직 일관성 결여 및 잠재적 NPE 위험
  • [위치]: HandleLogFeatureUseCase.java (Line 36-41)
  • [문제 이유]: resolveBaseDate 내부에서는 null 발생 시 Instant.now()를 사용하도록 방어 코드가 작성되어 있으나, 41라인에서 LogFeatureEvent를 생성할 때는 원본 request.timeStamp()를 그대로 전달합니다. 이로 인해 timeStampnull일 경우 CalculateLogChurnScoreService에서 event.timestamp().toString() 호출 시 NPE가 발생합니다.
  • [해결 제안]: execute 메서드 시작 부분에서 Instant 값을 확정하여 일관되게 사용하세요.
Suggested change
calculateLogChurnScoreService.calculateAndStore(
request.memberId(),
LocalDate.from(request.timeStamp()),
resolveBaseDate(request.timeStamp()),
List.of(new LogFeatureEvent(
resolveEventId(request),
request.timeStamp(),
Instant timestamp = Optional.ofNullable(request.timeStamp()).orElseGet(Instant::now);
calculateLogChurnScoreService.calculateAndStore(
request.memberId(),
resolveBaseDate(timestamp),
List.of(new LogFeatureEvent(
resolveEventId(request),
timestamp,

Comment on lines +58 to +63
private LocalDate resolveBaseDate(Instant timestamp) {
return Optional.ofNullable(timestamp)
.orElseGet(Instant::now)
.atZone(ZoneId.of("Asia/Seoul"))
.toLocalDate();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

🔍 타임존 하드코딩 및 로직 단순화

  • 위치: HandleLogFeatureUseCase.java (Line 58-63)
  • 문제 이유: "Asia/Seoul" 타임존이 하드코딩되어 있어 유지보수성이 떨어집니다. 또한 DTO에 @NotNull이 적용되어 있으므로 Optional 처리를 제거하여 로직을 단순화할 수 있습니다.
  • 해결 제안: 타임존을 상수로 분리하고 로직을 단순화하세요.
    private LocalDate resolveBaseDate(Instant timestamp) {
        return timestamp.atZone(ZoneId.of("Asia/Seoul"))
                .toLocalDate();
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🗂️ area: BE 백엔드 영역 ☁️ area: INFRA 인프라/운영/배포 영역 deploy:api-server 배포 대상: customer-api 🐛 fix 기능에 대한 버그 수정 Infra Team 🔥 priority: P0 즉시 처리 필요(서비스/데모 블로커) release:patch 버전 patch bump: X.Y.(Z+1) 🏷️ release 릴리즈 준비/버전 태깅/릴리즈 노트/릴리즈 브랜치 작업

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant