Skip to content

Conversation

@pokerbearkr
Copy link
Contributor

@pokerbearkr pokerbearkr commented Jun 22, 2025


변경 사항

  • 내 프로필용 점수 조회 개발

image

  • 타인 프로필용 점수 조회 개발

image


트러블 슈팅


해결해야 할 문제

  • 티어같은 경우는 프론트에서 처리해야 겠죠..?

참고 사항


코드 리뷰 전 확인 체크리스트

  • 불필요한 콘솔 로그, 주석 제거
  • 커밋 메시지 컨벤션 준수 (type : )
  • 기능 정상 동작 확인

Summary by CodeRabbit

  • New Features
    • 내 점수와 다른 사용자의 총 점수를 조회할 수 있는 새로운 API가 추가되었습니다. (GET /api/points/me, GET /api/points/{userId})
  • 버그 수정
    • 해당 없음
  • 기타
    • 코드 스타일 및 import 정리가 일부 파일에 반영되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Jun 22, 2025

Walkthrough

사용자의 총 점수를 조회하는 새로운 포인트 시스템이 도입되었습니다. 이를 위해 PointService, PointController, PointResponse가 추가되었고, 관련 Repository 및 JPA 쿼리가 확장되었습니다. RankingController에는 관련 DTO와 ResponseEntity import가 추가되었습니다.

Changes

파일/경로 요약 변경 내용 요약
.../application/ranking/dto/PointResponse.java PointResponse 레코드 신설, int points 필드 포함
.../application/ranking/dto/RankingResponse.java record 선언부의 공백만 추가, 기능 변화 없음
.../application/ranking/service/PointService.java PointService 서비스 클래스 신설, getTotalPoints(Long userId) 메서드 추가
.../domain/submission/repository/UserProblemResultRepository.java sumPointByUserId(Long userId) 메서드 선언 추가
.../infrastructure/persistence/repository/submission/impl/UserProblemResultRepositoryImpl.java sumPointByUserId(Long userId) 구현 메서드 추가
.../infrastructure/persistence/repository/submission/jpa/UserProblemResultJpaRepository.java sumScoreByUserId(Long userId) JPQL 쿼리 및 메서드 추가
.../presentation/ranking/PointController.java PointController REST 컨트롤러 신설, /me, /{userId} GET 엔드포인트 추가
.../presentation/ranking/RankingController.java PointResponse, ResponseEntity import 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant PointController
    participant PointService
    participant UserProblemResultRepository
    participant UserProblemResultJpaRepository

    Client->>PointController: GET /api/points/me 또는 /api/points/{userId}
    PointController->>PointService: getTotalPoints(userId)
    PointService->>UserProblemResultRepository: sumPointByUserId(userId)
    UserProblemResultRepository->>UserProblemResultJpaRepository: sumScoreByUserId(userId)
    UserProblemResultJpaRepository-->>UserProblemResultRepository: Optional<Integer> points
    UserProblemResultRepository-->>PointService: Optional<Integer> points
    PointService-->>PointController: int points
    PointController-->>Client: ResponseEntity<PointResponse>
Loading

Suggested labels

enhancement

Suggested reviewers

  • Kimminu7
  • minjee2758

Poem

🥕
점수의 길을 따라 토끼가 뛰어요,
새로운 컨트롤러에 귀를 쫑긋 세워요.
서비스와 레포지토리, 함께 손잡고
유저의 점수를 찾아서 hop hop hop!
코드의 들판에 변화가 피었네,
오늘도 개발자와 토끼는 기분이 좋네.
🐇

✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

♻️ Duplicate comments (1)
src/main/java/org/ezcode/codetest/domain/submission/repository/UserProblemResultRepository.java (1)

30-30: 메서드 선언은 올바르지만 명명 일관성 검토 필요

도메인 레포지토리 인터페이스의 메서드 선언이 올바르게 작성되었습니다. 하지만 구현체에서 "point"와 "score"가 혼용되고 있는 점을 확인해주세요.

이전에 UserProblemResultRepositoryImpl.java에서 언급한 명명 일관성 문제와 동일한 이슈입니다.

🧹 Nitpick comments (5)
src/main/java/org/ezcode/codetest/application/ranking/dto/RankingResponse.java (1)

6-6: 불필요한 공백 제거 필요

record 키워드와 RankingResponse 사이의 추가 공백이 코드 포매팅을 일관성 있게 유지하는 데 방해가 됩니다.

-public record   RankingResponse(
+public record RankingResponse(
src/main/java/org/ezcode/codetest/application/ranking/dto/PointResponse.java (1)

3-5: LGTM! 간단하고 명확한 구현입니다.

포인트 값을 담는 간단한 레코드로 잘 구현되었습니다.

향후 확장성을 고려한다면 다음과 같은 개선을 고려해볼 수 있습니다:

+import javax.validation.constraints.Min;
+
+/**
+ * 사용자 포인트 정보를 담는 응답 DTO
+ */
 public record PointResponse (
+    @Min(0)
     int points
 ){}
src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java (2)

22-24: 변수명 일관성을 유지하세요.

다른 메서드와의 일관성을 위해 변수명을 통일해주세요.

-        int totalPoints = pointService.getTotalPoints(userId);
-        return ResponseEntity.ok(new PointResponse(totalPoints));
+        int totalPoint = pointService.getTotalPoints(userId);
+        return ResponseEntity.ok(new PointResponse(totalPoint));

23-24: 변수명 일관성 개선 필요

같은 의미의 변수에 대해 totalPointstotalPoint로 서로 다른 명명을 사용하고 있습니다. 일관성을 위해 통일해주세요.

다음과 같이 통일하는 것을 권장합니다:

 @GetMapping("/{userId}")
 public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
-    int totalPoint = pointService.getTotalPoints(userId);
-    return ResponseEntity.ok(new PointResponse(totalPoint));
+    int totalPoints = pointService.getTotalPoints(userId);
+    return ResponseEntity.ok(new PointResponse(totalPoints));
 }

Also applies to: 29-29

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/jpa/UserProblemResultJpaRepository.java (1)

26-33: 쿼리 성능 최적화 고려사항

대용량 데이터에서 성능을 위해 인덱스 사용을 검토해보세요. user.idisCorrect 컬럼에 복합 인덱스가 있는지 확인하는 것을 권장합니다.

다음과 같은 인덱스 추가를 고려해보세요:

CREATE INDEX idx_user_problem_result_user_correct 
ON user_problem_result(user_id, is_correct);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9601ac and 2b56a9e.

📒 Files selected for processing (8)
  • src/main/java/org/ezcode/codetest/application/ranking/dto/PointResponse.java (1 hunks)
  • src/main/java/org/ezcode/codetest/application/ranking/dto/RankingResponse.java (1 hunks)
  • src/main/java/org/ezcode/codetest/application/ranking/service/PointService.java (1 hunks)
  • src/main/java/org/ezcode/codetest/domain/submission/repository/UserProblemResultRepository.java (2 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/impl/UserProblemResultRepositoryImpl.java (1 hunks)
  • src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/jpa/UserProblemResultJpaRepository.java (2 hunks)
  • src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java (1 hunks)
  • src/main/java/org/ezcode/codetest/presentation/ranking/RankingController.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (8)
src/main/java/org/ezcode/codetest/presentation/ranking/RankingController.java (1)

4-4: 사용되지 않는 import 제거 또는 활용 확인 필요

PointResponseResponseEntity import가 추가되었지만 현재 컨트롤러에서 사용되지 않고 있습니다. 향후 사용 예정이 아니라면 제거하는 것이 좋겠습니다.

다음 스크립트로 해당 클래스들이 실제로 사용되는지 확인해보겠습니다:

#!/bin/bash
# Description: Check if PointResponse and ResponseEntity are actually used in RankingController

# Search for usage of PointResponse in the controller
rg -A 3 -B 3 "PointResponse" src/main/java/org/ezcode/codetest/presentation/ranking/RankingController.java

# Search for usage of ResponseEntity in the controller  
rg -A 3 -B 3 "ResponseEntity" src/main/java/org/ezcode/codetest/presentation/ranking/RankingController.java

Also applies to: 8-8

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/impl/UserProblemResultRepositoryImpl.java (1)

40-43: 메서드명 일관성 문제 확인 필요

메서드명이 sumPointByUserId인데 내부에서 sumScoreByUserId를 호출하고 있습니다. "point"와 "score"가 같은 의미로 사용되는지 확인이 필요합니다.

명명 일관성을 확인하기 위해 다음 스크립트를 실행하겠습니다:

#!/bin/bash
# Description: Check naming consistency between point and score across the codebase

# Search for methods containing "point" and "score" to understand the naming convention
echo "=== Searching for 'point' related methods ==="
rg -n "point|Point" --type java

echo "=== Searching for 'score' related methods ==="
rg -n "score|Score" --type java

echo "=== Searching for sumScoreByUserId method definition ==="
rg -A 5 -B 2 "sumScoreByUserId" --type java
src/main/java/org/ezcode/codetest/domain/submission/repository/UserProblemResultRepository.java (1)

9-9: LGTM! @param import 추가가 적절합니다.

새로운 메서드의 파라미터 어노테이션을 위한 import가 올바르게 추가되었습니다.

src/main/java/org/ezcode/codetest/application/ranking/service/PointService.java (1)

7-17: 서비스 구현이 올바르게 되어 있습니다.

Spring의 표준 패턴을 잘 따르고 있으며, Optional.orElse(0)를 사용하여 null 안전성을 보장하고 있습니다.

src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/jpa/UserProblemResultJpaRepository.java (2)

26-33: JPQL 쿼리 구현이 정확합니다.

사용자가 정답을 맞춘 문제들의 점수를 정확히 합산하는 로직이며, JOIN과 필터링 조건이 올바르게 작성되어 있습니다.


26-33: JPQL 쿼리 구현이 올바릅니다

정답으로 처리된 문제의 점수만 합산하는 로직이 정확하게 구현되었습니다. Optional 반환 타입도 적절합니다.

src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java (2)

27-31: 사용자 점수 조회에 대한 보안 정책을 확인하세요.

현재 구현은 인증된 모든 사용자가 다른 사용자의 점수를 조회할 수 있습니다. 이것이 의도된 동작인지 확인이 필요하며, userId 파라미터에 대한 입력 검증도 추가하는 것을 고려해보세요.

만약 사용자 프라이버시 보호가 필요하다면, 다음과 같은 제한을 고려해보세요:

  • 관리자 권한 체크
  • 사용자 자신의 정보만 조회 허용
  • 공개 프로필 설정에 따른 조회 제한

20-25: 현재 사용자 점수 조회 로직이 올바릅니다

@AuthenticationPrincipal을 사용한 현재 사용자 식별과 점수 조회 로직이 적절하게 구현되었습니다.

Comment on lines +13 to +15
public int getTotalPoints(Long userId) {
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

입력 검증 및 예외 처리 개선 필요

userId가 null일 경우에 대한 검증이 없습니다. 또한 데이터베이스 호출 시 발생할 수 있는 예외에 대한 명시적인 처리를 고려해보세요.

다음과 같이 입력 검증을 추가하는 것을 권장합니다:

 public int getTotalPoints(Long userId) {
+    if (userId == null) {
+        throw new IllegalArgumentException("사용자 ID는 null일 수 없습니다");
+    }
     return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public int getTotalPoints(Long userId) {
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
public int getTotalPoints(Long userId) {
if (userId == null) {
throw new IllegalArgumentException("사용자 ID는 null일 수 없습니다");
}
return userProblemResultRepository.sumPointByUserId(userId).orElse(0);
}
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/ranking/service/PointService.java
around lines 13 to 15, add a null check for the userId parameter at the start of
the getTotalPoints method to validate input. If userId is null, throw an
IllegalArgumentException with a clear message. Additionally, wrap the repository
call in a try-catch block to handle potential database exceptions, and handle or
rethrow them appropriately to ensure robust error handling.

Comment on lines +27 to +31
@GetMapping("/{userId}")
public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
int totalPoint = pointService.getTotalPoints(userId);
return ResponseEntity.ok(new PointResponse(totalPoint));
}
Copy link

@coderabbitai coderabbitai bot Jun 22, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

보안 및 입력 검증 개선 필요

다른 사용자의 점수 조회에 대한 권한 검사가 없고, userId 입력 검증이 부족합니다.

다음과 같은 개선사항을 고려해주세요:

  1. 입력 검증 추가:
 @GetMapping("/{userId}")
 public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
+    if (userId == null || userId <= 0) {
+        return ResponseEntity.badRequest().build();
+    }
     int totalPoints = pointService.getTotalPoints(userId);
     return ResponseEntity.ok(new PointResponse(totalPoints));
 }
  1. 권한 검사 추가 (필요시):
    • 모든 사용자의 점수를 공개할 것인지, 아니면 특정 권한이 필요한지 정책을 명확히 하고 적절한 보안 검사를 추가해주세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java
around lines 27 to 31, the getUserPoint method lacks input validation for userId
and does not perform any authorization checks. Add validation to ensure userId
is a valid positive number before processing. Implement authorization logic to
verify if the requesting user has permission to access the requested user's
points, based on your security policy, and restrict access accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

다른 사람 프로필 들어갔을때 티어 보이게 하려는거라 아무나 조회 가능해

Copy link

Choose a reason for hiding this comment

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

@pokerbearkr 아, 프로필 페이지에서 티어 표시용이군요! 그럼 공개 API로 설계된 것이 맞네요.

권한 검사는 필요 없다는 점 이해했습니다. 다만 기본적인 입력 검증은 여전히 권장합니다:

@GetMapping("/{userId}")
public ResponseEntity<PointResponse> getUserPoint(@PathVariable Long userId) {
    if (userId == null || userId <= 0) {
        return ResponseEntity.badRequest().build();
    }
    int totalPoint = pointService.getTotalPoints(userId);
    return ResponseEntity.ok(new PointResponse(totalPoint));
}

이렇게 하면 잘못된 userId가 들어왔을 때 더 명확한 에러 응답을 줄 수 있어요.

  (\   /)
 ( ._.)
o_(")(")  *understanding hop*

✏️ Learnings added
Learnt from: pokerbearkr
PR: ezcode-my/backend#89
File: src/main/java/org/ezcode/codetest/presentation/ranking/PointController.java:27-31
Timestamp: 2025-06-22T06:01:45.521Z
Learning: PointController의 getUserPoint 엔드포인트는 다른 사용자의 프로필에서 티어 정보를 표시하기 위한 공개 API로, 모든 사용자가 다른 사용자의 점수를 조회할 수 있도록 설계되었다.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@thezz9 thezz9 merged commit e29aa84 into dev Jun 22, 2025
2 checks passed
@thezz9 thezz9 deleted the feat/rank branch June 22, 2025 20:44
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.

4 participants