Skip to content

Conversation

@yangjiae12
Copy link
Member

@yangjiae12 yangjiae12 commented Jan 3, 2026

#️⃣ 연관된 이슈

관련된 이슈 번호를 적어주세요.
Close #174

✨ 작업 내용 (Summary)

이번 PR에서 작업한 내용을 간략히 설명해주세요. (이미지 첨부 가능)

챌린지의 중도 참여 로직을 도입하였습니다. 이때 챌린지 연장 알림이 보내진 후에 참여하는 챌린저들을 위해 라운드가 n일 남았다는 정보를 제공해야 하는데, 이는 챌린지 상단 정보 조회 API의 remainDays를 사용합니다.

또한 시간 의존성으로 인해 발생하던 테스트 버그(자정 전후로 테스트 실행 시 LocalTime 계산 오류로 빌드 실패)를 해결하여 빌드 안정성을 확보했습니다.


✅ 변경 사항 체크리스트

다음 항목들을 확인하고 체크해주세요.

  • 코드에 영향이 있는 모든 부분에 대한 테스트를 작성하고 실행했나요?
  • 문서를 작성하거나 수정했나요? (필요한 경우)
  • 중요한 변경 사항이 팀에 공유되었나요?

🧪 테스트 결과

코드 변경에 대해 테스트를 수행한 결과를 요약해주세요.

  • 테스트 환경: 로컬
  • 테스트 방법: Swagger, 단위 테스트(ChallengeServiceInfoTest)
  • 결과 요약: (예: 모든 테스트 통과, 새로운 테스트 케이스 3개 추가 완료)
  • 중도 참여 검증 및 시간 버그 수정

📸 스크린샷

관련된 스크린샷 또는 GIF가 있다면 여기에 첨부해주세요.

챌린지 중도 참여 스크린샷
미참여자이며 진행중임을 확인 image
중도 참여 확인 image
테스트 코드 결과 image

💬 리뷰 요구사항

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요.

테스트 안정성: LocalTime.MIN/MAX를 사용해 시간 의존성을 제거한 방식


📎 참고 자료

관련 문서, 레퍼런스 링크 등이 있다면 여기에 첨부해주세요.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 진행 중인 챌린지에서 게스트 사용자도 참가 가능하도록 확대
  • 버그 수정

    • 챌린지 참가 요청 검증 조건 완화 - 종료된 챌린지에서만 차단
    • 챌린지 참가 버튼 표시 로직 개선 - 공간 여부에 따라 동적으로 결정
  • 테스트

    • 시간 기반 테스트 안정성 개선으로 불필요한 실패 제거

✏️ Tip: You can customize this high-level summary in your review settings.

- 챌린지가 진행 중(ONGOING)이더라도 정원이 남았다면 참여할 수 있도록 검증 로직 수정
- 미참여자가 진행 중인 챌린지 조회 시 '참가하기' 버튼이 노출되도록 버튼 상태 결정 로직 개선
- 챌린지 종료(FINISHED) 상태가 아닌 경우 모든 모집 단계에서 참여 가능하도록 완화
- ChallengeServiceInfoTest에 상황 9(진행 중인 챌린지 + 자리 있음 -> JOIN) 케이스 추가
- 상태가 ONGOING일 때도 참가하기 버튼이 정상 반환되는지 검증
- LocalTime.now() 기반의 상대적 시간 계산을 고정 시간 및 MIN/MAX 상수로 교체
- 자정 전후 테스트 실행 시 발생하던 시간 역전(start > end) 버그 해결
- 테스트 데이터 생성 시 비즈니스 규칙(인증 종료 시간 > 시작 시간)을 준수하도록 수정
@yangjiae12 yangjiae12 self-assigned this Jan 3, 2026
@yangjiae12 yangjiae12 added 🐞 bug 버그 이슈 🌟 feat 새로운 기능 개발 labels Jan 3, 2026
@yangjiae12 yangjiae12 linked an issue Jan 3, 2026 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link

coderabbitai bot commented Jan 3, 2026

📝 Walkthrough

Walkthrough

챌린지 참가 로직이 완화되었습니다. 가입 요청 검증은 완료 상태만 차단하도록 변경되었으며, 버튼 상태 결정에서 비참가자의 상태별 조건 제한이 제거되었습니다. 테스트는 시간 기반 불안정성을 해결하기 위해 고정된 시간 범위를 사용하도록 수정되었고, 진행 중인 챌린지 참가 시나리오가 추가되었습니다.

Changes

Cohort / File(s) 요약
참가 로직 완화
src/main/java/com/hrr/backend/domain/challenge/service/ChallengeServiceImpl.java
validateJoinRequest: FINISHED 상태만 차단하도록 변경 (이전: UPCOMING/RECRUITING만 허용)
resolveButtonStatus: 비참가자의 상태 조건 제거, 스페이스 가용성만 기준으로 JOIN 반환
테스트 안정성 및 커버리지
src/test/java/com/hrr/backend/domain/challenge/service/ChallengeServiceInfoTest.java
LocalTime.now() 의존성 제거, 고정된 시간 윈도우(9:00–18:00, 00:00–00:01, LocalTime.MIN/MAX) 적용
새 테스트 추가: guest_ongoing_hasSpace_returns_JOIN (진행 중 상태에서 스페이스 있을 때 참가 가능 검증)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

참가의 문이 활짝 열렸네 🚪
FINISHED만 못 들어와도
시간은 더 이상 흔들리지 않고
진행 중이어도 스페이스 있으면 JOIN! ✨
테스트는 흔들지 않는 기초 위에 ⏰

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 중도 참여 로직 구현 및 테스트 코드 수정이라는 주요 변경사항을 명확하게 요약하며, 실제 코드 변경(validateJoinRequest 및 resolveButtonStatus 로직 완화, 테스트 안정화)과 완벽하게 일치합니다.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/test/java/com/hrr/backend/domain/challenge/service/ChallengeServiceInfoTest.java (3)

66-66: 시간 의존성 버그 수정 완료! 🎉

LocalTime.now() 기반의 동적 시간 계산을 고정된 시간 범위로 교체하여 자정 전후 발생하던 테스트 불안정성을 해결했습니다. 전략이 명확합니다:

  • Lines 66, 95: 9:00-18:00 - 실제 인증 시간대를 시뮬레이션하는 현실적인 범위
  • Line 121: 00:00-00:01 - 현재 시간이 범위 밖임을 보장하는 좁은 창
  • Lines 145, 172: MIN-MAX - 시간이 제한 요소가 되지 않아야 하는 테스트
Line 121 개선 제안

00:00-00:01 범위는 극히 드물지만 테스트가 정확히 자정에 실행될 경우 범위 내에 포함될 수 있습니다. 더 안전한 방법은 과거 시간대를 사용하는 것입니다:

-        setVerificationTime(challenge, LocalTime.of(0, 0), LocalTime.of(0, 1));
+        setVerificationTime(challenge, LocalTime.of(2, 0), LocalTime.of(3, 0));

또는 LocalTime.now().isBefore(start)를 보장하는 미래 시간을 사용할 수도 있습니다.

참고: Java 시간 API의 불변성과 테스트 안정성에 대해 더 알고 싶다면 Baeldung의 Testing Date and Time 가이드를 추천합니다.

Also applies to: 95-95, 121-121, 145-145, 172-172


260-260: 시간 의존성이 남아있습니다

이 테스트는 FINISHED 상태를 검증하므로 시간대가 실제 로직에 영향을 주지 않습니다. 하지만 LocalTime.now()를 사용하면 다른 테스트에서 제거한 시간 의존성이 다시 도입됩니다. 일관성을 위해 고정 시간을 사용하는 것이 좋습니다.

제안하는 수정
-        setVerificationTime(challenge, LocalTime.now().minusHours(1), LocalTime.now().plusHours(1));
+        setVerificationTime(challenge, LocalTime.of(9, 0), LocalTime.of(18, 0));

또는 더 명시적으로:

-        setVerificationTime(challenge, LocalTime.now().minusHours(1), LocalTime.now().plusHours(1));
+        setVerificationTime(challenge, LocalTime.MIN, LocalTime.MAX);

275-298: 중도 참여 시나리오 테스트 추가 완료! ✅

ONGOING 상태의 챌린지에 자리가 있을 때 미참여자가 JOIN 버튼을 볼 수 있는지 검증하는 테스트가 추가되었습니다. PR 목표인 중도 참여 로직의 핵심 시나리오를 커버하고 있습니다.

테스트 커버리지를 더 강화하려면 다음 시나리오를 추가로 검증하는 것을 권장합니다:

  1. ONGOING + 만석 케이스: 진행 중이지만 정원이 찬 경우 WAITLIST 반환 확인
  2. 실제 참여 검증: joinChallenge 메서드가 ONGOING 상태에서 정상 동작하는지 통합 테스트 추가
추가 테스트 예시
@Test
@DisplayName("상황 10: 미참여자 + 진행중(ONGOING) + 만석 -> WAITLIST")
void guest_ongoing_full_returns_WAITLIST() {
    // Given
    Long challengeId = 1L;
    User user = mock(User.class);
    Challenge challenge = mock(Challenge.class);

    // 조건: 진행 중이지만 만석
    setChallengeStatus(challenge, ChallengeStatus.ONGOING, 10, 10);
    setRoundDate(challenge, LocalDate.now().minusDays(5));

    // Mocking
    mockFetchingChallenge(challengeId, challenge);
    mockParticipant(user, challenge, false);
    mockConverter(ActionButtonStatus.WAITLIST);

    // When
    ChallengeResponseDto.HeaderInfoDto result = challengeService.getChallengeHeaderInfo(challengeId, user);

    // Then
    assertThat(result.getActionButtonStatus()).isEqualTo(ActionButtonStatus.WAITLIST);
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b696cda and f3401cf.

📒 Files selected for processing (2)
  • src/main/java/com/hrr/backend/domain/challenge/service/ChallengeServiceImpl.java
  • src/test/java/com/hrr/backend/domain/challenge/service/ChallengeServiceInfoTest.java
🔇 Additional comments (2)
src/main/java/com/hrr/backend/domain/challenge/service/ChallengeServiceImpl.java (2)

762-763: 버튼 로직 단순화 굿! 🎯

미참여자에게 상태별 제한 없이 자리가 있으면 무조건 JOIN을 반환하도록 개선되었습니다. 이는 Lines 642-643의 검증 로직 완화와 일관성을 유지하며, 코드의 복잡도를 낮춰 유지보수성을 높였습니다.

다만, UPCOMING 상태(챌린지 시작 전)에서도 JOIN 버튼이 노출되는데, 이것이 의도된 UX인지 확인이 필요합니다. 일부 서비스에서는 시작 전 챌린지에 "예약하기" 등 다른 문구를 사용하기도 합니다. 기획 의도와 일치하는지 체크해주세요.


642-645: 중도 참여 시 현재 라운드만 기록하는 것이 설계 의도인지 확인 필요

createRoundRecordOrFail (line 458)에서 challenge.getCurrentRound() 기준으로만 RoundRecord를 생성하고 있습니다. 진행 중인 챌린지에 참여하는 경우도 현재 라운드 기록만 생성되며, 지난 라운드에 대한 기록은 생성되지 않습니다.

이것이 의도된 설계라면 (중도 참여자는 현재 라운드부터만 추적), 그 의도를 명시하는 주석을 추가하면 향후 유지보수 시 혼동을 막을 수 있습니다. 예를 들어:

// 중도 참여자는 현재 라운드부터만 참여 기록을 시작합니다.
// 과거 라운드 이력은 API 응답의 remainDays 기반으로 사용자에게 표시됩니다.

지만 만약 중도 참여자도 지난 라운드를 추적해야 한다면, 모든 이전 라운드에 대해 RoundRecord를 생성하는 로직이 필요합니다.

@yangjiae12 yangjiae12 requested a review from yc3697 January 3, 2026 16:32
Copy link
Contributor

@yc3697 yc3697 left a comment

Choose a reason for hiding this comment

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

거 참 코드래빗 리뷰 안 남는 거 부럽네,,, 수고하였어요,,,

@yangjiae12
Copy link
Member Author

거 참 코드래빗 리뷰 안 남는 거 부럽네,,, 수고하였어요,,,

ㅎㅎ 감삼다

@yangjiae12 yangjiae12 merged commit c8987f9 into develop Jan 4, 2026
2 checks passed
@yangjiae12 yangjiae12 deleted the feat/174-challenge-api-update branch January 4, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐞 bug 버그 이슈 🌟 feat 새로운 기능 개발 ✔️ test 테스트 지애

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 챌린지 관련 API 수정

3 participants