Conversation
|
Caution Review failedThe pull request is closed. 요약Walkthrough이 PR은 V2 모임 생성 기능을 구현합니다. 요청/응답 DTO, 태그 및 이미지 처리를 포함한 서비스 로직, 새로운 API 엔드포인트, 그리고 동시 태그 생성을 위한 TagService 확장 기능을 추가합니다. Changes
Sequence DiagramsequenceDiagram
participant Client
participant Controller as GroupV2Controller
participant Service as GroupV2Service
participant UserRepo as UserRepository
participant TagService
participant GroupV2Repo as GroupV2Repository
participant Database
Client->>Controller: POST /api/v2/groups/create<br/>(CustomUserDetails, CreateGroupV2Request)
Controller->>Service: create(userDetails, request)
Service->>UserRepo: findById(hostUserId)
UserRepo->>Database: SELECT user
Database-->>UserRepo: User entity
UserRepo-->>Service: User
Service->>Service: createGroupV2Address()
Service->>Service: createGroupV2()
Service->>Service: createHostGroupUserV2(HOST)
Service->>TagService: findOrCreateAll(tagNames)
TagService->>Database: SELECT tags by name
Database-->>TagService: existing tags
TagService->>Database: INSERT new tags
alt Race Condition
Database-->>TagService: DataIntegrityViolationException
TagService->>Database: SELECT all tags by name (retry)
end
Database-->>TagService: all tags
TagService-->>Service: List<Tag>
Service->>Service: createGroupTagV2Entries()
Service->>Service: createGroupImageV2Entries()
Service->>GroupV2Repo: save(groupV2)
GroupV2Repo->>Database: INSERT group + relations
Database-->>GroupV2Repo: saved GroupV2
GroupV2Repo-->>Service: GroupV2
Service->>Service: CreateGroupV2Response.from(group, host)
Service-->>Controller: CreateGroupV2Response
Controller-->>Client: 201 Created<br/>ApiResponse<CreateGroupV2Response>
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 추가 검토 필요 부분:
Possibly related PRs
Poem
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro 📒 Files selected for processing (8)
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.
Pull request overview
This PR implements V2 group creation functionality and V1 tag creation with the ability to find or create tags. The implementation follows similar patterns to the V1 group creation but adapts them for the V2 entity structure.
Key Changes
- Implemented
TagService.findOrCreateAll()method to handle concurrent tag creation with proper transaction handling - Added V2 group creation endpoint at
/api/v2/groups/createwith associated request/response DTOs - Created comprehensive HTTP test file covering various scenarios including different image formats and validation cases
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
src/main/java/team/wego/wegobackend/tag/application/service/TagService.java |
Implements tag find-or-create logic with concurrency handling for duplicate tag names |
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java |
Adds V2 group creation service method that orchestrates group, host, tags, and images creation |
src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java |
Exposes POST endpoint for V2 group creation |
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.java |
Request DTO with validation constraints for group creation |
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupImageV2Request.java |
Request DTO for group image data |
src/main/java/team/wego/wegobackend/group/v2/application/dto/response/CreateGroupV2Response.java |
Response DTO returning created group details with images, tags, and membership info |
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.java |
Minor formatting update (added blank line) |
src/test/http/group/v2/group-v2-create.http |
Comprehensive HTTP test scenarios for V2 group creation with various image formats and edge cases |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
|
|
||
| ### 2-2. 모임 V2 생성 (WEBP 업로드 결과 URL로 생성) | ||
| POST http://localhost:8080/api/v1/groups/create |
There was a problem hiding this comment.
The endpoint URL is incorrect. The comment says this is a V2 group creation test, but the endpoint path uses '/api/v1/groups/create' instead of '/api/v2/groups/create'. This inconsistency means the test will call the wrong API version.
| import jakarta.validation.constraints.NotNull; | ||
| import java.time.LocalDateTime; | ||
| import java.util.List; | ||
| import team.wego.wegobackend.group.application.dto.v1.request.CreateGroupImageRequest; |
There was a problem hiding this comment.
Incorrect import. The import should be 'team.wego.wegobackend.group.v2.application.dto.request.CreateGroupImageV2Request' instead of 'team.wego.wegobackend.group.application.dto.v1.request.CreateGroupImageRequest'. This import refers to the V1 class instead of the V2 class that is defined elsewhere in this PR.
| @Transactional | ||
| public CreateGroupV2Response create(CustomUserDetails userDetails, | ||
| CreateGroupV2Request request) { | ||
|
|
||
| // 회원 조회 | ||
| User host = userRepository.findById(userDetails.getId()) | ||
| .orElseThrow(() -> new GroupException(GroupErrorCode.HOST_USER_NOT_FOUND, | ||
| userDetails.getId()) | ||
| ); | ||
|
|
||
| // 모임 주소 생성 | ||
| GroupV2Address address = GroupV2Address.of(request.location(), request.locationDetail()); | ||
|
|
||
| // 모임 생성 | ||
| GroupV2 group = GroupV2.create( | ||
| request.title(), | ||
| address, | ||
| request.startTime(), | ||
| request.endTime(), | ||
| request.description(), | ||
| request.maxParticipants(), | ||
| host | ||
| ); | ||
|
|
||
| // 모임 주최자 생성 | ||
| GroupUserV2.create(group, host, GroupUserV2Role.HOST); | ||
|
|
||
| // 태그 생성 또는 찾기 | ||
| if (request.tags() != null) { | ||
| List<Tag> tags = tagService.findOrCreateAll(request.tags()); | ||
| for (Tag tag : tags) { | ||
| GroupTagV2.create(group, tag); | ||
| } | ||
| } | ||
|
|
||
| // 이미지 생성 | ||
| if (request.images() != null) { | ||
| for (CreateGroupImageV2Request imageRequest : request.images()) { | ||
| GroupImageV2.create(group, imageRequest.sortOrder(), imageRequest.imageUrl440x240(), | ||
| imageRequest.imageUrl100x100()); | ||
| } | ||
| } | ||
|
|
||
| // 모임 저장 | ||
| GroupV2 saved = groupV2Repository.save(group); | ||
|
|
||
| return CreateGroupV2Response.from(saved, host); | ||
| } |
There was a problem hiding this comment.
Missing validation for endTime being after startTime. When endTime is not null, it should be validated that endTime is after startTime to prevent invalid time ranges. The V1 GroupService includes this validation in validateCreateGroupRequest at line 68, but V2 lacks this check.
| return existing; | ||
| } | ||
|
|
||
| // 동시 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리해야 한다. |
There was a problem hiding this comment.
Comment has a typo or unclear wording. The comment '동시 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리해야 한다' could be clearer. Consider rephrasing to '동시에 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리한다' for better clarity.
| < ../image/resources/img1.png | ||
| --boundary | ||
| Content-Disposition: form-data; name="images"; filename="img2.jpg" | ||
| Content-Type: image/jpeg | ||
|
|
||
| < ../image/resources/img2.jpg |
There was a problem hiding this comment.
Inconsistent file path reference. The path uses '../image/resources/img1.png' while the first test case uses '../../image/resources/' (with two '../'). Ensure file path consistency across all test cases or verify which path is correct based on the actual directory structure.
| User host = userRepository.findById(userDetails.getId()) | ||
| .orElseThrow(() -> new GroupException(GroupErrorCode.HOST_USER_NOT_FOUND, | ||
| userDetails.getId()) | ||
| ); | ||
|
|
||
| // 모임 주소 생성 | ||
| GroupV2Address address = GroupV2Address.of(request.location(), request.locationDetail()); | ||
|
|
||
| // 모임 생성 | ||
| GroupV2 group = GroupV2.create( | ||
| request.title(), | ||
| address, | ||
| request.startTime(), | ||
| request.endTime(), | ||
| request.description(), | ||
| request.maxParticipants(), | ||
| host | ||
| ); | ||
|
|
||
| // 모임 주최자 생성 | ||
| GroupUserV2.create(group, host, GroupUserV2Role.HOST); |
There was a problem hiding this comment.
Missing user counter updates. When a group is created, the host user's groupCreatedCount and groupJoinedCount should be incremented. The V1 GroupService includes these updates in the registerHost method (lines 117-118), but V2 is missing this functionality. This inconsistency will result in incorrect user statistics.
| < ../../image/resources/img1.png | ||
| --boundary | ||
| Content-Disposition: form-data; name="images"; filename="img2.jpg" | ||
| Content-Type: image/jpeg | ||
|
|
||
| < ../../image/resources/img2.jpg |
There was a problem hiding this comment.
Inconsistent file path reference. The path uses '../../image/resources/img1.png' while other image upload tests in the same file use '../image/resources/' (with one less '../'). This inconsistency could lead to file not found errors. Check lines 104, 109, 114, 178, 183, 238, 243, 248, 253, 266, 271, 276 for comparison.
| public record CreateGroupImageV2Request( | ||
| Integer sortOrder, | ||
| String imageUrl440x240, | ||
| String imageUrl100x100 | ||
| ) {} |
There was a problem hiding this comment.
Missing input validation. The record fields lack validation annotations. At minimum, sortOrder should have @NotNull and range validation, and image URLs should have @notblank validation to prevent null or empty values from being passed to the service layer where they would cause exceptions in GroupImageV2.create().
| if (request.images() != null) { | ||
| for (CreateGroupImageV2Request imageRequest : request.images()) { | ||
| GroupImageV2.create(group, imageRequest.sortOrder(), imageRequest.imageUrl440x240(), | ||
| imageRequest.imageUrl100x100()); | ||
| } | ||
| } |
There was a problem hiding this comment.
Missing validation for maximum number of images. The service should validate that the images list does not exceed 3 items, consistent with the V1 implementation in GroupImageService (line 76-78) which enforces this limit. Without this check, users could potentially create groups with more than 3 images, violating the business rule.
| @Max(value = 12, message = "모임: 최대 인원은 최대 12명 이하이어야 합니다.") | ||
| Integer maxParticipants, | ||
|
|
||
| List<CreateGroupImageV2Request> images |
There was a problem hiding this comment.
Missing validation for images list size. Consider adding @SiZe(max = 3, message = "모임: 모임 이미지는 최대 3개 입니다.") annotation to the images field to enforce the maximum limit at the request level, consistent with the validation performed in V1 GroupImageService.
📝 Pull Request
📌 PR 종류
해당하는 항목에 체크해주세요.
✨ 변경 내용
V2 모임을 생성과 V1 태그 생성을 구현합니다.
응답 필드가 수정되었습니다.
유저 이메일 조회 1 <- 뭐지?
유저 ID 조회 1
태그 조회 IN 1
모임 INSERT 1
태그 INSERT 3 (3개 다 없는 상태)
모임이미지 INSERT 1
모임이미지변형 INSERT 2
모임이미지 INSERT 1
모임이미지변형 INSERT 2
모임유저 INSERT 1
🔍 관련 이슈
🧪 테스트
변경된 기능에 대한 테스트 범위 또는 테스트 결과를 작성해주세요.
🚨 확인해야 할 사항 (Checklist)
PR을 제출하기 전에 아래 항목들을 확인해주세요.
🙋 기타 참고 사항
리뷰어가 참고하면 좋을 만한 추가 설명이 있다면 적어주세요.
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.