Skip to content

[FEAT] V2 모임 생성과 태그 생성 구현#127

Merged
LimdaeIl merged 7 commits intomainfrom
feat/group-v2-create
Dec 17, 2025
Merged

[FEAT] V2 모임 생성과 태그 생성 구현#127
LimdaeIl merged 7 commits intomainfrom
feat/group-v2-create

Conversation

@LimdaeIl
Copy link
Collaborator

@LimdaeIl LimdaeIl commented Dec 17, 2025

📝 Pull Request

📌 PR 종류

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

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

✨ 변경 내용

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

릴리스 노트

  • 새로운 기능
    • 그룹 생성 API 엔드포인트 추가 - 제목, 위치, 시간, 설명, 태그, 이미지 등 상세 정보 지원
    • 그룹 이미지 다중 포맷 및 다양한 크기 지원
    • 태그 자동 생성 및 관리 기능 추가
    • 그룹 참여자 수 제한 및 검증 기능 추가

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

@LimdaeIl LimdaeIl self-assigned this Dec 17, 2025
Copilot AI review requested due to automatic review settings December 17, 2025 14:00
@LimdaeIl LimdaeIl added the ✨enhancement New feature or request label Dec 17, 2025
@LimdaeIl LimdaeIl moved this from Backlog to In progress in WeGo-Together Backend Dec 17, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 17, 2025

Caution

Review failed

The pull request is closed.

요약

Walkthrough

이 PR은 V2 모임 생성 기능을 구현합니다. 요청/응답 DTO, 태그 및 이미지 처리를 포함한 서비스 로직, 새로운 API 엔드포인트, 그리고 동시 태그 생성을 위한 TagService 확장 기능을 추가합니다.

Changes

Cohort / File(s) 변경 요약
V2 그룹 DTO
src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupImageV2Request.java, src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.java, src/main/java/team/wego/wegobackend/group/v2/application/dto/response/CreateGroupV2Response.java
모임 생성 요청 및 응답을 위한 새 레코드 DTO 추가. CreateGroupImageV2Request는 이미지 정렬/URL 정보 포함. CreateGroupV2Request는 제목, 위치, 시간, 태그, 설명, 최대 참여자 수에 대한 유효성 검사 주석 포함. CreateGroupV2Response는 주소, 생성자, 멤버십, 이미지 변형 정보를 포함하는 중첩 레코드 포함.
서비스 계층
src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java, src/main/java/team/wego/wegobackend/tag/application/service/TagService.java
GroupV2Service에 새 create() 메서드 추가하여 모임 생성 처리, 주소/태그/이미지 생성 및 호스트 롤 설정 수행. TagService에 findOrCreateAll(List) 메서드 추가하여 동시성 충돌 시 태그 조회/생성 및 재시도 로직 처리.
컨트롤러
src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java
POST /api/v2/groups/create 엔드포인트 추가하여 인증된 사용자가 모임을 생성 요청할 수 있도록 구현.
기타
src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.java, src/test/http/group/v2/group-v2-create.http
GroupUserV2Status의 파일 끝 줄바꿈 추가. V2 모임 생성 워크플로우를 위한 종합적인 HTTP 테스트 시나리오 추가 (사용자 생성, 로그인, 이미지 업로드, 모임 생성 포함).

Sequence Diagram

sequenceDiagram
    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>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

추가 검토 필요 부분:

  • CreateGroupV2Response의 중첩 레코드 구조 및 변형 매핑 로직 검증
  • TagService.findOrCreateAll()의 동시성 처리 및 예외 재시도 로직 확인
  • GroupV2Service.create()에서 여러 엔티티 생성 순서 및 트랜잭션 일관성 검증
  • CreateGroupV2Request의 유효성 검사 주석 (FutureOrPresent, Future 등) 적절성 확인

Possibly related PRs

Poem

🐰 모임을 만드는 날, 태그가 춤을 추고
이미지는 여러 크기로 변신하며
API 엔드포인트는 새 길을 열어
데이터베이스에 기쁜 소식을 전하네! 🎉
함께 모일 수 있는 공간,
이제 완성되었도다! ✨

✨ 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/group-v2-create

📜 Recent 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 4b6d0d0 and a248d59.

📒 Files selected for processing (8)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupImageV2Request.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/request/CreateGroupV2Request.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/response/CreateGroupV2Response.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/service/GroupV2Service.java (2 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/presentation/GroupV2Controller.java (3 hunks)
  • src/main/java/team/wego/wegobackend/tag/application/service/TagService.java (2 hunks)
  • src/test/http/group/v2/group-v2-create.http (1 hunks)

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.

@LimdaeIl LimdaeIl merged commit c459a8c into main Dec 17, 2025
4 of 5 checks passed
@LimdaeIl LimdaeIl deleted the feat/group-v2-create branch December 17, 2025 14:00
@github-project-automation github-project-automation bot moved this from In progress to Done in WeGo-Together Backend Dec 17, 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 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/create with 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
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;
import team.wego.wegobackend.group.application.dto.v1.request.CreateGroupImageRequest;
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +104 to +151
@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);
}
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
return existing;
}

// 동시 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리해야 한다.
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

Comment has a typo or unclear wording. The comment '동시 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리해야 한다' could be clearer. Consider rephrasing to '동시에 다른 트랜잭션이 같은 태그를 먼저 생성하는 경우를 처리한다' for better clarity.

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +183
< ../image/resources/img1.png
--boundary
Content-Disposition: form-data; name="images"; filename="img2.jpg"
Content-Type: image/jpeg

< ../image/resources/img2.jpg
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +129
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);
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +43
< ../../image/resources/img1.png
--boundary
Content-Disposition: form-data; name="images"; filename="img2.jpg"
Content-Type: image/jpeg

< ../../image/resources/img2.jpg
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +7
public record CreateGroupImageV2Request(
Integer sortOrder,
String imageUrl440x240,
String imageUrl100x100
) {}
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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().

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +145
if (request.images() != null) {
for (CreateGroupImageV2Request imageRequest : request.images()) {
GroupImageV2.create(group, imageRequest.sortOrder(), imageRequest.imageUrl440x240(),
imageRequest.imageUrl100x100());
}
}
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
@Max(value = 12, message = "모임: 최대 인원은 최대 12명 이하이어야 합니다.")
Integer maxParticipants,

List<CreateGroupImageV2Request> images
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
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