Skip to content

[FEAT] 내 모임 V2 목록 조회 기능 구현#141

Merged
LimdaeIl merged 2 commits intomainfrom
feat/my-group
Dec 19, 2025
Merged

[FEAT] 내 모임 V2 목록 조회 기능 구현#141
LimdaeIl merged 2 commits intomainfrom
feat/my-group

Conversation

@LimdaeIl
Copy link
Collaborator

@LimdaeIl LimdaeIl commented Dec 19, 2025

📝 Pull Request

📌 PR 종류

해당하는 항목에 체크해주세요.

  • 기능 추가 (Feature)
  • 버그 수정 (Fix)
  • 문서 수정 (Docs)
  • 코드 리팩터링 (Refactor)
  • 테스트 추가 (Test)
  • 기타 변경 (Chore)

✨ 변경 내용

내 모임 V2 목록 조회 기능 구현합니다.

🔍 관련 이슈

🧪 테스트

변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.

  • 유닛 테스트 추가 / 수정
  • 통합 테스트 검증
  • 수동 테스트 완료

🚨 확인해야 할 사항 (Checklist)

PR을 제출하기 전에 아래 항목들을 확인해주세요.

  • 코드 포매팅 완료
  • 불필요한 파일/코드 제거
  • 로직 검증 완료
  • 프로젝트 빌드 성공
  • 린트/정적 분석 통과 (해당 시)

🙋 기타 참고 사항

리뷰어가 참고하면 좋을 만한 추가 설명이 있다면 적어주세요.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 개인 그룹 목록 조회 기능 추가 (현재, 내 게시물, 지난 그룹별 분류)
    • 커서 기반 페이지네이션 지원
    • 그룹 상태 및 사용자 멤버십 상태별 필터링 기능 추가
    • 각 그룹 항목에 참여 가능 여부 표시
  • 개선

    • 그룹 생성 쿨다운 시간 단축 (30초 → 5초)

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

사용자와 연결된 그룹을 검색할 수 있는 기능을 도입하여,
그룹 유형(현재, 내 게시물, 이전) 및 상태별로 필터링할 수 있도록 합니다.
페이지네이션 기능을 포함하고 이미지, 태그, 멤버십 정보 등 관련 그룹 정보를 불러옵니다.

대기 시간을 30초에서 5초로 단축합니다
@LimdaeIl LimdaeIl self-assigned this Dec 19, 2025
Copilot AI review requested due to automatic review settings December 19, 2025 10:06
@LimdaeIl LimdaeIl added the ✨enhancement New feature or request label Dec 19, 2025
@LimdaeIl LimdaeIl moved this from Backlog to In progress in WeGo-Together Backend Dec 19, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 19, 2025

개요

"내 모임" V2 목록 조회 기능을 구현합니다. 새로운 DTO, 서비스 계층, 쿼리 메서드 및 컨트롤러 엔드포인트를 통해 사용자가 현재/과거/내가 작성한 모임을 필터링 및 페이지네이션하여 조회할 수 있도록 합니다.

변경 사항

코호트 / 파일(들) 변경 요약
DTO 확장
src/main/java/team/wego/wegobackend/group/v2/application/dto/common/CreatedBy.java
새로운 정적 팩토리 메서드 of(Long userId, String nickName, String profileImage, String profileMessage) 추가
새 유형 정의
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/MyGroupTypeV2.java
공개 열거형 MyGroupTypeV2 추가 (CURRENT, MY_POST, PAST) 및 문자열 검증 메서드 from(String) 포함
응답 DTO
src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetMyGroupListV2Response.java
새로운 레코드 GetMyGroupListV2Response 및 중첩 Item 레코드 추가, 남은 좌석/참여 가능 여부 계산 로직 포함
쿼리 저장소 인터페이스
src/main/java/team/wego/wegobackend/group/v2/domain/repository/GroupV2QueryRepository.java
두 가지 새로운 쿼리 메서드 추가: fetchMyGroupRows(...), fetchMyPostGroupRows(...)
쿼리 저장소 구현
src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/GroupV2QueryRepositoryImpl.java
Querydsl을 사용한 두 쿼리 메서드 구현, 상태 필터링 및 커서 기반 페이지네이션 로직 포함
투영 레코드
src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/MyGroupListRow.java
모임 목록 조회용 새로운 데이터 전송 객체 레코드 추가
서비스 계층
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupMyGetV2Service.java
새로운 공개 서비스 클래스, getMyGroups(...) 메서드로 필터링/페이지네이션/상태 해석 로직 구현
컨트롤러 엔드포인트
src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java
새 GET /api/v2/groups/me 엔드포인트 추가
상수 변경
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java
COOL_DOWN_SECONDS 상수 30에서 5로 감소
통합 테스트
src/test/http/group/v2/v2-group-get-me.http
신규 기능 전체 흐름 테스트 (사용자 로그인, 모임 생성, 조회, 페이지네이션)

시퀀스 다이어그램

sequenceDiagram
    participant Client
    participant Controller as GroupV2Controller
    participant Service as GroupMyGetV2Service
    participant Repository as GroupV2QueryRepository
    participant DB as Database

    Client->>Controller: GET /api/v2/groups/me<br/>(type, cursor, size, filters)
    Controller->>Service: getMyGroups(userId, cursor, size, type, filter, ...)
    Service->>Service: Validate userId & default type/filter
    Service->>Service: resolveStatuses(filter, includes, excludes)
    
    alt type == MY_POST
        Service->>Repository: fetchMyPostGroupRows(userId, cursor, limit, ...)
    else type == CURRENT or PAST
        Service->>Repository: fetchMyGroupRows(userId, cursor, limit, ...)
    end
    
    Repository->>DB: Query groups with status filters<br/>& cursor pagination
    DB-->>Repository: List<MyGroupListRow>
    Repository-->>Service: MyGroupListRow list
    
    Service->>Repository: fetchTagNamesByGroupIds(groupIds)
    Service->>Repository: fetchMainImageUrlsByGroupIds(groupIds)
    
    DB-->>Service: Tags & Images
    
    Service->>Service: Transform rows to Items<br/>(compute remainingSeats,<br/>joinable, MyMembership)
    Service-->>Controller: GetMyGroupListV2Response
    Controller-->>Client: ApiResponse<GetMyGroupListV2Response>
Loading

예상 코드 리뷰 노력

🎯 3 (중간 복잡도) | ⏱️ ~25분

검토 시 특별히 주의가 필요한 부분:

  • GroupV2QueryRepositoryImpl의 복잡한 Querydsl 쿼리 로직 (조인, 필터링, 그룹화, 정렬)
  • GroupMyGetV2Service.resolveStatuses(...) 메서드의 상태 필터링 규칙 및 기본값 설정 로직
  • remainingSeats 계산 및 joinable 플래그 결정 로직의 비즈니스 요구사항 적절성
  • 커서 기반 페이지네이션 구현의 경계 케이스 처리 (hasNext 판단, nextCursor 계산)

관련된 PR들

🐰 내 모임을 찾아주니 반갑네요,

커서를 타고 페이지를 넘으며,

현재와 과거를 가르는 필터 같아,

상태별 조회로 한눈에 쏙,

V2 기능 완성, 모임의 길잡이! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 '[FEAT] 내 모임 V2 목록 조회 기능 구현'으로 변경사항의 주요 내용인 'My Groups V2 list retrieval' 기능 구현을 명확하게 설명합니다.
Linked Issues check ✅ Passed 연결된 이슈 #140은 'My Groups V2 list retrieval' 기능 구현을 요청하며, PR의 모든 코드 변경사항이 이 목표를 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 My Groups V2 목록 조회 기능 구현과 관련되어 있으며, 범위를 벗어난 변경사항은 없습니다.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/my-group

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/main/java/team/wego/wegobackend/group/v2/application/dto/request/MyGroupTypeV2.java (1)

19-29: 대소문자 구분 매칭에 대해 고려해 보세요.

현재 from() 메서드는 대소문자를 구분하여 "Current"나 "CURRENT"는 실패합니다. API 사용성을 위해 대소문자를 무시하는 매칭을 고려할 수 있습니다.

🔎 대소문자 무시 옵션
 public static MyGroupTypeV2 from(String value) {
     if (value == null) {
         throw new GroupException(GroupErrorCode.MY_GROUP_TYPE_NOT_NULL);
     }
-    return switch (value) {
+    return switch (value.toLowerCase()) {
         case "current" -> CURRENT;
-        case "myPost" -> MY_POST;
+        case "mypost" -> MY_POST;
         case "past" -> PAST;
         default -> throw new GroupException(GroupErrorCode.INVALID_MY_GROUP_TYPE, value);
     };
 }
src/main/java/team/wego/wegobackend/group/v2/domain/repository/GroupV2QueryRepository.java (1)

37-38: 불필요한 빈 줄을 제거하세요.

두 개의 연속된 빈 줄은 일반적인 코딩 컨벤션에 맞지 않습니다.

🔎 제안하는 수정
     );
-

-

+
     Map<Long, List<String>> fetchTagNamesByGroupIds(List<Long> groupIds);
src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (1)

129-138: API 복잡도 고려사항

엔드포인트에 7개의 쿼리 파라미터가 있어 API 사용이 복잡할 수 있습니다. 대부분이 선택적 파라미터이고 적절한 기본값이 설정되어 있어 문제는 아니지만, API 문서화를 잘 해두시기 바랍니다.

📜 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 96fda52 and 60d4a7b.

📒 Files selected for processing (10)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/common/CreatedBy.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/request/MyGroupTypeV2.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetMyGroupListV2Response.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/service/GroupMyGetV2Service.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/repository/GroupV2QueryRepository.java (2 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/GroupV2QueryRepositoryImpl.java (2 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/MyGroupListRow.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (3 hunks)
  • src/test/http/group/v2/v2-group-get-me.http (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/MyGroupTypeV2.java (1)
src/main/java/team/wego/wegobackend/group/domain/exception/GroupException.java (1)
  • GroupException (6-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Agent
  • GitHub Check: CodeQL analysis (java)
🔇 Additional comments (17)
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java (1)

61-61: 쿨다운 시간이 30초에서 5초로 크게 감소했습니다.

그룹 생성 쿨다운이 6배 단축되었습니다. 이 변경이 의도적인지 확인해 주세요. 5초는 스팸성 그룹 생성을 방지하기에 충분하지 않을 수 있습니다.

src/main/java/team/wego/wegobackend/group/v2/application/dto/common/CreatedBy.java (1)

16-20: LGTM!

of() 팩토리 메서드가 projection 데이터에서 CreatedBy를 생성할 수 있도록 유연성을 제공합니다. 기존 from(User) 메서드와 잘 조화됩니다.

src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/MyGroupListRow.java (1)

8-33: LGTM!

QueryDSL projection을 위한 잘 구성된 record입니다. 필드 타입이 쿼리 결과와 적절히 매핑되어 있고, 그룹 정보, 호스트 정보, 참가자 수, 사용자 멤버십 정보를 명확하게 분리하고 있습니다.

src/test/http/group/v2/v2-group-get-me.http (2)

1-153: LGTM!

새로운 /api/v2/groups/me 엔드포인트에 대한 포괄적인 E2E 테스트 컬렉션입니다. 회원가입부터 페이지네이션, 타입별 필터링까지 전체 플로우를 잘 커버하고 있습니다.


34-44: 테스트 이미지 파일이 모두 존재합니다.

../../image/resources/img1.png../../image/resources/img2.jpg 파일이 src/test/http/image/resources/ 디렉토리에 정상적으로 존재하므로, 테스트 실행에 문제가 없습니다.

src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/GroupV2QueryRepositoryImpl.java (2)

186-285: LGTM!

fetchMyGroupRows 메서드가 잘 구현되어 있습니다. 사용자 멤버십에 대한 inner join과 ATTEND 카운트를 위한 left join 구조가 올바릅니다. groupBy에 모든 select 필드가 포함되어 SQL 의미론을 준수합니다.


287-356: fetchMyPostGroupRows에서 left join 사용이 적절합니다.

호스트가 group.host에는 있지만 group.users에는 명시적 레코드가 없을 수 있으므로 myGu에 대한 left join이 올바른 선택입니다. MyMembership 레코드는 groupUserId, role, status 등의 필드가 null일 수 있도록 설계되어 있으므로(참고: MyMembership.from() 메서드의 orElse 로직), 서비스 계층에서 추가적인 null 처리 없이도 안전하게 작동합니다.

src/main/java/team/wego/wegobackend/group/v2/domain/repository/GroupV2QueryRepository.java (1)

20-35: 메서드 시그니처가 잘 설계되었습니다.

두 메서드의 파라미터 차이가 논리적입니다:

  • fetchMyGroupRows: 사용자의 멤버십 상태(myStatuses)로 필터링
  • fetchMyPostGroupRows: 호스트 기준 필터링이므로 myStatuses 불필요
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupMyGetV2Service.java (6)

30-42: 입력 검증 및 기본값 처리가 적절합니다.

userId null 체크와 적절한 예외 처리가 구현되어 있습니다.


47-52: 타입별 기본 필터 로직이 명확합니다.

CURRENTMY_POSTACTIVE, PASTARCHIVED 필터를 기본값으로 사용하는 것이 직관적입니다.


58-80: 타입별 조건부 로직이 올바릅니다.

MY_POST는 호스트 기준 조회, 나머지는 멤버십 기준 조회로 분기하는 것이 적절하며, myStatuses 기본값을 ATTEND로 설정하는 것도 합리적입니다.


100-102: Null 안전성 처리가 우수합니다.

participantCountmaxParticipants의 null 체크와 기본값 처리가 잘 되어 있습니다.


142-181: 상태 필터 해석 로직이 견고합니다.

필터 기본값 처리, 충돌 제거, 그리고 빈 조건에 대한 기본 include 설정이 잘 구현되어 있습니다. 특히 lines 174-178의 충돌 제거 로직이 데이터 일관성을 보장합니다.


82-84: Java 버전이 이미 21로 설정되어 있으므로 호환성 문제 없음.

프로젝트의 build.gradle에 languageVersion = JavaLanguageVersion.of(21)이 설정되어 있어, getLast() 메서드는 Java 21에서 도입된 기능이지만 현재 프로젝트의 Java 버전과 일치합니다. 추가 조치가 필요하지 않습니다.

src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetMyGroupListV2Response.java (2)

39-68: DTO 팩토리 메서드 설계가 우수합니다.

계산된 필드(remainingSeats, joinable)를 팩토리 메서드에서 처리하는 것이 좋은 설계입니다. 특히:

  • Line 57: Math.max(0, ...) 로 음수 방지
  • Lines 58-61: RECRUITING 상태와 남은 좌석을 기반으로 한 joinable 로직이 명확함
  • 모든 GroupV2Status 값이 switch 표현식에서 처리됨

9-16: 불변 DTO 구조가 적절합니다.

Java record를 사용한 불변 DTO와 정적 팩토리 메서드 패턴이 잘 적용되었습니다.

src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (1)

125-154: 엔드포인트 구조가 적절합니다.

새로운 /me 엔드포인트가 기존 패턴을 잘 따르고 있으며, 파라미터 설계가 RESTful 원칙에 부합합니다. Line 140의 MyGroupTypeV2.from(type) 메서드는 null 값과 유효하지 않은 입력값에 대해 적절한 GroupException을 발생시키므로 예외 처리가 올바르게 구현되어 있습니다.

@LimdaeIl LimdaeIl merged commit 91a5c35 into main Dec 19, 2025
7 checks passed
@LimdaeIl LimdaeIl deleted the feat/my-group branch December 19, 2025 10:10
@github-project-automation github-project-automation bot moved this from In progress to Done in WeGo-Together Backend Dec 19, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a "My Groups V2 List" feature that allows users to retrieve their groups with various filtering options. The implementation adds a new /api/v2/groups/me endpoint with support for three group types: current groups, past groups, and groups created by the user (myPost).

Key changes include:

  • New GroupMyGetV2Service service layer for handling "my groups" business logic
  • Two new QueryDSL repository methods (fetchMyGroupRows and fetchMyPostGroupRows) for efficient data retrieval
  • Support for cursor-based pagination with customizable filtering by group status and user membership status
  • Enhanced response DTOs that include user membership information

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
GroupV2Controller.java Adds new /me GET endpoint with support for filtering by type, cursor pagination, and various status parameters
GroupMyGetV2Service.java New service class implementing business logic for retrieving user's groups with filtering and pagination
GroupV2QueryRepositoryImpl.java Implements two new QueryDSL methods for fetching user's groups with different join strategies based on query type
GroupV2QueryRepository.java Adds interface declarations for the new repository methods
MyGroupListRow.java New projection record for mapping query results with user membership details
GetMyGroupListV2Response.java Response DTO with nested Item record containing group details and calculated fields
MyGroupTypeV2.java Enum defining three types of "my groups" queries with string-based conversion
CreatedBy.java Adds static factory method of() for creating instances from individual fields
GroupV2Service.java Modifies COOL_DOWN_SECONDS constant from 30 to 5 (appears unrelated to main feature)
v2-group-get-me.http New HTTP test file with 12 test scenarios covering signup, login, group creation, and various "my groups" queries

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


BooleanBuilder where = new BooleanBuilder();
where.and(group.deletedAt.isNull());
where.and(group.host.id.eq(userId)); // ✅ 내가 만든 모임
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The inline comment uses an emoji checkmark (✅) which may not render properly in all environments and IDE configurations. Consider using standard comment text instead for better compatibility and professionalism.

Copilot uses AI. Check for mistakes.
.leftJoin(group.users, myGu)
.on(myGu.user.id.eq(userId))

// ✅ 참가자 수는 ATTEND만
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The inline comment uses an emoji checkmark (✅) which may not render properly in all environments and IDE configurations. Consider using standard comment text instead for better compatibility and professionalism.

Copilot uses AI. Check for mistakes.

}
}

Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Unnecessary blank line at the end of the file. Consider removing this extra line to maintain consistent file formatting.

Suggested change

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 23


Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Multiple unnecessary blank lines at the end of the file. Consider keeping only one blank line to maintain consistent file formatting.

Suggested change

Copilot uses AI. Check for mistakes.
host.id,
host.nickName,
host.profileImage,
host.profileMessage, // ✅ 추가
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The inline comment uses an emoji checkmark (✅) which may not render properly in all environments and IDE configurations. Consider using standard comment text instead for better compatibility and professionalism.

Copilot uses AI. Check for mistakes.
.from(group)
.join(group.host, host)

// ✅ 내 membership은 있을 수도/없을 수도 → left join + on(userId)
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The inline comment uses an emoji checkmark (✅) which may not render properly in all environments and IDE configurations. Consider using standard comment text instead for better compatibility and professionalism.

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +38


Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

Excessive blank lines between method declarations. Consider removing one of these blank lines to maintain consistent spacing with the rest of the interface.

Suggested change

Copilot uses AI. Check for mistakes.
@RequestParam(required = false) List<GroupV2Status> includeStatuses,
@RequestParam(required = false) List<GroupV2Status> excludeStatuses,

// ✅ 내 상태도 보고 싶으면: ATTEND,LEFT,KICKED,BANNED
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The inline comment uses an emoji checkmark (✅) which may not render properly in all environments and IDE configurations. Consider using standard comment text instead for better compatibility and professionalism.

Suggested change
// 내 상태도 보고 싶으면: ATTEND,LEFT,KICKED,BANNED
// NOTE: 내 상태도 보고 싶으면: ATTEND, LEFT, KICKED, BANNED

Copilot uses AI. Check for mistakes.
Comment on lines +142 to +180
private ResolvedStatuses resolveStatuses(
GroupListFilter filter,
List<GroupV2Status> includeStatuses,
List<GroupV2Status> excludeStatuses
) {
boolean hasInclude = includeStatuses != null && !includeStatuses.isEmpty();
boolean hasExclude = excludeStatuses != null && !excludeStatuses.isEmpty();

List<GroupV2Status> includes = filter.defaultIncludeStatuses();
List<GroupV2Status> excludes = filter.defaultExcludeStatuses();

if (includes == null) {
includes = List.of();
}
if (excludes == null) {
excludes = List.of();
}

if (hasInclude) {
includes = includeStatuses;
excludes = List.of();
}
if (hasExclude) {
excludes = excludeStatuses;
}

// include/exclude/filter 아무것도 안 왔고 ACTIVE면 기본 노출 세트
if (!hasInclude && !hasExclude && filter != GroupListFilter.ALL && includes.isEmpty()) {
includes = List.of(GroupV2Status.RECRUITING, GroupV2Status.FULL);
}

// 충돌 제거
if (!includes.isEmpty() && !excludes.isEmpty()) {
var includeSet = java.util.EnumSet.copyOf(includes);
excludes.forEach(includeSet::remove);
includes = List.copyOf(includeSet);
}

return new ResolvedStatuses(includes, excludes);
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The resolveStatuses method contains logic that is nearly identical to the status resolution logic in GroupV2Service (lines 77-116). This code duplication increases maintenance burden and risk of inconsistencies. Consider extracting this common logic into a shared utility class or helper method that both services can use.

Suggested change
private ResolvedStatuses resolveStatuses(
GroupListFilter filter,
List<GroupV2Status> includeStatuses,
List<GroupV2Status> excludeStatuses
) {
boolean hasInclude = includeStatuses != null && !includeStatuses.isEmpty();
boolean hasExclude = excludeStatuses != null && !excludeStatuses.isEmpty();
List<GroupV2Status> includes = filter.defaultIncludeStatuses();
List<GroupV2Status> excludes = filter.defaultExcludeStatuses();
if (includes == null) {
includes = List.of();
}
if (excludes == null) {
excludes = List.of();
}
if (hasInclude) {
includes = includeStatuses;
excludes = List.of();
}
if (hasExclude) {
excludes = excludeStatuses;
}
// include/exclude/filter 아무것도 안 왔고 ACTIVE면 기본 노출 세트
if (!hasInclude && !hasExclude && filter != GroupListFilter.ALL && includes.isEmpty()) {
includes = List.of(GroupV2Status.RECRUITING, GroupV2Status.FULL);
}
// 충돌 제거
if (!includes.isEmpty() && !excludes.isEmpty()) {
var includeSet = java.util.EnumSet.copyOf(includes);
excludes.forEach(includeSet::remove);
includes = List.copyOf(includeSet);
}
return new ResolvedStatuses(includes, excludes);
private static final class StatusResolutionHelper {
private StatusResolutionHelper() {
// utility class
}
private static ResolvedStatuses resolveStatuses(
GroupListFilter filter,
List<GroupV2Status> includeStatuses,
List<GroupV2Status> excludeStatuses
) {
boolean hasInclude = includeStatuses != null && !includeStatuses.isEmpty();
boolean hasExclude = excludeStatuses != null && !excludeStatuses.isEmpty();
List<GroupV2Status> includes = filter.defaultIncludeStatuses();
List<GroupV2Status> excludes = filter.defaultExcludeStatuses();
if (includes == null) {
includes = List.of();
}
if (excludes == null) {
excludes = List.of();
}
if (hasInclude) {
includes = includeStatuses;
excludes = List.of();
}
if (hasExclude) {
excludes = excludeStatuses;
}
// include/exclude/filter 아무것도 안 왔고 ACTIVE면 기본 노출 세트
if (!hasInclude && !hasExclude && filter != GroupListFilter.ALL && includes.isEmpty()) {
includes = List.of(GroupV2Status.RECRUITING, GroupV2Status.FULL);
}
// 충돌 제거
if (!includes.isEmpty() && !excludes.isEmpty()) {
var includeSet = java.util.EnumSet.copyOf(includes);
excludes.forEach(includeSet::remove);
includes = List.copyOf(includeSet);
}
return new ResolvedStatuses(includes, excludes);
}
}
private ResolvedStatuses resolveStatuses(
GroupListFilter filter,
List<GroupV2Status> includeStatuses,
List<GroupV2Status> excludeStatuses
) {
return StatusResolutionHelper.resolveStatuses(filter, includeStatuses, excludeStatuses);

Copilot uses AI. Check for mistakes.
private static final int MAX_PAGE_SIZE = 50;
private static final int GROUP_LIST_IMAGE_LIMIT = 3;
private static final int COOL_DOWN_SECONDS = 30;
private static final int COOL_DOWN_SECONDS = 5;
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The COOL_DOWN_SECONDS has been changed from 30 to 5 seconds. This appears to be unrelated to the "My Groups V2 List" feature and seems like a temporary change for testing purposes. If this change is intentional for production, it significantly reduces the cooldown period which may lead to abuse. If this is only for testing, it should not be committed to the main branch as it weakens the rate limiting mechanism.

Suggested change
private static final int COOL_DOWN_SECONDS = 5;
private static final int COOL_DOWN_SECONDS = 30;

Copilot uses AI. Check for mistakes.
@coderabbitai coderabbitai bot mentioned this pull request Dec 22, 2025
14 tasks
@coderabbitai coderabbitai bot mentioned this pull request Jan 1, 2026
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[FEAT] 내 모임 V2 목록 조회 기능 구현

1 participant

Comments