8000 [Feature] 유저 연속 참여 및 주간 활동 조회 기능 구현 by wngktjd13 · Pull Request #47 · If-u-Lab/If-u-server · GitHub
[go: up one dir, main page]

Skip to content

[Feature] 유저 연속 참여 및 주간 활동 조회 기능 구현 - #47

Merged
wngktjd13 merged 9 commits into
devfrom
feature/my-page
Dec 26, 2025
Merged

wngktjd13 merged 9 commits into
devfrom
feature/my-page

Conversation

@wngktjd13
Copy link
Copy Markdown
Member

🔗 Issue Link

🎯 What I Did

  • 연속 참여(Streak) 로직 구현: 매일 투표/댓글 시 연속 일수 증가, 하루 빠지면 초기화
  • 최근 7일간 활동 여부 조회 기능 추가
  • 유저 정보 API 응답에 streak, weeklyActivity 필드 추가

🔍 Review Points

  • UserService.updateUserStreak(): streak 계산 로직 (첫 활동/연속/초기화 분기)
  • getWeeklyActivity(): 투표+댓글 활동 날짜를 합쳐서 7일간 활동 여부 계산
  • CommentService에서 userRepository.findById() → userService.findValidUser()로 변경 (삭제된 유저 체크)

🧪 API Test Scenarios

테스트한 엔드포인트

  • GET /api/v1/users/me

테스트 시나리오

  1. 정상 플로우
    • 첫 투표 시 streak = 1 확인
    • 같은 날 추가 활동 시 streak 유지 확인
    • 다음 날 활동 시 streak + 1 확인
    • weeklyActivity 배열에 활동한 날짜 true 반영 확인
  2. 에러 케이스
    - 삭제된 유저로 댓글 작성 시 USER_NOT_FOUND 에러 확인

✅ Checklist

  • Swagger 문서화 완료 (@Operation, @ApiResponse, @ApiErrorExample(s) 등)
  • 필요시 Notion 문서화 완료

@wngktjd13 wngktjd13 self-assigned this Dec 26, 2025
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @wngktjd13, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 사용자 참여도와 활동성을 추적하고 시각화하는 기능을 도입합니다. 사용자의 연속 활동 일수(streak)를 계산하고, 최근 7일간의 활동 여부를 제공함으로써 사용자 참여를 독려하고 서비스 내 활동 패턴을 파악하는 데 기여합니다. 또한, 사용자 정보 API를 확장하여 이러한 새로운 지표들을 응답에 포함시킵니다.

Highlights

  • 사용자 연속 활동(Streak) 로직 구현: 매일 투표 또는 댓글 작성 시 연속 일수가 증가하며, 하루라도 활동이 없으면 초기화됩니다.
  • 최근 7일간 활동 여부 조회 기능 추가: 사용자의 최근 7일간 활동 여부를 실시간으로 계산하여 제공하는 기능이 추가되었습니다.
  • 유저 정보 API 응답 확장: 사용자 정보 조회 API 응답에 streak (연속 활동 일수) 및 weeklyActivity (주간 활동 여부) 필드가 추가되었습니다.
  • 댓글 서비스 사용자 조회 로직 개선: 댓글 서비스(CommentService)에서 사용자 조회 로직이 userRepository.findById()에서 userService.findValidUser()로 변경되어 삭제된 사용자 체크를 강화했습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@claude
claude Bot commented Dec 26, 2025
Copy link
Copy Markdown

PR 리뷰

전반적으로 streak과 주간 활동 로직이 잘 구현되었습니다. 코드 구조가 명확하고 주석도 잘 작성되었네요.

P1 (꼭 반영해주세요)

  • VoteRepository.java:49, CommentRepository.java:32 - JPQL에서 CAST(createdAt AS LocalDate)는 데이터베이스 방언에 따라 동작하지 않을 수 있습니다. MySQL에서는 DATE(c.createdAt) 또는 FUNCTION('DATE', c.createdAt)를 사용하는 것이 안전합니다.

P2 (적극적으로 고려해주세요)

  • UserService.java:133-134 - 매번 2개의 쿼리를 실행하여 활동 날짜를 조회하는데, 사용자가 많아지면 성능 문제가 발생할 수 있습니다. 단일 쿼리로 합치거나 캐싱을 고려해보세요.
  • UserService.java:101-120 - updateUserStreak() 메서드가 public으로 선언되었으나 외부에서 직접 호출되면 안 되는 메서드로 보입니다. package-private 또는 private으로 변경하고 필요 시 User 엔티티를 파라미터로 받는 대신 userId를 받아 내부에서 조회하는 방식을 고려하세요.
  • VoteService.java:84-86 - 새 투표일 때만 streak를 업데이트하는데, 투표를 변경할 때도 활동으로 인정할지 고려가 필요합니다. (현재 로직상 투표 변경은 streak에 영향 없음)

P3 (웬만하면 반영해주세요)

  • UserService.java:128-145 - getWeeklyActivity() 메서드의 JavaDoc에 반환 리스트의 순서가 명시되어 있으나, 실제 구현을 보면 index 0: 오늘이 맞는지 확인 필요합니다. (오늘부터 역순으로 추가하므로 맞음)
  • User.java:87-90 - updateStreak() 메서드에서 streak 값의 유효성 검증(음수 체크)이 없습니다. 방어적 코딩을 위해 추가하는 것을 권장합니다.
  • CommentService.java:77 - streak 업데이트를 댓글 저장 후에 수행하는데, 저장 전에 수행하는 것이 더 논리적일 수 있습니다. (댓글이 저장되지 않으면 streak도 업데이트되지 않아야 함)

P4 (반영해도 좋고 넘어가도 좋습니다)

  • CommentRepository.java:5-6, VoteRepository.java:6-8 - import 순서가 일관되지 않습니다. java.time 관련 import를 함께 정렬하세요.
  • UserService.java:119 - 로그 메시지에 현재 날짜 정보도 추가하면 디버깅에 도움이 될 것 같습니다.

참고: 현재 ddl-auto: update로 설정되어 있어 DB 스키마는 자동으로 업데이트됩니다만, 프로덕션 배포 시에는 별도 마이그레이션 전략이 필요합니다.

@gemini-code-assist gemini-code-assist Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

이번 PR은 유저의 연속 참여(streak) 및 주간 활동 조회 기능을 성공적으로 구현했습니다. 전반적으로 로직이 잘 구성되어 있으며, 기능 요구사항을 잘 만족시킨 것으로 보입니다.

몇 가지 개선점을 제안합니다. 첫째, LocalDate.now()를 직접 사용하는 대신 java.time.Clock을 주입받아 사용하면 테스트 용이성과 시간대(timezone) 처리 안정성을 크게 높일 수 있습니다. 이는 서버 애플리케이션에서 중요한 부분입니다. 둘째, getWeeklyActivity 메서드의 로직을 조금 더 간결하고 효율적으로 개선할 수 있는 방안을 제안했습니다.

자세한 내용은 각 파일의 리뷰 코멘트를 참고해주세요. 좋은 코드 감사합니다!

8000
@claude
claude Bot commented Dec 26, 2025
Copy link
Copy Markdown

PR 리뷰

긍정적인 부분

  • Clock 주입을 통한 테스트 가능성 확보가 우수합니다 (ClockConfig.java)
  • Streak 로직이 명확하게 구현되어 있으며, 엔티티 메서드에 유효성 검증이 포함되어 있습니다

P1 (꼭 반영해주세요)

  • User.java:42-46 - DB에 current_streak, last_activity_date 컬럼이 추가되었으나 마이그레이션 스크립트가 없습니다. ddl-auto: update를 사용 중이지만 운영 환경에서는 명시적인 마이그레이션이 필요합니다. 기존 유저 데이터의 기본값 처리 방안도 필요합니다.

P2 (적극적으로 고려해주세요)

  • UserService.java:106-125 - updateUserStreak() 메서드의 핵심 로직에 대한 단위 테스트가 누락되었습니다. 특히 날짜 경계값(자정, 하루 전, 이틀 전) 케이스에 대한 검증이 필요합니다.
  • VoteService.java:86 - 투표 변경 시에는 streak를 업데이트하지 않는데, CommentService에서도 댓글 수정 시 동일한 처리가 필요한지 확인 필요합니다.
  • UserService.java:138-141 - 두 개의 repository 쿼리를 순차 실행 후 Set으로 합치는 방식은 N+1 문제는 없으나, 데이터가 많을 경우 성능 이슈가 있을 수 있습니다. 단일 쿼리로 통합하거나 성능 테스트가 권장됩니다.

P3 (웬만하면 반영해주세요)

  • UserService.java:133-148 - getWeeklyActivity() 메서드가 매 API 호출마다 실행되므로 캐싱 고려를 권장합니다 (예: @Cacheable 또는 Redis)
  • User.java:87-93 - updateStreak() 메서드의 유효성 검증이 음수만 체크하는데, date가 null인 경우도 검증이 필요할 수 있습니다.
  • CommentRepository.java:33 / VoteRepository.java:50 - JPQL의 FUNCTION('DATE', ...) 구문은 MySQL 방언 의존적입니다. 주석으로 DB 의존성 명시를 권장합니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • CommentRepository.java:4-5, 12 - import 순서가 불일치합니다 (java.time 관련 import가 분리됨)
  • UserService.java:131 - 주석에 "실시간 계산"이라고 명시되어 있는데, 향후 캐싱 도입 시 주석 업데이트 필요합니다

@claude
claude Bot commented Dec 26, 2025
Copy link
Copy Markdown

PR 리뷰

연속 참여(Streak) 기능이 깔끔하게 구현되었습니다. Clock을 빈으로 주입받아 테스트 가능하게 설계한 점이 좋습니다.

P1 (꼭 반영해주세요)

  • User.java:42-46 - current_streak, last_activity_date 컬럼 추가에 대한 DB 마이그레이션 스크립트가 누락되었습니다. JPA ddl-auto에 의존하면 운영 환경에서 문제가 발생할 수 있습니다. Flyway나 Liquibase 같은 마이그레이션 도구 사용을 권장합니다.

P2 (적극적으로 고려해주세요)

  • UserService.java:106-125 - updateUserStreak() 메서드가 항상 로그를 출력하는데, 같은 날 중복 활동 시(115줄 early return)에는 로그가 출력되지 않습니다. 일관성을 위해 모든 케이스에서 로그를 남기거나, 변경이 있을 때만 남기도록 통일하는 것이 좋습니다.
  • UserService.java:133-155 - getWeeklyActivity() 메서드에서 투표와 댓글 활동을 각각 조회한 후 Set에 합치고 있습니다. DB 쿼리를 2번 실행하는데, 사용자별 활동이 많으면 성능 이슈가 있을 수 있습니다. UNION을 사용한 단일 쿼리로 최적화를 고려해보세요.
  • VoteService.java:86 / CommentService.java:78 - streak 업데이트가 투표/댓글 생성 트랜잭션 내부에서 동기적으로 실행됩니다. 동시성 상황(같은 시각에 투표+댓글)에서 마지막 호출의 결과만 반영될 수 있습니다. 비동기 처리나 별도 트랜잭션 분리를 고려해보세요.

P3 (웬만하면 반영해주세요)

  • UserService.java:96-125 - updateUserStreak() 메서드에 대한 단위 테스트 추가를 권장합니다. 특히 날짜 경계 케이스(첫 활동, 연속, 초기화)에 대한 테스트가 중요합니다.
  • UserService.java:133-155 - getWeeklyActivity() 메서드에 대한 테스트도 추가하면 좋습니다.
  • User.java:87-93 - updateStreak() 메서드에서 음수 검증만 하고 있는데, 날짜가 null인 경우나 미래 날짜인 경우에 대한 검증도 추가하는 것이 안전합니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • UserService.java:24 - 사용하지 않는 import HashSet 제거 필요
  • CommentRepository.java:5-6 - 사용하지 않는 import LocalDate, Set 제거 필요
  • VoteRepository.java:6 - 사용하지 않는 import LocalDate, Set 제거 필요

@claude
claude Bot commented Dec 26, 2025
Copy link
Copy Markdown

PR 리뷰

연속 참여(Streak) 기능 구현이 전반적으로 잘 되어 있습니다. Clock 빈을 통한 테스트 가능성 고려도 좋습니다.

P1 (꼭 반영해주세요)

  • User.java:42-46 - current_streak, last_activity_date 컬럼 추가 시 기존 사용자 데이터에 대한 default 값 설정이 필요합니다. ddl-auto: update 사용 시 nullable=false 컬럼 추가는 기존 레코드에 0/NULL을 넣게 되는데, MySQL에서 NOT NULL 컬럼 추가 시 에러가 발생할 수 있습니다.

P2 (적극적으로 고려해주세요)

  • UserService.java:105-124 - updateUserStreak() 메서드가 @transactional이지만, 투표 변경 시에는 streak를 업데이트하지 않는 로직이 누락되었습니다. VoteService.java:86에서는 새 투표만 처리하는데, 사용자가 다른 선택지로 변경하는 것도 "활동"으로 봐야 하지 않을까요? 기획 ì� AB6E ˜도 확인이 필요합니다.

  • UserService.java:132-154 - getWeeklyActivity() 메서드에서 2번의 repository 호출과 stream 연산이 발생합니다. 투표/댓글 테이블에 복합 인덱스 (user_id, created_at) 추가를 권장합니다. 또한 두 쿼리를 UNION으로 합치는 것도 고려해볼 만합니다.

  • CommentService.java:46-48 - 삭제된 유저 체크를 위해 findValidUser()로 변경한 것은 좋으나, VoteService에서도 동일하게 findValidUser()를 사용하므로 일관성은 있습니다만, 기존 코드의 userRepository.findById()를 사용하던 다른 서비스들도 검토가 필요합니다.

P3 (웬만하면 반영해주세요)

  • UserService.java:105-124 - streak 업데이트 로직에 대한 단위 테스트 추가를 권장합니다. 특히 경계 케이스(자정 넘어가는 시점, 연속/초기화 분기)는 Clock을 mocking하여 테스트하기 좋은 구조입니다.

  • User.java:87-93 - updateStreak() 메서드에서 음수 검증만 있는데, date가 null인 경우도 검증하는 것이 좋겠습니다.

  • VoteService.java:86 / CommentService.java:77 - streak 업데이트 호출이 각각 다른 위치에 있습니다. VoteService는 새 투표 생성 후, CommentService는 댓글 저장 후인데, 통일성을 위해 둘 다 저장 후로 맞추는 것을 권장합니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • CommentRepository.java:7-9 - import 순서가 java.time.LocalDateTime → org.springframework 순으로 되어 있는데, 일반적으로 java → jakarta → org 순서가 권장됩니다.

  • UserService.java:123 - 로그 메시지에 날짜 정보도 함께 출력하면 디버깅에 도움이 됩니다: "Streak updated: userId={}, streak={}, date={}"

@wngktjd13
wngktjd13 merged commit 7148547 into dev Dec 26, 2025
1 check passed
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

0