Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f1e4a19
[refactor] alias, category, tag, feedTag jpa entity 삭제 (#257)
seongjunnoh Aug 19, 2025
3197a54
[refactor] 바뀐 jpa entity 구조에 맞춰 프로덕션 코드 수정 중 (#257)
seongjunnoh Aug 19, 2025
7a7d0d9
[refactor] 기존 테스트 코드 수정 중 (#257)
seongjunnoh Aug 19, 2025
c63ae6f
[feat] Tag 관련 일급 컬렉션 및 Converter 추가 (#257)
seongjunnoh Aug 19, 2025
74a4c89
[feat] EnumMappings final class 추가 (#257)
seongjunnoh Aug 19, 2025
55fa518
Merge remote-tracking branches 'origin' and 'origin/refactor/#251-del…
seongjunnoh Aug 19, 2025
9c1f5fa
[refactor] queryDto 코드 수정 (#257)
seongjunnoh Aug 19, 2025
6f6fcde
[refactor] 영속성 코드 수정 (#257)
seongjunnoh Aug 19, 2025
5ad40d8
[refactor] EnumMappings, TagList (#257)
seongjunnoh Aug 19, 2025
071a2f2
[refactor] service, 도메인 계층 코드 수정 (#257)
seongjunnoh Aug 19, 2025
ed9b292
[feat] error code 추가 (#257)
seongjunnoh Aug 19, 2025
e71d741
[refactor] 기존 테스트 코드 수정 (#257)
seongjunnoh Aug 19, 2025
a79cf0d
[refactor] nullable 수정 (#257)
buzz0331 Aug 20, 2025
8b43d03
[feat] 방 상세보기용 마감일 보여주는 RecruitingRoomFormatAfterTime 추가 (#249)
hd0rable Aug 19, 2025
b22f5d2
[feat] 최근검색어 스웨거 id hidden추가 (#261)
hd0rable Aug 19, 2025
d25cbf9
[refactor] 에러코드 static import (#249)
hd0rable Aug 19, 2025
a3b65fb
[refactor] 방 상세보기 추천방 책 이미지 추가 (#249)
hd0rable Aug 19, 2025
0ebac90
[refactor] 방 상세보기 추천방 책 이미지 수정 (#249)
hd0rable Aug 19, 2025
2e4894e
[refactor] 모집마감한 방 방 상세보기 조회 안되도록 검증 (#249)
hd0rable Aug 19, 2025
48fe4f1
[refactor] 방 상세보기 조회 스웨거 에러코드 추가 (#249)
hd0rable Aug 19, 2025
fb3fc5b
[refactor] 오늘의 한마디 작성 스웨거 에러코드 추가 (#256)
hd0rable Aug 19, 2025
7a29871
[refactor] 오늘의 한마디 작성 response 수정 (#256)
hd0rable Aug 19, 2025
cc1deb6
[refactor] 오늘의 한마디 작성 response 수정 (#256)
hd0rable Aug 19, 2025
0bd171b
[refactor] 오늘의 한마디 작성 AttendanceCheckCommandPort.findById 작성 (#256)
hd0rable Aug 19, 2025
97619b4
[hotfix] 파라미터 위치 변경 (#256)
hd0rable Aug 19, 2025
4311688
[feat] 방 나가기 관련 에러코드 추가 (#265)
hd0rable Aug 20, 2025
3301f4f
[feat] 방 나가기 컨트롤러작성 (#265)
hd0rable Aug 20, 2025
4b3beed
[feat] 테스트용 RoomJpaEntity.updateRoomPercentage 추가 (#265)
hd0rable Aug 20, 2025
99321da
[feat] 방나가기 관련 도메인 검증 추가 (#265)
hd0rable Aug 20, 2025
631bf2a
[todo] 리펙관련 방 기록 삭제시 방 퍼센트 업데이트 todo 추가 (#265)
hd0rable Aug 20, 2025
6c778cf
[refactor] static import 추가 (#265)
hd0rable Aug 20, 2025
ae7ea84
[feat] 방 나가기 유즈케이스 RoomParticipantDeleteUseCase 작성(#265)
hd0rable Aug 20, 2025
cd4be85
[feat] 방 나가기 유즈케이스 RoomParticipantDeleteUseCase 구현체 RoomParticipantDe…
hd0rable Aug 20, 2025
e8f1278
[feat] 방 나가기 관련 방 진행도 업데이트 헬퍼 메서드RoomProgressManager.removeUserProgre…
hd0rable Aug 20, 2025
a0f1e81
[feat] 방 나가기 스웨거 에러코드 추가 (#265)
hd0rable Aug 20, 2025
7fae639
[feat] 방 나가기 통합 테스트코드 추가 (#265)
hd0rable Aug 20, 2025
3190f0a
[feat] 방 나가기 관련 도메인 단위테스트코드 추가 (#265)
seongjunnoh Aug 20, 2025
d1a091a
[refactor] 헬퍼 서비스에서 도메인 한번 더 조회말고 도메인 주입받아 상태변경하도록 수정 (#265)
hd0rable Aug 20, 2025
53cf9d3
[refactor] 방 나가기 api 통합 테스트 코드 바뀐 jpa 구조에 맞춰서 수정 (#257)
seongjunnoh Aug 20, 2025
ac32f64
[refactor] 다른 모집중인 추천방 조회 코드 수정 (#257)
seongjunnoh Aug 20, 2025
da67129
Merge remote-tracking branch 'origin' into refactor/#257-alias-catego…
seongjunnoh Aug 20, 2025
a78bed9
Merge remote-tracking branch 'origin' into refactor/#257-alias-catego…
seongjunnoh Aug 20, 2025
0ac1bd7
[fix] develop 브랜치에 바로 적용된 변경사항에 맞춰 테스트 코드 수정 (#257)
seongjunnoh Aug 20, 2025
6ec8adc
[fix] conflict 해결 (#257)
buzz0331 Aug 20, 2025
b161e7e
[fix] 에러 메시지 수정 (#257)
buzz0331 Aug 20, 2025
fc8c524
[fix] ContentList 책임 위임 (#257)
buzz0331 Aug 20, 2025
b9465bb
[rename] 값 객체 패키지 이동 (#257)
buzz0331 Aug 20, 2025
29413bc
[fix] 단위테스트코드 에러코드 수정 (#257)
hd0rable Aug 20, 2025
62150be
Merge remote-tracking branch 'origin/develop' into refactor/#257-alia…
hd0rable Aug 20, 2025
d91c598
[fix] 로그인한 유저 파라미터 추가 테스트코드 수정
hd0rable Aug 20, 2025
e89d772
Merge remote-tracking branch 'origin' into refactor/#257-alias-catego…
seongjunnoh Aug 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import konkuk.thip.comment.application.port.out.dto.CommentQueryDto;
import konkuk.thip.comment.application.port.out.dto.QCommentQueryDto;
import konkuk.thip.common.entity.StatusType;
import konkuk.thip.user.adapter.out.jpa.QAliasJpaEntity;
import konkuk.thip.user.adapter.out.jpa.QUserJpaEntity;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
Expand All @@ -24,7 +23,6 @@ public class CommentQueryRepositoryImpl implements CommentQueryRepository {

private final QCommentJpaEntity comment = QCommentJpaEntity.commentJpaEntity;
private final QUserJpaEntity commentCreator = QUserJpaEntity.userJpaEntity;
private final QAliasJpaEntity aliasOfCommentCreator = QAliasJpaEntity.aliasJpaEntity;
private final QCommentJpaEntity parentComment = new QCommentJpaEntity("parentComment");
private final QUserJpaEntity parentCommentCreator = new QUserJpaEntity("parentCommentCreator");

Expand All @@ -34,10 +32,8 @@ public List<CommentQueryDto> findRootCommentsWithDeletedByCreatedAtDesc(Long pos
QCommentQueryDto proj = new QCommentQueryDto(
comment.commentId,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.alias,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
Expand All @@ -58,7 +54,6 @@ public List<CommentQueryDto> findRootCommentsWithDeletedByCreatedAtDesc(Long pos
.select(proj)
.from(comment)
.leftJoin(comment.userJpaEntity, commentCreator)
.leftJoin(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(whereClause)
.orderBy(comment.createdAt.desc())
.limit(size + 1) // size + 1 개 조회
Expand All @@ -79,10 +74,8 @@ public List<CommentQueryDto> findAllActiveChildCommentsByCreatedAtAsc(Long rootC
comment.parent.commentId,
parentCommentCreator.nickname,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.alias,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
Expand All @@ -97,7 +90,6 @@ public List<CommentQueryDto> findAllActiveChildCommentsByCreatedAtAsc(Long rootC
.leftJoin(comment.parent, parentComment)
.leftJoin(parentComment.userJpaEntity, parentCommentCreator)
.leftJoin(comment.userJpaEntity, commentCreator)
.leftJoin(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.parent.commentId.in(parentIds), // parentIds 하위의 모든 자식 댓글 조회
comment.status.eq(StatusType.ACTIVE) // 자식 댓글은 ACTIVE인 것만 조회
Expand Down Expand Up @@ -141,10 +133,8 @@ public Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsByCreatedAtAsc
comment.parent.commentId,
parentCommentCreator.nickname,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.alias,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
Expand All @@ -159,7 +149,6 @@ public Map<Long, List<CommentQueryDto>> findAllActiveChildCommentsByCreatedAtAsc
.leftJoin(comment.parent, parentComment)
.leftJoin(parentComment.userJpaEntity, parentCommentCreator)
.leftJoin(comment.userJpaEntity, commentCreator)
.leftJoin(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.parent.commentId.in(parentIds), // parentIds 하위의 모든 자식 댓글 조회
comment.status.eq(StatusType.ACTIVE) // 자식 댓글은 ACTIVE인 것만 조회
Expand Down Expand Up @@ -193,10 +182,8 @@ public CommentQueryDto findRootCommentId(Long rootCommentId) {
QCommentQueryDto proj = new QCommentQueryDto(
comment.commentId,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.alias,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
Expand All @@ -207,7 +194,6 @@ public CommentQueryDto findRootCommentId(Long rootCommentId) {
.select(proj)
.from(comment)
.join(comment.userJpaEntity, commentCreator)
.join(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.commentId.eq(rootCommentId),
comment.status.eq(StatusType.ACTIVE)
Expand All @@ -223,10 +209,8 @@ public CommentQueryDto findChildCommentId(Long rootCommentId, Long replyCommentI
comment.parent.commentId,
parentCommentCreator.nickname,
commentCreator.userId,
aliasOfCommentCreator.imageUrl,
commentCreator.alias,
commentCreator.nickname,
aliasOfCommentCreator.value,
aliasOfCommentCreator.color,
comment.createdAt,
comment.content,
comment.likeCount,
Expand All @@ -239,7 +223,6 @@ public CommentQueryDto findChildCommentId(Long rootCommentId, Long replyCommentI
.join(comment.parent, parentComment)
.join(parentComment.userJpaEntity, parentCommentCreator)
.join(comment.userJpaEntity, commentCreator)
.join(commentCreator.aliasForUserJpaEntity, aliasOfCommentCreator)
.where(
comment.parent.commentId.eq(rootCommentId),
parentComment.status.eq(StatusType.ACTIVE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.querydsl.core.annotations.QueryProjection;
import jakarta.annotation.Nullable;
import konkuk.thip.user.domain.value.Alias;

import java.time.LocalDateTime;

Expand All @@ -23,7 +24,22 @@ public record CommentQueryDto(
* child comment
*/
@QueryProjection
public CommentQueryDto {}
public CommentQueryDto (
Long commentId,
Long parentCommentId,
String parentCommentCreatorNickname,
Long creatorId,
Alias creatorAlias,
String creatorNickname,
LocalDateTime createdAt, // 댓글 작성 시각
String content,
int likeCount,
Boolean isDeleted
) {
this(commentId, parentCommentId, parentCommentCreatorNickname, creatorId, creatorAlias.getImageUrl(),
creatorNickname, creatorAlias.getValue(), creatorAlias.getColor(),
createdAt, content, likeCount, isDeleted);
}

/**
* root comment
Expand All @@ -32,16 +48,15 @@ public record CommentQueryDto(
public CommentQueryDto (
Long commentId,
Long creatorId,
String creatorProfileImageUrl,
Alias creatorAlias,
String creatorNickname,
String alias,
String aliasColor,
LocalDateTime createdAt, // 댓글 작성 시각
String content,
int likeCount,
boolean isDeleted
) {
this(commentId, null, null, creatorId, creatorProfileImageUrl, creatorNickname,
alias, aliasColor, createdAt, content, likeCount, isDeleted);
this(commentId, null, null, creatorId, creatorAlias.getImageUrl(),
creatorNickname, creatorAlias.getValue(), creatorAlias.getColor(),
createdAt, content, likeCount, isDeleted);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,15 @@ public enum ErrorCode implements ResponseCode {
FEED_ALREADY_SAVED(HttpStatus.BAD_REQUEST, 160006, "사용자가 이미 저장한 피드입니다."),
FEED_NOT_SAVED_CANNOT_DELETE(HttpStatus.BAD_REQUEST, 160007, "사용자가 저장하지 않은 피드는 저장삭제 할 수 없습니다."),
FEED_CAN_NOT_SHOW_PRIVATE_ONE(HttpStatus.BAD_REQUEST, 160008, "비공개 피드는 피드 작성자 이외에는 조회할 수 없습니다."),
TAG_SHOULD_BE_UNIQUE(HttpStatus.BAD_REQUEST, 160009, "피드에 등록된 태그는 중복될 수 없습니다."),
TAG_LIST_SIZE_OVERFLOW(HttpStatus.BAD_REQUEST, 160010, "등록 가능한 태그 개수를 초과하였습니다."),


/**
* 165000: ContentList error
*/
CONTENT_LIST_SIZE_OVERFLOW(HttpStatus.BAD_REQUEST, 165000, "컨텐츠 리스트의 크기가 초과되었습니다. 최대 3개까지 가능합니다."),
CONTENT_NOT_FOUND(HttpStatus.BAD_REQUEST, 165001, "해당 이미지는 이 피드에 존재하지 않습니다:"),

/**
* 170000 : Image File error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ public enum SwaggerResponseDescription {
BOOK_NOT_FOUND,
TAG_NOT_FOUND,
TAG_NAME_NOT_MATCH,
INVALID_FEED_COMMAND,
CONTENT_LIST_SIZE_OVERFLOW,
TAG_SHOULD_BE_UNIQUE,
TAG_LIST_SIZE_OVERFLOW,
BOOK_NAVER_API_PARSING_ERROR,
BOOK_NAVER_API_ISBN_NOT_FOUND,
EMPTY_FILE_EXCEPTION,
Expand All @@ -193,7 +195,9 @@ public enum SwaggerResponseDescription {
BOOK_NOT_FOUND,
TAG_NOT_FOUND,
TAG_NAME_NOT_MATCH,
INVALID_FEED_COMMAND,
CONTENT_LIST_SIZE_OVERFLOW,
TAG_SHOULD_BE_UNIQUE,
TAG_LIST_SIZE_OVERFLOW,
FEED_ACCESS_FORBIDDEN
))),
CHANGE_FEED_SAVED_STATE(new LinkedHashSet<>(Set.of(
Expand Down
117 changes: 117 additions & 0 deletions src/main/java/konkuk/thip/common/util/EnumMappings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package konkuk.thip.common.util;

import konkuk.thip.feed.domain.value.Tag;
import konkuk.thip.room.domain.value.Category;
import konkuk.thip.user.domain.value.Alias;

import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

public final class EnumMappings {

private EnumMappings() {}

private static final Map<Alias, Category> aliasToCategory;
private static final Map<Category, List<Tag>> categoryToTags;

// 역방향 인덱스
private static final Map<Category, Alias> categoryToAlias;
private static final Map<Tag, Category> tagToCategory;

static {
// Alias -> Category
EnumMap<Alias, Category> a2c = new EnumMap<>(Alias.class);
a2c.put(Alias.WRITER, Category.LITERATURE); // 문학가
a2c.put(Alias.SCIENTIST, Category.SCIENCE_IT); // 과학자
a2c.put(Alias.SOCIOLOGIST, Category.SOCIAL_SCIENCE); // 사회학
a2c.put(Alias.ARTIST, Category.ART); // 예술가
a2c.put(Alias.PHILOSOPHER, Category.HUMANITY); // 철학자
aliasToCategory = Collections.unmodifiableMap(a2c);

// Category -> Tags
EnumMap<Category, List<Tag>> c2t = new EnumMap<>(Category.class);
c2t.put(Category.LITERATURE, List.of( // 문학
Tag.KOREAN_NOVEL, Tag.FOREIGN_NOVEL, Tag.CLASSIC_LITERATURE, Tag.ESSAY, Tag.POETRY,
Tag.PLAY, Tag.DETECTIVE_NOVEL, Tag.FANTASY_NOVEL, Tag.ROMANCE_NOVEL, Tag.LITERARY_THEORY
));
c2t.put(Category.SCIENCE_IT, List.of( // 과학·IT
Tag.GENERAL_SCIENCE, Tag.PHYSICS, Tag.CHEMISTRY, Tag.BIOLOGY, Tag.ASTRONOMY,
Tag.EARTH_SCIENCE, Tag.MATHEMATICS, Tag.GENERAL_ENGINEERING,
Tag.COMPUTER_ENGINEERING, Tag.PROGRAMMING, Tag.IT_GENERAL
));
c2t.put(Category.SOCIAL_SCIENCE, List.of( // 사회과학
Tag.SOCIOLOGY, Tag.LAW, Tag.GENERAL_POLITICS, Tag.POLITICAL_SCIENCE,
Tag.ECONOMICS, Tag.BUSINESS_ADMIN, Tag.JURISPRUDENCE, Tag.EDUCATION,
Tag.PSYCHOLOGY, Tag.MEDIA, Tag.INTERNATIONAL_RELATIONS, Tag.SOCIAL_ISSUES,
Tag.MARKETING, Tag.INVESTMENT, Tag.STARTUP, Tag.GENERAL_ECONOMY
));
c2t.put(Category.HUMANITY, List.of( // 인문학
Tag.PHILOSOPHY, Tag.HISTORY, Tag.RELIGION, Tag.CLASSICS, Tag.LINGUISTICS,
Tag.CULTURAL_ANTHROPOLOGY, Tag.HUMANISTIC_ESSAY, Tag.EASTERN_PHILOSOPHY,
Tag.WESTERN_PHILOSOPHY, Tag.WORLD_HISTORY, Tag.KOREAN_HISTORY,
Tag.HISTORICAL_ESSAY, Tag.ANCIENT_HISTORY, Tag.MODERN_HISTORY
));
c2t.put(Category.ART, List.of(
Tag.ART, Tag.MUSIC, Tag.MOVIE, Tag.PHOTO, Tag.DANCE,
Tag.THEATER, Tag.DESIGN, Tag.ARCHITECTURE, Tag.GENERAL_ART
));
Comment on lines +23 to +59
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

굿굿 확실히 이렇게 해두면 나중에 매핑 바꿔야 되는 요구사항이 들어올때 유연하게 대응 가능할 것 같네여

categoryToTags = Collections.unmodifiableMap(c2t);

// ------------역방향 인덱스------------
// Category -> Alias
EnumMap<Category, Alias> c2a = new EnumMap<>(Category.class);
aliasToCategory.forEach((alias, category) -> {
Alias prev = c2a.put(category, alias);
if (prev != null && prev != alias) {
throw new IllegalStateException("Category에 두 개 이상의 Alias 매핑: " + category);
}
});
categoryToAlias = Collections.unmodifiableMap(c2a);

// Tag -> Category (각 Tag는 정확히 하나의 Category)
EnumMap<Tag, Category> t2c = new EnumMap<>(Tag.class);
categoryToTags.forEach((category, tags) -> {
for (Tag tag : tags) {
Category prev = t2c.put(tag, category);
if (prev != null && prev != category) {
throw new IllegalStateException(
"Tag가 둘 이상의 Category에 매핑됨: " + tag + " (" + prev + " vs " + category + ")"
);
}
}
});
tagToCategory = Collections.unmodifiableMap(t2c);
}

// ----------- Public API -----------

/** Alias -> Category */
public static Category categoryFrom(Alias alias) {
return aliasToCategory.get(alias);
}

/** Category -> Tags */
public static List<Tag> tagsFrom(Category category) {
return categoryToTags.getOrDefault(category, List.of());
}

/** Category -> Alias */
public static Alias aliasFrom(Category category) {
return categoryToAlias.get(category);
}

/** Tag -> Category */
public static Category categoryFrom(Tag tag) {
return tagToCategory.get(tag);
}

public static Map<Category, List<Tag>> getCategoryToTags() {
return Collections.unmodifiableMap(categoryToTags);
}

public static Map<Alias, Category> getAliasToCategory() {
return Collections.unmodifiableMap(aliasToCategory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import jakarta.annotation.PostConstruct;
import konkuk.thip.common.exception.BusinessException;
import konkuk.thip.config.properties.AwsS3Properties;
import konkuk.thip.room.domain.Category;
import konkuk.thip.user.domain.Alias;
import konkuk.thip.room.domain.value.Category;
import konkuk.thip.user.domain.value.Alias;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

Expand Down
16 changes: 10 additions & 6 deletions src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import jakarta.persistence.*;
import konkuk.thip.book.adapter.out.jpa.BookJpaEntity;
import konkuk.thip.feed.adapter.out.jpa.converter.ContentListJsonConverter;
import konkuk.thip.feed.adapter.out.jpa.converter.TagListJsonConverter;
import konkuk.thip.feed.domain.Feed;
import konkuk.thip.feed.domain.value.TagList;
import konkuk.thip.feed.domain.value.ContentList;
import konkuk.thip.post.adapter.out.jpa.PostJpaEntity;
import konkuk.thip.user.adapter.out.jpa.UserJpaEntity;
Expand Down Expand Up @@ -36,24 +38,25 @@ public class FeedJpaEntity extends PostJpaEntity {

// JSON 문자열로 저장되는 단일 컬럼
@Convert(converter = ContentListJsonConverter.class)
@Column(name = "content_list", columnDefinition = "TEXT", nullable = false)
@Column(name = "content_list", columnDefinition = "TEXT")
private ContentList contentList = ContentList.empty();

// 삭제용 피드 저장 양방향 매핑 관계
@OneToMany(mappedBy = "feedJpaEntity", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<SavedFeedJpaEntity> savedFeeds = new ArrayList<>();

// 삭제용 피드 태그 양방향 매핑 관계
@OneToMany(mappedBy = "feedJpaEntity", cascade = CascadeType.REMOVE, orphanRemoval = true)
private List<FeedTagJpaEntity> feedTags = new ArrayList<>();
@Column(name = "tag_list", columnDefinition = "TEXT")
@Convert(converter = TagListJsonConverter.class)
private TagList tagList = TagList.empty();

@Builder
public FeedJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity, ContentList contentList) {
public FeedJpaEntity(String content, Integer likeCount, Integer commentCount, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity, ContentList contentList, TagList tagList) {
super(content, likeCount, commentCount, userJpaEntity);
this.isPublic = isPublic;
this.reportCount = reportCount;
this.bookJpaEntity = bookJpaEntity;
if(contentList != null) this.contentList = contentList;
this.contentList = contentList != null ? contentList : ContentList.empty();
this.tagList = tagList != null ? tagList : TagList.empty();
}

public void updateFrom(Feed feed) {
Expand All @@ -63,6 +66,7 @@ public void updateFrom(Feed feed) {
this.likeCount = feed.getLikeCount();
this.commentCount = feed.getCommentCount();
this.contentList = feed.getContentList();
this.tagList = feed.getTagList();
}
Comment on lines 68 to 70
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

updateFrom에서도 null-coalescing 적용 필요 (생성자와의 일관성 유지)

지금 상태에선 업데이트 경로로 null이 들어오면 엔티티 필드가 null로 저장될 수 있어, 생성자 경로(항상 empty 보장)와 의미가 엇갈립니다. 일관된 도메인 불변성을 위해 updateFrom에서도 empty로 코얼레싱하세요.

-        this.contentList = feed.getContentList();
-        this.tagList = feed.getTagList();
+        this.contentList = (feed.getContentList() != null) ? feed.getContentList() : ContentList.empty();
+        this.tagList = (feed.getTagList() != null) ? feed.getTagList() : TagList.empty();
📝 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.

Suggested change
this.contentList = feed.getContentList();
this.tagList = feed.getTagList();
}
this.contentList = (feed.getContentList() != null) ? feed.getContentList() : ContentList.empty();
this.tagList = (feed.getTagList() != null) ? feed.getTagList() : TagList.empty();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java around
lines 68 to 70, updateFrom assigns feed.getContentList() and feed.getTagList()
directly which allows nulls; change updateFrom to coalesce nulls to empty lists
(matching the constructor behavior) by replacing direct assignments with
null-safe assignments that set an empty list when feed.getContentList() or
feed.getTagList() is null.


@VisibleForTesting
Expand Down
Loading