Skip to content

Comments

[FEAT] 모임 V2 엔티티 재설계#125

Merged
LimdaeIl merged 4 commits intomainfrom
feat/group-v2-entity
Dec 17, 2025
Merged

[FEAT] 모임 V2 엔티티 재설계#125
LimdaeIl merged 4 commits intomainfrom
feat/group-v2-entity

Conversation

@LimdaeIl
Copy link
Collaborator

@LimdaeIl LimdaeIl commented Dec 17, 2025

📝 Pull Request

📌 PR 종류

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

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

✨ 변경 내용

모임 v2 엔티티 재설계와 예외 코드가 추가 되었습니다. 자세한 모임 v2에 대한 설계 구조는 별도로 정리하겠습니다.

🔍 관련 이슈

🧪 테스트

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

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

🚨 확인해야 할 사항 (Checklist)

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

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

🙋 기타 참고 사항

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

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 모임 이미지 최적화: 여러 크기의 이미지 지원 추가
    • 향상된 모임 상태 관리 및 상태 전환 로직 개선
    • 모임 멤버십 관리 강화 (역할 및 상태 추적)
    • 개선된 오류 메시지: 차단된 사용자 재참여 방지, 필수 항목 검증 강화

✏️ 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 13:05
@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 도메인 모델 전체를 재설계합니다. 14개의 새로운 엔티티/열거형을 추가하여 모임 상태 전이, 이미지 변형 관리, 사용자 멤버십 생명주기, 위치 검증을 지원합니다. 동시에 모임/이미지/위치/상태 검증을 위한 8개의 새로운 오류 코드를 추가합니다.

Changes

콘텐츠 / 파일 변경 요약
오류 코드 확장
GroupErrorCode.java
8개의 새로운 오류 상수 추가: GROUP_IMAGE_VARIANT_REQUIRED, GROUP_BANNED_USER, GROUP_IMAGE_MUST_440_240, GROUP_IMAGE_MUST_100_100, GROUP_NOT_NULL, LOCATION_REQUIRED, GROUP_STATUS_REQUIRED, GROUP_STATUS_TRANSFER_IMPOSSIBLE
V2 핵심 엔티티
GroupV2.java
모임의 JPA 엔티티, 상태 필드(RECRUITING, FULL, CLOSED, CANCELLED, FINISHED), 상태 전이 로직 및 관계 관리 메서드 정의
V2 주소 값 객체
GroupV2Address.java
위치 및 상세 위치를 포함하는 임베드 가능한 값 객체, location 필드 검증 적용
V2 모임 상태 열거형
GroupV2Status.java
5가지 상태 상수 및 canTransitionTo 상태 전이 검증 로직
V2 이미지 엔티티
GroupImageV2.java
정렬 순서가 고유한 이미지 저장소, 생성 팩토리 메서드 및 변형(variant) 관리
V2 이미지 변형 엔티티
GroupImageV2Variant.java
이미지 포맷 정보(URL, 타입, 포맷)을 포함하는 변형 엔티티 및 팩토리 메서드
V2 이미지 변형 타입 열거형
GroupImageV2VariantType.java
CARD_440_240, THUMBNAIL_100_100 상수와 너비/높이/기본 포맷 접근자
V2 사용자 멤버십 엔티티
GroupUserV2.java
모임 참가자의 역할, 상태, 참가/퇴장 시간을 관리하며, reAttend/leave/kick/ban 생명주기 메서드 제공
V2 사용자 역할 열거형
GroupUserV2Role.java
HOST, MANAGER, MEMBER 3개의 역할 상수
V2 사용자 상태 열거형
GroupUserV2Status.java
ATTEND, LEFT, KICKED, BANNED 4개의 멤버십 상태 상수
V2 모임 태그 엔티티
GroupTagV2.java
GroupV2와 Tag의 연관성을 나타내는 조인 엔티티
V2 이미지 포맷 열거형
ImageV2Format.java
PNG, JPEG, WEBP 3개의 이미지 포맷 상수
저장소 업데이트
GroupV2Repository.java
제네릭 타입을 Group에서 GroupV2로 변경
DTO 마이너 변경
GetGroupListV2Response.java,
GetGroupV2Response.java
파일 끝에 줄바꿈 추가

예상 코드 리뷰 노력

🎯 4 (복잡함) | ⏱️ ~45분

다음 부분들에 특별한 주의가 필요합니다:

  • GroupV2.java의 상태 전이 로직: canTransitionTo 메서드와 changeStatus 메서드의 상태 검증 규칙이 이슈 #124의 요구사항과 정확히 일치하는지 확인 필요
  • 양방향 관계 관리: GroupImageV2, GroupUserV2, GroupTagV2의 assignTo/unassign 메서드와 Group의 addImage/removeImage 등의 메서드에서 관계가 올바르게 유지되는지 검증
  • 팩토리 메서드 검증: GroupImageV2.create()와 GroupV2Address.of()의 null/blank 검증이 모든 필수 필드를 충분히 검사하는지 확인
  • 데이터베이스 제약: GroupImageV2의 (group_id, sort_order) 고유 제약과 GroupImageV2Variant의 (group_image_id, variant_type) 고유 제약이 올바르게 설정되었는지 확인
  • CASCADE 및 ORPHAN_REMOVAL: OneToMany 관계에서 cascade=ALL과 orphanRemoval=true 설정이 의도한 대로 작동하는지 검토

관련된 PR들

🐰 새로운 모임이 탄생했네요, 우리 함께!
상태는 아름답게, 이미지는 정렬하고,
사용자들은 참석하고 떠나고, 금지되고...
복잡한 관계도 밝고 명확하게!
V2의 세계로, 확장성과 함께! 🚀

✨ 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-entity

📜 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 b51feab and 8f0db16.

📒 Files selected for processing (15)
  • src/main/java/team/wego/wegobackend/group/domain/exception/GroupErrorCode.java (2 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupListV2Response.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/application/dto/response/GetGroupV2Response.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupImageV2.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupImageV2Variant.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupImageV2VariantType.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupTagV2.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Role.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupUserV2Status.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2Address.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/GroupV2Status.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/entity/ImageV2Format.java (1 hunks)
  • src/main/java/team/wego/wegobackend/group/v2/domain/repository/GroupV2Repository.java (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 4b6d0d0 into main Dec 17, 2025
4 of 5 checks passed
@LimdaeIl LimdaeIl deleted the feat/group-v2-entity branch December 17, 2025 13:05
@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 introduces a redesigned V2 version of the Group entity domain model, adding new entities and supporting classes for an improved group management system with enhanced image handling, user role management, and status transitions.

Key Changes:

  • New entity model with GroupV2 as the aggregate root managing relationships with users, images, and tags
  • State machine implementation for group status transitions (RECRUITING → FULL/CLOSED/CANCELLED/FINISHED)
  • Image variant support with multiple sizes and formats (CARD_440_240, THUMBNAIL_100_100) for optimized display

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
GroupV2Repository.java Updated repository to reference new GroupV2 entity instead of legacy Group entity
ImageV2Format.java New enum defining supported image formats (PNG, JPEG, WEBP)
GroupV2Status.java New enum with state machine logic for group lifecycle status transitions
GroupV2Address.java New embeddable value object for location information with validation
GroupV2.java Core aggregate root entity with bidirectional relationships and status management
GroupUserV2Status.java New enum for user participation states (ATTEND, LEFT, KICKED, BANNED)
GroupUserV2Role.java New enum defining user roles (HOST, MANAGER, MEMBER)
GroupUserV2.java Join entity managing group-user relationships with role and status
GroupTagV2.java Join entity for group-tag associations
GroupImageV2VariantType.java Enum defining image variant types with dimensions and default formats
GroupImageV2Variant.java Entity storing different size/format variants of group images
GroupImageV2.java Entity managing group images with sort order and multiple variants
GetGroupV2Response.java Minor formatting fix (trailing newline added)
GetGroupListV2Response.java Minor formatting fix (trailing newline added)
GroupErrorCode.java Added 8 new error codes for V2 validation scenarios

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

Comment on lines +52 to +56
private GroupImageV2(GroupV2 group, int sortOrder) {
this.sortOrder = sortOrder;
assignTo(group);
group.addImage(this);
}
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 constructor creates a circular bidirectional call pattern. It calls assignTo(group) which sets this.group, and then immediately calls group.addImage(this), which in turn calls assignTo again on the same image. This results in the image being added to the group's images list during construction. While this works, it's unconventional and can cause issues if someone later calls GroupImageV2.create() followed by group.addImage() manually, resulting in duplicate entries. Consider refactoring to either handle the bidirectional relationship in one place or document this behavior clearly.

Copilot uses AI. Check for mistakes.
Comment on lines +130 to +131
this.images.remove(image);
image.unassign();
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 removeImage method could fail silently if the image is not in the list. The List.remove() method will return false if the item doesn't exist, but this is not checked. Additionally, calling unassign() on an image that wasn't in the list will still set its group to null. Consider checking if the image exists in the list before calling unassign(), or returning a boolean to indicate success.

Suggested change
this.images.remove(image);
image.unassign();
if (this.images.remove(image)) {
image.unassign();
}

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +25
public boolean canTransitionTo(GroupV2Status status) {
return allowedNext(this).contains(status);
}

private static Set<GroupV2Status> allowedNext(GroupV2Status current) {
return switch (current) {
case RECRUITING -> EnumSet.of(FULL, CLOSED, CANCELLED, FINISHED);
case FULL -> EnumSet.of(RECRUITING, CLOSED, CANCELLED, FINISHED);
case CLOSED -> EnumSet.of(CANCELLED, FINISHED);
case CANCELLED, FINISHED -> EnumSet.noneOf(GroupV2Status.class);
};
}
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 canTransitionTo method and the state transition logic are not documented. The allowed state transitions are business-critical and non-obvious (for example, why CLOSED can transition to CANCELLED but CANCELLED cannot transition to anything). Add Javadoc comments explaining the state machine, the purpose of each transition, and why certain transitions are not allowed.

Copilot uses AI. Check for mistakes.
Comment on lines +144 to +147
public void addTag(GroupTagV2 groupTag) {
this.groupTags.add(groupTag);
groupTag.assignTo(this);
}
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 addTag method has the same circular dependency issue as addImage and addUser. The method calls groupTag.assignTo(this), but in GroupTagV2.create(), it already calls group.addTag(groupTag) after creating the instance. This can lead to duplicate additions in the groupTags list. Consider refactoring to avoid the bidirectional method calls or add a check to prevent duplicate additions.

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +74
public static GroupImageV2Variant create(
GroupImageV2VariantType type,
String imageUrl) {
return new GroupImageV2Variant(type, imageUrl, type.defaultFormat());
}

public static GroupImageV2Variant create(
GroupImageV2VariantType type,
String imageUrl,
ImageV2Format format) {
return new GroupImageV2Variant(type, imageUrl, format);
}
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 create methods don't validate the imageUrl parameter. Null or blank URLs are not checked, which could violate the @column(nullable = false) constraint and cause database errors. Add validation to ensure imageUrl is not null or blank before creating the variant.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +21
@Table(name = "v2_group_tags")
@Entity
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 GroupTagV2 entity is missing a unique constraint on the combination of group_id and tag_id. Without this constraint, the same tag could be added to a group multiple times, creating duplicate entries. Add a unique constraint similar to the one in GroupUserV2 and GroupImageV2 to prevent duplicate group-tag associations.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +6
import lombok.AccessLevel;
import lombok.Getter;

@Getter(AccessLevel.PUBLIC)
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 annotation @Getter(AccessLevel.PUBLIC) on an enum is unnecessary. Enum constants are inherently public and accessible. Since enum values don't have fields requiring getters, this annotation serves no purpose and should be removed.

Suggested change
import lombok.AccessLevel;
import lombok.Getter;
@Getter(AccessLevel.PUBLIC)

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +27

public int width() {
return width;
}

public int height() {
return height;
}

public ImageV2Format defaultFormat() {
return defaultFormat;
}
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 methods width(), height(), and defaultFormat() are redundant as Lombok's @Getter annotation already generates getWidth(), getHeight(), and getDefaultFormat() methods. These duplicate methods add unnecessary code without providing additional value. Remove these methods and rely on the Lombok-generated getters.

Suggested change
public int width() {
return width;
}
public int height() {
return height;
}
public ImageV2Format defaultFormat() {
return defaultFormat;
}

Copilot uses AI. Check for mistakes.
changeStatus(GroupV2Status.FINISHED);
}

public void addImage(GroupImageV2 image) {
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 addImage method can lead to duplicate additions and potential infinite recursion. The method calls image.assignTo(this), but in GroupImageV2.create(), it already calls group.addImage(this) after assignTo(group). This creates a circular dependency where addImage→assignTo is called, and then create→assignTo→addImage is called. Consider refactoring to avoid the bidirectional method calls or add a check to prevent duplicate additions.

Suggested change
public void addImage(GroupImageV2 image) {
public void addImage(GroupImageV2 image) {
if (this.images.contains(image)) {
return;
}

Copilot uses AI. Check for mistakes.
Comment on lines +134 to +137
public void addUser(GroupUserV2 groupUser) {
this.users.add(groupUser);
groupUser.assignTo(this);
}
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 addUser method has the same circular dependency issue as addImage. The method calls groupUser.assignTo(this), but in GroupUserV2.create(), it already calls group.addUser(groupUser) after creating the instance. This can lead to duplicate additions in the users list and potential inconsistencies. Consider refactoring to avoid the bidirectional method calls or add a check to prevent duplicate additions.

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