Conversation
그룹 출석 기능을 도입하여 사용자가 그룹에 참여하고 나갈 수 있도록 합니다. 다양한 출석 관련 시나리오에 대한 새로운 오류 코드를 추가합니다. 유연한 그룹 참여를 위해 참여 정책(즉시 참여, 승인 필요)을 통합합니다. 참여 정책 정보를 포함하도록 그룹 목록 및 상세 정보 응답을 재구성합니다. 출석 및 퇴장 작업을 처리하는 출석 관리 전용 서비스를 구현합니다.
개요그룹 가입 정책(INSTANT, APPROVAL_REQUIRED, INVITE_ONLY)을 도입하고, 멤버십 상태 관리 개선, 그룹 참여/퇴출 로직을 전용 서비스로 분리했습니다. 에러 핸들링 강화 및 다중 DTO 확장을 통해 정책 정보를 응답에 포함시켰습니다. 변경사항
시퀀스 다이어그램sequenceDiagram
participant Client
participant Controller as GroupV2Controller
participant AttendService as GroupV2AttendanceService
participant GroupRepo as GroupV2Repository
participant UserRepo as GroupUserV2Repository
participant Domain as GroupUserV2 Domain
Client->>Controller: attend(userId, groupId)
activate Controller
Controller->>AttendService: attend(userId, groupId)
activate AttendService
AttendService->>GroupRepo: findById(groupId)
activate GroupRepo
GroupRepo-->>AttendService: group
deactivate GroupRepo
AttendService->>AttendService: 검증: 호스트 제약, 그룹 상태, 용량
AttendService->>UserRepo: findByGroupIdAndUserId(groupId, userId)
activate UserRepo
UserRepo-->>AttendService: existingMembership (optional)
deactivate UserRepo
alt 기존 멤버십 없음
AttendService->>Domain: GroupUserV2.createPending(group, user)
activate Domain
Domain->>Domain: 가입정책 확인
alt 정책 = INSTANT
Domain->>Domain: status = ATTEND
else 정책 = APPROVAL_REQUIRED
Domain->>Domain: status = PENDING
end
Domain-->>AttendService: newMembership
deactivate Domain
else 기존 멤버십 있음
AttendService->>Domain: existingMembership.requestJoin()
activate Domain
Domain->>Domain: 상태 전이 (CANCELLED/LEFT → PENDING)
Domain-->>AttendService: void
deactivate Domain
end
AttendService->>AttendService: ATTEND 인원 재계산, FULL 상태 업데이트
AttendService->>GroupRepo: save(group)
AttendService-->>Controller: AttendanceGroupV2Response
deactivate AttendService
Controller-->>Client: ApiResponse<AttendanceGroupV2Response>
deactivate Controller
Client->>Controller: left(userId, groupId)
activate Controller
Controller->>AttendService: left(userId, groupId)
activate AttendService
AttendService->>GroupRepo: findById(groupId)
AttendService->>UserRepo: findByGroupIdAndUserId(groupId, userId)
AttendService->>Domain: membership.leaveOrCancel()
activate Domain
Domain->>Domain: 상태 기반 처리 (ATTEND → LEFT, PENDING → CANCELLED)
Domain-->>AttendService: void
deactivate Domain
AttendService->>AttendService: ATTEND 인원 재계산, RECRUITING 상태 복구
AttendService->>GroupRepo: save(group)
AttendService-->>Controller: AttendanceGroupV2Response
deactivate AttendService
Controller-->>Client: ApiResponse<AttendanceGroupV2Response>
deactivate Controller
예상 코드 리뷰 난이도🎯 4 (복잡함) | ⏱️ ~50분 주의 깊게 검토할 영역:
관련 가능성 있는 PR들
마음 전하는 시
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (6)
src/test/http/group/v2/v2-group-attend-approval-required.http (1)
147-149: 선택적 테스트에 응답 검증 추가를 고려해 주세요.Line 147의 상세 조회 테스트에 응답 검증 블록이 없습니다. MEMBER1의 상태가 PENDING인지 확인하는 assertion을 추가하면 테스트 완성도가 높아집니다.
🔎 응답 검증 블록 제안
### 7. (선택) 모임 상세 조회 - MEMBER1 토큰으로 내 상태 확인 GET http://localhost:8080/api/v2/groups/{{groupId_approvalTest}} Authorization: Bearer {{member1AccessToken}} + +> {% + client.test("응답 성공", () => client.assert(response.status === 200)); + // 필요시 멤버 상태 검증 추가 +%}src/test/http/group/v2/v2-group-update.http (1)
353-354: 테스트 데이터의 날짜가 과거입니다.
startTime이2025-12-30으로 설정되어 있는데, 현재 날짜(2025년 12월)와 가까워 곧 과거 날짜가 됩니다. 모임 생성/수정 시 과거 날짜 검증 로직이 있다면 테스트가 실패할 수 있습니다. 미래 날짜(예: 2026년)로 변경하는 것이 좋습니다.🔎 날짜 수정 제안
- "startTime": "2025-12-30T19:00:00", - "endTime": "2025-12-30T21:00:00", + "startTime": "2026-12-30T19:00:00", + "endTime": "2026-12-30T21:00:00",src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2UpdateService.java (1)
127-151: 미사용 메서드가 있습니다.
defaultLogoItem()메서드가 정의되어 있지만 현재 어디에서도 호출되지 않습니다. Lines 107-109에서imageItems가 비어있을 때 기본 이미지를 설정하려는 의도로 보이지만, 실제로는 빈 ArrayList만 생성하고 있습니다.의도된 동작인지 확인이 필요합니다:
- 기본 이미지가 필요 없다면 이 메서드를 제거
- 기본 이미지가 필요하다면 Lines 107-109 수정
🔎 기본 이미지 적용 예시
// 이미지가 0개면 기본 이미지(variants 2개) 1장 내려주기 if (imageItems.isEmpty()) { - imageItems = new ArrayList<>(); + imageItems = List.of(defaultLogoItem()); }src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java (1)
90-92:getReferenceById사용 시 사용자 존재 여부 미검증
userRepository.getReferenceById(userId)는 프록시만 반환하므로, 존재하지 않는 사용자 ID가 전달될 경우 나중에EntityNotFoundException이 발생합니다. 입력 검증 단계에서 사용자 존재 여부를 확인하는 것이 좋습니다.src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (1)
90-100:left()엔드포인트 업데이트 적절함
attend()와 동일한 패턴으로 새 서비스로 위임합니다.참고: HTTP 메서드가
POST로 되어 있는데,left액션은 상태 변경이므로DELETE나PATCH가 RESTful 관례에 더 부합할 수 있습니다. 하지만 기존 API 계약이 있다면 유지해도 무방합니다.src/test/http/group/v2/V2-group-left.http (1)
58-81:joinPolicy필드 누락 (선택사항)모임 생성 요청에
joinPolicy필드가 포함되지 않았습니다. 기본값(INSTANT)이 적용되어 테스트는 동작하지만, 명시적으로 추가하면 테스트 의도가 더 명확해집니다."description": "left() 성공/중복 left/HOST left 불가를 테스트합니다.", "maxParticipants": 5, + "joinPolicy": "INSTANT", "images": [
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (34)
src/main/java/team/wego/wegobackend/group/domain/exception/GroupErrorCode.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/common/MyMembership.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/AttendanceGroupV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/CreateGroupV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupListV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetMyGroupListV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/dto/response/UpdateGroupV2Response.javasrc/main/java/team/wego/wegobackend/group/v2/application/service/GroupMyGetV2Service.javasrc/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.javasrc/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.javasrc/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2UpdateService.javasrc/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2.javasrc/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.javasrc/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2.javasrc/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2JoinPolicy.javasrc/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2Status.javasrc/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/GroupV2QueryRepositoryImpl.javasrc/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/GroupListRow.javasrc/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/MyGroupListRow.javasrc/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.javasrc/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2ControllerDocs.javasrc/test/http/group/group-attend.httpsrc/test/http/group/v2/V2-group-left.httpsrc/test/http/group/v2/v2-group-attend-approval-required.httpsrc/test/http/group/v2/v2-group-attend-instant.httpsrc/test/http/group/v2/v2-group-attend.httpsrc/test/http/group/v2/v2-group-create.httpsrc/test/http/group/v2/v2-group-delete.httpsrc/test/http/group/v2/v2-group-get-list.httpsrc/test/http/group/v2/v2-group-get-me.httpsrc/test/http/group/v2/v2-group-get.httpsrc/test/http/group/v2/v2-group-update.http
💤 Files with no reviewable changes (1)
- src/test/http/group/v2/v2-group-attend.http
🔇 Additional comments (42)
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.java (1)
3-11: LGTM! 승인제 기능을 위한 상태값 추가가 적절합니다.PENDING, REJECTED, CANCELLED 상태가 추가되어 승인 기반 참여 흐름을 지원합니다. 상태 정의가 명확하고 완전합니다.
src/test/http/group/v2/v2-group-update.http (1)
265-381: 이미지 업로드 및 PATCH 테스트 예제 추가가 잘 되었습니다.다양한 필드와 이미지 교체 시나리오를 커버하는 종합적인 테스트 흐름입니다. assertion을 통한 검증도 충실합니다.
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2.java (3)
129-136:createPending()팩토리 메서드가 적절하게 구현되었습니다.승인제 모임의 가입 요청을 위한 PENDING 상태 생성이 잘 캡슐화되어 있습니다.
148-180:leaveOrCancel()상태 기반 핸들링이 잘 구현되었습니다.switch 표현식을 사용하여 각 상태별 처리가 명확하게 분리되어 있고, 모든 케이스에 대해 적절한 예외를 던지고 있습니다. default 케이스로 방어적 처리도 되어 있습니다.
85-92:leave()메서드의 예외 처리 개선이 좋습니다.기존 silent failure 대신 명시적 예외를 던지도록 변경되어 디버깅과 오류 추적이 용이해졌습니다.
src/main/java/team/wego/wegobackend/group/domain/exception/GroupErrorCode.java (2)
11-39: 에러 코드 추가가 잘 설계되었습니다.각 상태 전이 시나리오에 대해 적절한 HTTP 상태 코드(CONFLICT, FORBIDDEN, BAD_REQUEST)가 사용되었고, 메시지 템플릿에 컨텍스트 정보(%s 포맷)가 포함되어 있어 디버깅에 유용합니다.
86-86:ALREADY_REQUESTED_TO_JOIN에러 코드 추가 확인.중복 가입 요청에 대한 에러 코드가 적절하게 추가되었습니다. 이 에러 코드가
GroupUserV2.requestJoin()메서드에서 활용되어야 합니다.src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/MyGroupListRow.java (1)
6-6: 변경 사항 확인 완료.
GroupV2JoinPolicy타입의joinPolicy필드가 레코드에 추가되어 프로젝션 레이어를 통해 참여 정책 정보가 전달됩니다. 구조적으로 문제없습니다.Also applies to: 12-12
src/test/http/group/v2/v2-group-delete.http (1)
60-60: 테스트 페이로드 업데이트 확인.삭제 테스트에
joinPolicy: "INSTANT"필드가 추가되어 새로운 API 요구사항을 반영합니다. 삭제 로직은 참여 정책과 무관하므로 이 테스트에서 단일 정책만 사용하는 것은 적절합니다.Also applies to: 155-155
src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/projection/GroupListRow.java (1)
4-4: 변경 사항 확인 완료.
GroupListRow프로젝션에joinPolicy필드가 추가되어MyGroupListRow와 일관된 구조를 유지합니다.Also applies to: 10-10
src/test/http/group/v2/v2-group-get.http (1)
64-64: 테스트 페이로드 업데이트 확인.조회 테스트에
joinPolicy필드가 추가되어 API 변경사항을 반영합니다.Also applies to: 105-105
src/test/http/group/v2/v2-group-create.http (1)
62-62: 테스트 페이로드에 joinPolicy 필드 추가 확인.모든 모임 생성 테스트에
joinPolicy: "INSTANT"필드가 추가되어 새로운 API 요구사항을 반영합니다.Also applies to: 129-129, 190-190, 281-281
src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupListV2Response.java (2)
5-5: DTO에 joinPolicy 필드 추가 확인.
GroupV2JoinPolicy필드가 응답 DTO에 추가되고 팩토리 메서드를 통해 올바르게 전파됩니다. 구조적으로 문제없습니다.Also applies to: 20-20, 50-50, 77-77
69-72: joinable 계산 로직에 joinPolicy 고려 필요 여부 확인.현재
joinable플래그는status와remainingSeats만 기반으로 계산됩니다. 그러나joinPolicy가APPROVAL_REQUIRED또는INVITE_ONLY인 경우, 즉시 참여가 불가능하므로 이 로직에 joinPolicy도 반영해야 할 수 있습니다.예를 들어:
INSTANT: 현재 로직 유지APPROVAL_REQUIRED:joinable은 true지만 승인 대기 상태 표시 필요INVITE_ONLY:joinable은 false여야 할 수 있음joinPolicy에 따른 비즈니스 요구사항을 확인하고, 필요시 로직을 조정하세요.
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2Status.java (1)
27-30: CLOSED 상태에서 퇴장 허용 여부 확인 필요.
canLeaveOrCancel()메서드가CLOSED상태에서도 true를 반환합니다.CLOSED는 "모집마감 (더 이상 참가 불가)" 상태인데, 이미 참가한 사용자가 퇴장할 수 있어야 하는지 비즈니스 요구사항을 확인하세요.일반적으로:
- 모집이 마감되었다면 신규 참가는 불가하지만, 기존 참가자의 퇴장은 허용될 수 있습니다.
- 또는 모집 마감 후에는 참가자 변경을 모두 불허할 수도 있습니다.
비즈니스 정책에 따라 로직을 확인하고, 주석에 정책을 명시하는 것을 권장합니다.
src/test/http/group/v2/v2-group-get-list.http (1)
63-63: 테스트 페이로드 업데이트 확인.목록 조회 테스트에
joinPolicy필드가 추가되어 API 변경사항을 반영합니다.src/test/http/group/v2/v2-group-get-me.http (1)
60-60: 테스트 페이로드가 새로운 joinPolicy 필드를 올바르게 반영하고 있습니다.INSTANT 정책으로 테스트하는 것이 적절합니다.
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupMyGetV2Service.java (1)
99-136: 변수명 리팩토링과 joinPolicy 필드 추가가 잘 되었습니다.
r에서myGroupListRow로 변수명을 변경하여 가독성이 크게 향상되었으며, joinPolicy 필드가 모든 응답 매핑에 일관되게 추가되었습니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/common/MyMembership.java (1)
31-44: 새로운 팩토리 메서드가 잘 구현되었습니다.null 체크 로직이 기존
from(List, Long)메서드(line 28)와 일관된 패턴을 따르고 있으며, GroupUserV2에서 MyMembership으로의 매핑이 명확합니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/response/UpdateGroupV2Response.java (1)
8-24: UpdateGroupV2Response에 joinPolicy 필드가 올바르게 추가되었습니다.다른 V2 응답 DTO들과 일관된 구조를 유지하고 있습니다.
src/main/java/team/wego/wegobackend/group/v2/infrastructure/querydsl/GroupV2QueryRepositoryImpl.java (3)
74-117: QueryDSL 프로젝션과 GROUP BY 절이 올바르게 업데이트되었습니다.Line 78에서
group.joinPolicy를 SELECT 프로젝션에 추가하고, Line 101에서groupBy절에도 동일하게 추가하여 SQL GROUP BY 오류를 방지했습니다. 이는 QueryDSL에서 집계 쿼리를 작성할 때 필수적인 패턴입니다.
223-289: fetchMyGroupRows 메서드의 프로젝션이 일관되게 업데이트되었습니다.Line 228과 Line 264에서
group.joinPolicy가 프로젝션과 groupBy 절에 모두 올바르게 추가되었습니다.
319-360: fetchMyPostGroupRows 메서드의 프로젝션이 올바르게 업데이트되었습니다.Line 322와 Line 347에서
group.joinPolicy가 일관되게 추가되었습니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/response/CreateGroupV2Response.java (1)
13-71: CreateGroupV2Response에 joinPolicy 필드가 올바르게 추가되었습니다.Line 21에서 필드를 선언하고 Line 56에서
group.getJoinPolicy()를 통해 도메인 엔티티로부터 값을 가져오는 패턴이 적절합니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupV2Response.java (1)
24-24: LGTM!
joinPolicy필드가 응답 DTO에 올바르게 추가되었습니다. 필드 위치도title다음,status앞으로 논리적인 순서입니다.Also applies to: 89-89
src/test/http/group/group-attend.http (1)
1-145: LGTM!테스트 케이스 구조가 명확하게 재정리되었습니다. 단계별 넘버링(0, 0-1, 1-1...)이 플로우를 이해하기 쉽게 만들어줍니다. 주요 시나리오(성공적인 참여, 중복 참여 예외, 호스트 자가 참여 예외)가 잘 커버되어 있습니다.
src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2ControllerDocs.java (1)
17-17: LGTM!
AttendanceGroupV2Response로의 타입 변경이 일관되게 적용되었습니다.attend와left엔드포인트가 동일한 응답 타입을 반환하는 것이 적절합니다.Also applies to: 54-54, 64-64
src/test/http/group/v2/v2-group-attend-instant.http (1)
1-195: LGTM! 포괄적인 테스트 시나리오입니다.INSTANT 정책에 대한 출석 플로우가 잘 구성되어 있습니다:
- 성공 케이스: 참여, 나가기, 재참여
- 예외 케이스: 중복 참여, 중복 나가기, 호스트 자가 참여
APPROVAL_REQUIRED및INVITE_ONLY정책에 대한 유사한 테스트 파일도 추후 추가하면 좋겠습니다.src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2UpdateService.java (1)
111-124: LGTM!
joinPolicy필드가UpdateGroupV2Response에 올바르게 전달되었습니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetMyGroupListV2Response.java (1)
22-22: LGTM!
joinPolicy필드가Item레코드에 일관되게 추가되었습니다. 다른 응답 DTO들과 필드 순서가 동일하여 API 응답의 일관성이 유지됩니다.Also applies to: 44-44, 66-66
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2.java (2)
68-71: LGTM!
joinPolicy필드가 올바르게 매핑되었습니다:
EnumType.STRING사용으로 DB 가독성과 마이그레이션 안전성 확보nullable = false로 필수 필드 보장length = 30은 현재 enum 값들(INSTANT, APPROVAL_REQUIRED, INVITE_ONLY)을 충분히 수용
88-99: 기본값 로직이 적절합니다.
joinPolicy가null일 경우INSTANT로 기본값 설정하는 방어적 프로그래밍이 적용되어 있습니다.CreateGroupV2Request에서@NotNull검증이 있지만, 엔티티 레벨에서의 방어 로직은 직접 엔티티 생성 시나리오에 대비하여 유용합니다.src/main/java/team/wego/wegobackend/group/v2/application/dto/response/AttendanceGroupV2Response.java (1)
9-33: LGTM!
AttendanceGroupV2Response로의 리네이밍이 적절합니다. "Attendance"가 참여(attend)와 퇴장(left) 양쪽 동작을 포괄하는 명칭입니다.joinPolicy필드 추가와 팩토리 메서드 업데이트가 일관되게 적용되었습니다.src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java (2)
125-132: APPROVAL_REQUIRED 브랜치에서 정원 체크 로직 검토 필요
APPROVAL_REQUIRED정책에서는requestJoin()이PENDING상태로 변경합니다.PENDING상태는attendCount에 포함되지 않으므로, Line 129-131의 정원 초과 체크는 실제로 트리거되지 않습니다.주석에 "재참여 포함해서 체크"라고 되어 있지만,
requestJoin()은ATTEND가 아닌PENDING으로 변경하므로 이 체크는 의미가 없어 보입니다. 승인 시점에서 정원 체크가 필요합니다.
148-193:left()메서드 로직 적절함
left()메서드는 HOST 나가기 방지, 상태 기반 검증, 도메인 위임(leaveOrCancel()), FULL → RECRUITING 자동 복귀 등 필요한 로직이 잘 구현되어 있습니다.src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java (2)
143-143:joinPolicy필드 추가 적절함모임 목록 응답에
joinPolicy가 포함되어, 클라이언트가 참여 정책을 미리 확인할 수 있습니다.
186-195: 모임 생성 시joinPolicy전달 구조 적절함
request.joinPolicy()를 도메인 레이어로 전달하고, null 처리는 도메인에서 담당하는 구조가 깔끔합니다.src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (2)
47-47: 새로운 서비스 의존성 주입 적절함
GroupV2AttendanceService분리로 관심사가 명확하게 분리되었습니다.
75-87:attend()엔드포인트 업데이트 적절함새로운
GroupV2AttendanceService로 위임하고, 응답 타입이AttendanceGroupV2Response로 변경되었습니다. 기존 패턴과 일관성을 유지합니다.src/test/http/group/v2/V2-group-left.http (3)
164-170: 중복left()테스트 케이스 좋음
LEFT상태에서 다시left()호출 시 예외 처리를 검증하는 테스트입니다. 주석에 예상 동작이 잘 설명되어 있습니다.
172-177: HOSTleft()불가 테스트 케이스 좋음HOST가 자신의 모임을 떠날 수 없다는 비즈니스 규칙을 검증합니다.
179-185: 상세 조회 테스트로 상태 확인 가능
left()이후 모임 상세 조회를 통해 참여 인원 및 상태 변경을 확인할 수 있어 유용합니다.
| @NotNull(message = "모임: 참여 방식(joinPolicy)은 필수 입니다.") | ||
| GroupV2JoinPolicy joinPolicy, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find and examine CreateGroupV2Request.java file
find . -type f -name "CreateGroupV2Request.java" | head -5Repository: WeGo-Together/WeGo_BackEnd
Length of output: 166
🏁 Script executed:
# Read the CreateGroupV2Request.java file
cat -n ./src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 1869
🏁 Script executed:
# Search for all usages of CreateGroupV2Request
rg -nP --type=java 'CreateGroupV2Request' -g '!**/test/**' -A 3 -B 3Repository: WeGo-Together/WeGo_BackEnd
Length of output: 7055
🏁 Script executed:
# Check if there's a V1 version of CreateGroupRequest to see how it handled joinPolicy
find . -type f -name "*CreateGroup*Request.java" | grep -v test | head -20Repository: WeGo-Together/WeGo_BackEnd
Length of output: 463
🏁 Script executed:
# Examine the V1 CreateGroupRequest to see how joinPolicy was handled
cat -n ./src/main/java/team/wego/wegobackend/group/application/dto/v1/request/CreateGroupRequest.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 1580
🏁 Script executed:
# Check the GroupV2JoinPolicy enum to see available values
find . -type f -name "GroupV2JoinPolicy.java" | head -5Repository: WeGo-Together/WeGo_BackEnd
Length of output: 153
🏁 Script executed:
# Examine the GroupV2JoinPolicy enum
cat -n ./src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2JoinPolicy.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 370
🏁 Script executed:
# Check if there are any tests or documentation that show how joinPolicy should be provided
rg -nP --type=java 'GroupV2JoinPolicy\.' -g '!**/test/**' | head -20Repository: WeGo-Together/WeGo_BackEnd
Length of output: 562
🏁 Script executed:
# Examine the GroupV2.java to see the full context of joinPolicy handling
sed -n '90,110p' ./src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 799
🏁 Script executed:
# Check how the request is used in the service layer
sed -n '170,200p' ./src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 1114
V2 API의 joinPolicy 필드가 필수값(@NotNull)으로 요구되어 클라이언트 업그레이드 필요합니다.
CreateGroupV2Request의 joinPolicy 필드에 @NotNull 제약이 있어 이 필드를 제공하지 않는 요청은 검증 단계에서 실패합니다. V2 API를 사용하는 클라이언트는 요청 시 joinPolicy를 포함해야 합니다.
주목할 점:
- GroupV2 엔티티에는 joinPolicy가 null일 때 기본값 INSTANT를 설정하는 로직이 있으나(GroupV2.java:99), DTO 검증 단계에서 @NotNull이 먼저 작동합니다.
- V2 API의 신규 필드이므로, 기존 V1 API 사용자는 업데이트 필요합니다.
- 기본값 활용이 필요한 경우, 요청 DTO에서 joinPolicy를 선택 필드로 변경하고 @nullable로 처리한 후 서비스 계층의 기본값 로직을 활용할 수 있습니다.
🤖 Prompt for AI Agents
In
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.java
around lines 40-41, the joinPolicy DTO field is annotated @NotNull which causes
validation failures before the entity-level default (INSTANT) can be applied;
remove the @NotNull constraint and make the field nullable/optional (e.g.,
annotate as @Nullable or use Optional) so clients can omit it, and ensure
service/entity code continues to apply the existing default when joinPolicy is
null.
| private final UserRepository userRepository; | ||
|
|
||
|
|
||
| // TODO: 참석, 취소 동시성 해결 필요. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "GroupV2AttendanceService.java" 2>/dev/nullRepository: WeGo-Together/WeGo_BackEnd
Length of output: 166
🏁 Script executed:
cat -n ./src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java | head -200Repository: WeGo-Together/WeGo_BackEnd
Length of output: 9162
상태 변경 후 정원 체크로 인한 레이스 컨디션 발생
attend() 메서드에서 상태 변경(88, 90-92줄)이 먼저 이루어진 후 정원 체크(96-97줄)가 수행됩니다. 두 스레드가 동시에 요청할 때, 첫 번째 스레드가 상태를 ATTEND로 변경한 후 정원을 초과해도 두 번째 스레드는 이미 stale한 카운트로 체크했기 때문에 정원 제한을 무시하고 진행할 수 있습니다.
비관적 락(Hibernate @Lock(LockModeType.PESSIMISTIC_WRITE))이나 Redis 분산 락을 사용하여 상태 변경 전에 정원을 검증하세요.
🤖 Prompt for AI Agents
In
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java
around lines 31 and specifically the attend() flow at ~88-97, the code changes
the attendee status before checking capacity which can cause a race where two
threads both pass a stale capacity check; change the flow to perform capacity
validation and update within a single transactional locked section: acquire a DB
pessimistic write lock on the group/attendance rows (or use a Redis distributed
lock keyed by group id) before reading current attendee count, verify capacity,
then set the attendee status and persist, ensuring the operation is atomic and
rolls back on failure; alternatively, move the capacity check before status
mutation only inside the locked transaction so concurrent requests cannot bypass
the limit.
| // 정원 체크(ATTEND만 카운트) | ||
| long attendCount = groupUserV2Repository.countByGroupIdAndStatus(groupId, | ||
| GroupUserV2Status.ATTEND); | ||
| if (attendCount > group.getMaxParticipants()) { | ||
| throw new GroupException(GroupErrorCode.GROUP_IS_FULL, groupId); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
정원 체크 시점에서 레이스 컨디션 발생 가능
reAttend() 또는 save() 이후에 countByGroupIdAndStatus()를 호출하므로, 동시 요청 시 이미 정원이 초과된 상태에서 예외가 발생합니다. 이 경우 트랜잭션 롤백으로 데이터는 정리되지만, 사용자 경험이 좋지 않을 수 있습니다.
또한 Line 98에서 attendCount > group.getMaxParticipants() 조건은 이미 자신이 포함된 카운트이므로 >= 대신 >가 맞습니다. 하지만 정원 체크를 상태 변경 전에 수행하는 것이 더 안전합니다.
🔎 정원 체크를 먼저 수행하는 방식 제안
if (group.getJoinPolicy() == GroupV2JoinPolicy.INSTANT) {
+ // 정원 체크를 먼저 수행
+ long currentAttendCount = groupUserV2Repository.countByGroupIdAndStatus(groupId,
+ GroupUserV2Status.ATTEND);
+ if (currentAttendCount >= group.getMaxParticipants()) {
+ throw new GroupException(GroupErrorCode.GROUP_IS_FULL, groupId);
+ }
+
if (groupUserV2 != null) {
// LEFT, KICKED, REJECTED, CANCELLED -> 재참여
groupUserV2.reAttend(); // 내부에서 BANNED만 막고, ATTEND로 변경
} else {
groupUserV2 = GroupUserV2.create(group, userRepository.getReferenceById(userId),
GroupUserV2Role.MEMBER);
groupUserV2Repository.save(groupUserV2);
}
- // 정원 체크(ATTEND만 카운트)
- long attendCount = groupUserV2Repository.countByGroupIdAndStatus(groupId,
- GroupUserV2Status.ATTEND);
- if (attendCount > group.getMaxParticipants()) {
- throw new GroupException(GroupErrorCode.GROUP_IS_FULL, groupId);
- }
+ long attendCount = currentAttendCount + 1;
// FULL 자동 전환🤖 Prompt for AI Agents
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.java
around lines 95-100: the capacity check currently runs after you change/save the
user's attendance which can cause race conditions and the comparison logic is
inverted for a pre-check; move the attendCount check to BEFORE changing/saving
the user's status, compute attendCount without the current user and use >=
group.getMaxParticipants() to reject when the group is already full, perform the
check inside the same transaction and obtain a lock on the group row (e.g.,
SELECT FOR UPDATE or repository method with a pessimistic lock) or rely on a DB
constraint to prevent races, and if the check fails throw GroupException
immediately without persisting the attendance change.
| public void requestJoin() { | ||
| if (this.status == GroupUserV2Status.BANNED) { | ||
| throw new GroupException(GroupErrorCode.GROUP_BANNED_USER); | ||
| } | ||
| // 이미 ATTEND, PENDING이면 상위에서 걸러도 되고 여기서 방어해도 가능하다고 판단 | ||
| this.status = GroupUserV2Status.PENDING; | ||
| this.joinedAt = LocalDateTime.now(); | ||
| this.leftAt = null; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find all calls to requestJoin() method
rg -n "requestJoin\(\)" --type=java -B5 -A5Repository: WeGo-Together/WeGo_BackEnd
Length of output: 2908
🏁 Script executed:
#!/bin/bash
# Check GroupErrorCode for the suggested error codes
rg -n "ALREADY_ATTEND_GROUP|ALREADY_REQUESTED_TO_JOIN|GROUP_BANNED_USER" --type=javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 1795
🏁 Script executed:
#!/bin/bash
# Get the full context around the requestJoin() call in the service
sed -n '100,130p' src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 1337
🏁 Script executed:
#!/bin/bash
# Get the full method context from the beginning
sed -n '50,125p' src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2AttendanceService.javaRepository: WeGo-Together/WeGo_BackEnd
Length of output: 3136
🏁 Script executed:
#!/bin/bash
# Find all requestJoin() calls throughout the codebase
rg "\.requestJoin\(\)" --type=java -B2 -A2Repository: WeGo-Together/WeGo_BackEnd
Length of output: 806
requestJoin() 메서드에서 ATTEND 및 PENDING 상태 체크 추가 권장
현재 구현은 BANNED 상태만 체크하고 있습니다. 다만 서비스 레이어(GroupV2AttendanceService)에서 호출 전에 ATTEND 및 PENDING 상태를 사전 검증하고 있어 실제 위험은 낮습니다. 그러나 도메인 엔티티 레벨에서의 방어적 처리를 위해 다음과 같은 체크 추가를 권장합니다:
public void requestJoin() {
if (this.status == GroupUserV2Status.BANNED) {
throw new GroupException(GroupErrorCode.GROUP_BANNED_USER);
}
+ if (this.status == GroupUserV2Status.ATTEND) {
+ throw new GroupException(
+ GroupErrorCode.ALREADY_ATTEND_GROUP,
+ this.group.getId(),
+ this.user.getId()
+ );
+ }
+ if (this.status == GroupUserV2Status.PENDING) {
+ throw new GroupException(
+ GroupErrorCode.ALREADY_REQUESTED_TO_JOIN,
+ this.group.getId(),
+ this.user.getId()
+ );
+ }
this.status = GroupUserV2Status.PENDING;
this.joinedAt = LocalDateTime.now();
this.leftAt = null;
}이렇게 하면 엔티티 메서드가 독립적으로 도메인 불변성을 보장하고 다른 방어 메서드들(예: leaveOrCancel())과 일관성을 유지합니다.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2.java
around lines 138 to 146, the requestJoin() method currently only guards against
BANNED; add defensive checks for ATTEND and PENDING before mutating state.
Specifically, if this.status == GroupUserV2Status.ATTEND throw new
GroupException(GroupErrorCode.GROUP_ALREADY_JOINED) (or the existing error code
used for already-attending users), and if this.status ==
GroupUserV2Status.PENDING throw new
GroupException(GroupErrorCode.GROUP_ALREADY_REQUESTED) (or the appropriate
existing error code for duplicate requests); only then set status = PENDING,
joinedAt = LocalDateTime.now(), leftAt = null. Ensure you use the same
GroupErrorCode enums used elsewhere for consistency.
| public enum GroupV2JoinPolicy { | ||
| INSTANT, // 참여 버튼 누르면 즉시 ATTEND | ||
| APPROVAL_REQUIRED, // 참여 버튼 누르면 신청 상태로 들어가고 HOST 승인 후 ATTEND | ||
| INVITE_ONLY // (미정)초대 받은 사람만 참여 | ||
| } |
There was a problem hiding this comment.
INVITE_ONLY 정책이 "미정" 상태로 표시되어 있습니다.
Line 6의 주석에서 INVITE_ONLY가 아직 결정되지 않은 기능("미정")으로 표시되어 있습니다. 프로덕션 코드에 미정 상태의 enum 값을 포함하면 다음과 같은 문제가 발생할 수 있습니다:
- API 사용자가 해당 정책을 선택했을 때 예상치 못한 동작 발생 가능
- 향후 해당 정책의 의미가 변경될 경우 breaking change 발생
다음 중 하나를 고려해 주세요:
- INVITE_ONLY 정책이 구현될 때까지 enum에서 제거
- 선택 시 명확한 에러 메시지와 함께 예외 처리 추가
- 구현이 완료되어 있다면 "(미정)" 주석 제거
해당 정책의 구현 상태를 확인하고 싶으시면, 다음 스크립트로 INVITE_ONLY 사용처를 검색할 수 있습니다:
#!/bin/bash
# INVITE_ONLY 정책이 실제로 처리되는 로직이 있는지 확인
rg -nP --type=java -C3 'INVITE_ONLY' -g '!**/test/**'🤖 Prompt for AI Agents
In
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2JoinPolicy.java
around lines 3–7, the INVITE_ONLY enum value is marked as "(미정)" which is unsafe
to keep in production; either remove INVITE_ONLY until its behavior is
implemented, or if it must remain, add handling so any selection of INVITE_ONLY
throws a clear, documented IllegalStateException (or similar) at runtime with a
user-facing error message, or if the feature is already implemented, simply
remove the "(미정)" comment; verify usages with the provided ripgrep command and
update tests and API docs accordingly.
| { | ||
| "sortOrder": 1, | ||
| "imageKey": "{{img0_key}}" | ||
| }, | ||
| { | ||
| "sortOrder": 2, | ||
| "imageKey": "{{img1_key}}" | ||
| } |
There was a problem hiding this comment.
sortOrder 시작 인덱스 불일치.
이 페이로드의 sortOrder가 1, 2로 시작하는 반면, 동일 파일의 다른 테스트 케이스(Line 142-152, 294-304)는 0부터 시작합니다. 일관성을 위해 0부터 시작하도록 수정하는 것을 권장합니다.
🔎 수정 제안
"images": [
{
- "sortOrder": 1,
+ "sortOrder": 0,
"imageKey": "{{img0_key}}"
},
{
- "sortOrder": 2,
+ "sortOrder": 1,
"imageKey": "{{img1_key}}"
}
]📝 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.
| { | |
| "sortOrder": 1, | |
| "imageKey": "{{img0_key}}" | |
| }, | |
| { | |
| "sortOrder": 2, | |
| "imageKey": "{{img1_key}}" | |
| } | |
| { | |
| "sortOrder": 0, | |
| "imageKey": "{{img0_key}}" | |
| }, | |
| { | |
| "sortOrder": 1, | |
| "imageKey": "{{img1_key}}" | |
| } |
🤖 Prompt for AI Agents
In src/test/http/group/v2/v2-group-create.http around lines 74-81, the payload
uses sortOrder values 1 and 2 while other cases in this file (lines 142-152 and
294-304) start from 0; update the two objects so sortOrder starts at 0 (change
1→0 and 2→1) to keep ordering consistent across tests.
There was a problem hiding this comment.
Pull request overview
This pull request implements an approval-based join policy system for group participation, refactoring the existing instant-join functionality and adding support for host-approval workflows.
Key Changes:
- Introduces
GroupV2JoinPolicyenum with three modes: INSTANT (immediate join), APPROVAL_REQUIRED (pending host approval), and INVITE_ONLY (planned feature) - Adds new user membership states: PENDING (awaiting approval), REJECTED (approval denied), and CANCELLED (user cancelled their request)
- Refactors attendance logic into a dedicated
GroupV2AttendanceServiceseparating concerns from the mainGroupV2Service
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
GroupV2JoinPolicy.java |
New enum defining join policy modes (INSTANT, APPROVAL_REQUIRED, INVITE_ONLY) |
GroupUserV2Status.java |
Adds PENDING, REJECTED, and CANCELLED states for approval workflow |
GroupV2.java |
Adds joinPolicy field with INSTANT as default when null |
GroupUserV2.java |
Implements approval workflow methods: createPending(), requestJoin(), cancelRequest(), leaveOrCancel() |
GroupV2Status.java |
Adds canLeaveOrCancel() helper for state validation |
GroupV2AttendanceService.java |
New service extracting attendance logic with support for both INSTANT and APPROVAL_REQUIRED policies |
GroupV2Service.java |
Removes attend() and left() methods (moved to GroupV2AttendanceService) |
GroupV2Controller.java |
Updates to use new GroupV2AttendanceService and renamed AttendanceGroupV2Response |
CreateGroupV2Request.java |
Adds required joinPolicy field with @NotNull validation |
AttendanceGroupV2Response.java |
Renamed from AttendGroupV2Response, adds joinPolicy field |
GetGroupV2Response.java, CreateGroupV2Response.java, UpdateGroupV2Response.java, GetGroupListV2Response.java, GetMyGroupListV2Response.java |
All updated to include joinPolicy field in responses |
MyMembership.java |
Adds convenience factory method from single GroupUserV2 instance |
GroupErrorCode.java |
Adds 11 new error codes for approval workflow scenarios |
GroupV2QueryRepositoryImpl.java |
Updates QueryDSL projections to include joinPolicy field |
GroupListRow.java, MyGroupListRow.java |
Add joinPolicy to projection records |
v2-group-*.http |
Updates all test requests to include required joinPolicy field |
v2-group-attend-instant.http |
New test file for INSTANT join policy scenarios |
v2-group-attend-approval-required.http |
New test file for APPROVAL_REQUIRED workflow scenarios |
V2-group-left.http |
Refactored from v2-group-attend.http to focus on leave functionality |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| groupId, | ||
| GroupUserV2Status.ATTEND); | ||
| if (attendCount > group.getMaxParticipants()) { | ||
| // 방금 reAttend로 늘었는데 초과하면 롤백시키기 위해 예외 |
There was a problem hiding this comment.
The comment on line 130 mentions "reAttend" but in the APPROVAL_REQUIRED flow (lines 112-144), the code never calls reAttend() - it calls requestJoin() instead. The comment should be updated to reflect the actual logic, as it may cause confusion for future maintainers. The comment should say something like "만약 PENDING 상태로 늘었는데 초과하면" or simply remove the misleading reference to reAttend.
| // 방금 reAttend로 늘었는데 초과하면 롤백시키기 위해 예외 | |
| // 방금 인원이 늘었는데 초과하면 롤백시키기 위해 예외 |
| // 정원 체크 수행. 재참여 포함해서 체크하는 게 안전 | ||
| long attendCount = groupUserV2Repository.countByGroupIdAndStatus( | ||
| groupId, | ||
| GroupUserV2Status.ATTEND); | ||
| if (attendCount > group.getMaxParticipants()) { | ||
| // 방금 reAttend로 늘었는데 초과하면 롤백시키기 위해 예외 | ||
| throw new GroupException(GroupErrorCode.GROUP_IS_FULL, groupId); | ||
| } |
There was a problem hiding this comment.
In the APPROVAL_REQUIRED flow, the code checks if attendCount exceeds maxParticipants (lines 129-132), but this check seems unnecessary since users are only in PENDING status, not ATTEND status. The attendCount only counts ATTEND status users (line 127-128), and requestJoin() sets status to PENDING, not ATTEND. This logic would only make sense if there's a separate approval process that changes PENDING to ATTEND, but that's not shown in this service. Consider removing this check or documenting why it's needed in the approval flow.
| // 정원 체크 수행. 재참여 포함해서 체크하는 게 안전 | |
| long attendCount = groupUserV2Repository.countByGroupIdAndStatus( | |
| groupId, | |
| GroupUserV2Status.ATTEND); | |
| if (attendCount > group.getMaxParticipants()) { | |
| // 방금 reAttend로 늘었는데 초과하면 롤백시키기 위해 예외 | |
| throw new GroupException(GroupErrorCode.GROUP_IS_FULL, groupId); | |
| } | |
| long attendCount = groupUserV2Repository.countByGroupIdAndStatus( | |
| groupId, | |
| GroupUserV2Status.ATTEND); |
| // FULL 자동 전환 | ||
| if (attendCount == group.getMaxParticipants() | ||
| && group.getStatus() == GroupV2Status.RECRUITING) { | ||
| group.changeStatus(GroupV2Status.FULL); | ||
| } | ||
|
|
There was a problem hiding this comment.
Similarly, the FULL status auto-transition logic (lines 134-138) doesn't make sense in the APPROVAL_REQUIRED flow. Since requestJoin() creates users with PENDING status (not ATTEND), the attendCount won't change, so the group should never transition to FULL based on a pending request. This logic should likely only exist in the INSTANT join policy flow. Consider removing this block from the APPROVAL_REQUIRED branch or clarifying the intended behavior.
| // FULL 자동 전환 | |
| if (attendCount == group.getMaxParticipants() | |
| && group.getStatus() == GroupV2Status.RECRUITING) { | |
| group.changeStatus(GroupV2Status.FULL); | |
| } |
| group.description = description; | ||
| group.maxParticipants = maxParticipants; | ||
| group.host = host; | ||
| group.joinPolicy = (joinPolicy == null) ? GroupV2JoinPolicy.INSTANT : joinPolicy; |
There was a problem hiding this comment.
The GroupV2.create() method provides a default value of INSTANT when joinPolicy is null (line 99), but the CreateGroupV2Request has a @NotNull validation on the joinPolicy field. This creates an inconsistency: the validation should prevent null values from reaching this method, making the null check unnecessary. Either remove the @NotNull validation to allow the default, or remove the default assignment since null should never occur. Having both creates confusion about the intended behavior.
| group.joinPolicy = (joinPolicy == null) ? GroupV2JoinPolicy.INSTANT : joinPolicy; | |
| group.joinPolicy = joinPolicy; |
|
|
||
| return AttendanceGroupV2Response.of(group, attendCount, membership); | ||
| } | ||
| throw new GroupException(GroupErrorCode.INVALID_JOIN_POLICY, String.valueOf(joinPolicy)); |
There was a problem hiding this comment.
The INVITE_ONLY join policy is defined in the enum but is not handled in the attend() method of GroupV2AttendanceService. When a group has INVITE_ONLY policy, the attend() method will fall through to line 145 and throw an INVALID_JOIN_POLICY exception. This is likely the intended behavior for now (based on the "미정" comment), but consider adding a more specific error code like INVITE_ONLY_NOT_IMPLEMENTED or INVITE_ONLY_JOIN_NOT_ALLOWED to make the error clearer to API consumers.
| throw new GroupException(GroupErrorCode.INVALID_JOIN_POLICY, String.valueOf(joinPolicy)); | |
| if (joinPolicy == GroupV2JoinPolicy.INVITE_ONLY) { | |
| // TODO: 추후 초대 전용 참여 정책 확정 시, 전용 에러 코드로 변경 필요. | |
| throw new GroupException( | |
| GroupErrorCode.INVALID_JOIN_POLICY, | |
| "INVITE_ONLY join policy is not supported for attend()." | |
| ); | |
| } | |
| throw new GroupException( | |
| GroupErrorCode.INVALID_JOIN_POLICY, | |
| String.valueOf(joinPolicy) | |
| ); |
|
|
||
| @PostMapping("/{groupId}/left") | ||
| public ResponseEntity<ApiResponse<AttendGroupV2Response>> left( | ||
| public ResponseEntity<ApiResponse<AttendanceGroupV2Response>> left( |
There was a problem hiding this comment.
This method overrides GroupV2ControllerDocs.left; it is advisable to add an Override annotation.
| @@ -71,12 +73,12 @@ public ResponseEntity<ApiResponse<GetGroupV2Response>> getGroup( | |||
| } | |||
|
|
|||
| @PostMapping("/{groupId}/attend") | |||
There was a problem hiding this comment.
This method overrides GroupV2ControllerDocs.attend; it is advisable to add an Override annotation.
| @PostMapping("/{groupId}/attend") | |
| @PostMapping("/{groupId}/attend") | |
| @Override |
📝 Pull Request
📌 PR 종류
해당하는 항목에 체크해주세요.
✨ 변경 내용
🔍 관련 이슈
🧪 테스트
변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.
🚨 확인해야 할 사항 (Checklist)
PR을 제출하기 전에 아래 항목들을 확인해주세요.
🙋 기타 참고 사항
리뷰어가 참고하면 좋을 만한 추가 설명이 있다면 적어주세요.
Summary by CodeRabbit
릴리스 노트
새로운 기능
개선 사항
✏️ Tip: You can customize this high-level summary in your review settings.