Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DDING-66] ClubMember 목록 조회 API 응답값 변경 #201

Merged
merged 2 commits into from
Jan 8, 2025

Conversation

KoSeonJe
Copy link
Collaborator

@KoSeonJe KoSeonJe commented Jan 8, 2025

🚀 작업 내용

  • 기존 동아리원 정보만 응답하였는데, 클라이언트의 요청으로 동아리명까지 추가하였습니다.
  • List<>로 반환하던 응답 DTO를 동아리명까지 포함시키기 위해 래핑한 DTO를 생성하였습니다.
public record wrapping (
     String clubName,
     List<> list
)  {
}

💬 리뷰 중점사항

래핑한 클래스 이름이 적절한지 봐주세요!

Summary by CodeRabbit

  • 새로운 기능

    • 클럽 멤버 정보 응답 구조 변경
    • 클럽 멤버 정보를 더 포괄적이고 구조화된 방식으로 반환
  • 리팩토링

    • 클럽 멤버 정보 처리 로직 개선
    • 데이터 응답 모델 최적화
  • 문서화

    • Swagger 문서 메타데이터 업데이트
    • API 응답 구조에 대한 상세 정보 추가

Copy link

coderabbitai bot commented Jan 8, 2025

워크스루

이 풀 리퀘스트는 클럽 멤버 정보를 반환하는 방식을 변경하는 리팩토링 작업입니다. 기존의 CentralClubMemberListResponse 대신 AllClubMemberInfoResponse를 도입하여 클럽 멤버 정보를 더욱 구조화되고 포괄적인 방식으로 반환합니다. 이 변경은 컨트롤러, 서비스, DTO 레이어에 걸쳐 일관되게 적용되었습니다.

변경 사항

파일 경로 변경 요약
src/main/java/ddingdong/ddingdongBE/domain/club/api/CentralClubApi.java getMyClubMembers 메서드 반환 타입을 List<CentralClubMemberListResponse>에서 AllClubMemberInfoResponse로 변경
src/main/java/ddingdong/ddingdongBE/domain/club/controller/CentralClubController.java 메서드 시그니처 및 응답 타입 업데이트, 새로운 서비스 메서드 호출 로직 추가
src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/AllClubMemberInfoResponse.java 새로운 응답 DTO 클래스 추가, 클럽 멤버 정보를 캡슐화하는 구조 도입
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberService.java getAllMyClubMember 메서드 반환 타입을 List<CentralClubMemberListQuery>에서 AllClubMemberInfoQuery로 변경
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java 메서드 구현 로직 업데이트, 새로운 쿼리 타입으로 변경
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/AllClubMemberInfoQuery.java 새로운 쿼리 DTO 레코드 추가

가능한 관련 PR

제안된 레이블

✨기능, 🎯리팩토링, D-0

제안된 리뷰어

  • wonjunYou
  • 5uhwann

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

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

🧹 Nitpick comments (1)
src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/ClubMemberListResponse.java (1)

6-9: Schema 설명과 클래스 이름의 불일치 수정 필요

클래스 이름이 CentralClubMemberListResponse에서 ClubMemberListResponse로 변경되어 더 일반적인 의미를 가지게 되었습니다. 하지만 Schema 설명은 여전히 "중앙동아리"로 특정되어 있습니다. 일관성을 위해 Schema 설명도 수정이 필요합니다.

@Schema(
        name = "ClubMemberResponse",
-        description = "중앙동아리 - 동아리원 조회 응답"
+        description = "동아리원 조회 응답"
)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7deac54 and 15e395a.

📒 Files selected for processing (8)
  • src/main/java/ddingdong/ddingdongBE/domain/club/api/CentralClubApi.java (2 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/club/controller/CentralClubController.java (2 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/AllClubMemberInfoResponse.java (1 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/ClubMemberListResponse.java (2 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberService.java (1 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java (2 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/AllClubMemberInfoQuery.java (1 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/ClubMemberListQuery.java (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (10)
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/AllClubMemberInfoQuery.java (2)

5-8: 클래스 이름과 필드 명명이 명확합니다.

Record 클래스를 사용하여 불변성을 보장하고, 필드명이 의도를 잘 표현하고 있습니다.


10-12: 정적 팩토리 메서드가 잘 구현되어 있습니다.

of 메서드를 통해 객체 생성의 의도가 명확히 드러나며, 생성자 사용을 캡슐화하고 있습니다.

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberService.java (1)

11-11: 반환 타입 변경이 요구사항과 잘 부합합니다.

getAllMyClubMember 메서드의 반환 타입을 AllClubMemberInfoQuery로 변경한 것이 클라이언트의 요구사항(동아리명 포함)을 잘 반영하고 있습니다.

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/ClubMemberListQuery.java (2)

Line range hint 5-12: 클래스 이름 단순화가 적절합니다.

Central 접두어를 제거하여 더 간결하고 명확해졌습니다.

개인정보 처리에 대한 검토가 필요합니다.

전화번호와 같은 민감한 개인정보가 포함되어 있습니다. 보안을 위해 다음 사항들을 검토해주세요:

  1. 로그에 개인정보가 노출되지 않도록 주의
  2. 필요한 경우 전화번호 마스킹 처리 고려

Line range hint 14-22: 정적 팩토리 메서드가 잘 구현되어 있습니다.

엔티티에서 DTO로의 변환 로직이 깔끔하게 구현되어 있습니다.

src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/AllClubMemberInfoResponse.java (2)

8-13: API 문서화가 잘 되어있습니다.

Swagger 어노테이션을 통해 API 응답 구조가 명확하게 문서화되어 있습니다.

클래스 이름이 적절합니다.

PR 목표에서 언급된 'wrapping' 대신 AllClubMemberInfoResponse라는 명확한 이름을 사용한 것이 좋습니다.


15-20: 매핑 로직이 깔끔하게 구현되어 있습니다.

Stream API를 활용하여 Query에서 Response로의 변환이 간결하게 구현되어 있습니다.

src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java (1)

35-41: 구현이 PR 목적에 잘 부합합니다!

클럽 이름을 포함하도록 응답 구조를 변경한 것이 PR의 목적에 잘 부합합니다. 스트림 API를 사용하여 깔끔하게 구현되었습니다.

src/main/java/ddingdong/ddingdongBE/domain/club/controller/CentralClubController.java (1)

57-61: 컨트롤러 구현이 깔끔합니다!

다른 메서드들과 동일한 패턴을 따르며, 응답 구조 변경이 깔끔하게 구현되었습니다.

src/main/java/ddingdong/ddingdongBE/domain/club/api/CentralClubApi.java (1)

54-58: API 문서화가 잘 되어있습니다!

응답 타입 변경에 따른 Swagger 어노테이션 업데이트가 잘 되어있습니다.

@github-actions github-actions bot added the D-3 label Jan 8, 2025
Copy link
Collaborator

@5uhwann 5uhwann left a comment

Choose a reason for hiding this comment

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

코멘트 확인 부탁드립니다~

Comment on lines 8 to 21
public record AllClubMemberInfoResponse(
@Schema(name = "동아리명", example = "COW")
String clubName,
@ArraySchema(schema = @Schema(implementation = ClubMemberListResponse.class))
List<ClubMemberListResponse> clubMembers
) {

public static AllClubMemberInfoResponse from(AllClubMemberInfoQuery query) {
List<ClubMemberListResponse> responses = query.clubMemberListQueries().stream()
.map(ClubMemberListResponse::from)
.toList();
return new AllClubMemberInfoResponse(query.clubName(), responses);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

p3)
별도의 클래스로 분리하지 말고 하나의 이너 클래스로 두어 관리하는건 어떨까요?

Suggested change
public record AllClubMemberInfoResponse(
@Schema(name = "동아리명", example = "COW")
String clubName,
@ArraySchema(schema = @Schema(implementation = ClubMemberListResponse.class))
List<ClubMemberListResponse> clubMembers
) {
public static AllClubMemberInfoResponse from(AllClubMemberInfoQuery query) {
List<ClubMemberListResponse> responses = query.clubMemberListQueries().stream()
.map(ClubMemberListResponse::from)
.toList();
return new AllClubMemberInfoResponse(query.clubName(), responses);
}
}
public record ClubMemberListResponse(
@Schema(name = "동아리명", example = "COW")
String clubName,
@ArraySchema(schema = @Schema(implementation = ClubMemberListResponse.class))
List<ClubMemberResponse> clubMembers
) {
public static AllClubMemberInfoResponse from(AllClubMemberInfoQuery query) {
List<ClubMemberListResponse> responses = query.clubMemberListQueries().stream()
.map(ClubMemberResponse::from)
.toList();
return new ClubMemberListResponse(query.clubName(), responses);
}
@Schema(
name = "ClubMemberResponse",
description = "중앙동아리 - 동아리원 정보 조회 응답"
)
public record ClubMemberListResponse(
@Schema(description = "식별자", example = "1")
Long id,
@Schema(description = "이름", example = "홍길동")
String name,
@Schema(description = "학번", example = "60001111")
String studentNumber,
@Schema(description = "전화번호", example = "010-1234-5678")
String phoneNumber,
@Schema(description = "동아리원 역할",
example = "LEADER",
allowableValues = {"LEADER", "EXECUTION", "MEMBER"}
)
String position,
@Schema(description = "학과", example = "학과")
String department
) {
public static ClubMemberResponse from(ClubMemberListQuery query) {
return new ClubMemberListResponse(
query.id(),
query.name(),
query.studentNumber(),
query.phoneNumber(),
query.position(),
query.department()
);
}
}
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

수정 완료하였습니다!
56d8d84

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

🧹 Nitpick comments (2)
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/AllClubMemberInfoQuery.java (2)

6-9: 클래스 이름을 더 명확하게 변경하는 것을 고려해 보세요.

AllClubMemberInfoQuery라는 이름보다 ClubMemberListWithNameQuery와 같이 클래스의 목적을 더 명확하게 표현하는 이름이 좋을 것 같습니다.


11-13: null 체크 로직 추가를 고려해 보세요.

팩토리 메서드에서 clubNameclubMembers에 대한 null 체크가 없습니다. 유효성 검사를 추가하는 것이 안전할 것 같습니다.

 public static AllClubMemberInfoQuery of(String clubName, List<ClubMember> clubMembers) {
+    Objects.requireNonNull(clubName, "클럽 이름은 null일 수 없습니다");
+    Objects.requireNonNull(clubMembers, "클럽 멤버 목록은 null일 수 없습니다");
     return new AllClubMemberInfoQuery(clubName, clubMembers);
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15e395a and 56d8d84.

📒 Files selected for processing (3)
  • src/main/java/ddingdong/ddingdongBE/domain/club/controller/dto/response/AllClubMemberInfoResponse.java (1 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java (2 hunks)
  • src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/dto/query/AllClubMemberInfoQuery.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (1)
src/main/java/ddingdong/ddingdongBE/domain/clubmember/service/FacadeCentralClubMemberServiceImpl.java (1)

34-37: 예외 처리 로직 추가가 필요합니다.

clubService.getByUserId()에서 클럽을 찾지 못했을 경우의 예외 처리가 명시적으로 보이지 않습니다. 적절한 예외 처리를 추가하는 것이 좋겠습니다.

다음 스크립트로 예외 처리 여부를 확인해보세요:

Comment on lines +36 to +40
@Schema(description = "동아리원 역할",
example = "LEADER",
allowableValues = {"LEADER", "EXECUTION", "MEMBER"}
)
String position,
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Position 필드를 enum으로 변경하는 것이 좋겠습니다.

현재 position 필드가 String으로 되어있는데, 허용 가능한 값이 제한적이므로 enum을 사용하는 것이 타입 안전성을 보장할 수 있습니다.

public enum ClubMemberPosition {
    LEADER, EXECUTION, MEMBER
}

그리고 다음과 같이 변경하세요:

-    String position,
+    ClubMemberPosition position,

Comment on lines +45 to +54
public static ClubMemberListResponse from(ClubMember clubMember) {
return new ClubMemberListResponse(
clubMember.getId(),
clubMember.getName(),
clubMember.getStudentNumber(),
clubMember.getPhoneNumber(),
clubMember.getPosition().getName(),
clubMember.getDepartment()
);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

from 메서드에서 position 매핑 로직 개선이 필요합니다.

position 값을 가져올 때 getName()을 호출하고 있는데, enum으로 변경 후에는 직접 enum 값으로 매핑하는 것이 좋겠습니다.

-    clubMember.getPosition().getName(),
+    clubMember.getPosition(),

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

Copy link

sonarqubecloud bot commented Jan 8, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Copy link
Collaborator

@5uhwann 5uhwann left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

@KoSeonJe KoSeonJe merged commit 0704a01 into develop Jan 8, 2025
3 of 4 checks passed
@KoSeonJe KoSeonJe deleted the feature/DDING-66 branch January 8, 2025 15:50
@KoSeonJe KoSeonJe self-assigned this Jan 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants