Skip to content

[chore] 도메인 엔티티 및 mapper 추가#23

Merged
seongjunnoh merged 27 commits into
developfrom
chore/20-add-domain-entity-mapper
Jun 24, 2025
Merged

[chore] 도메인 엔티티 및 mapper 추가#23
seongjunnoh merged 27 commits into
developfrom
chore/20-add-domain-entity-mapper

Conversation

@seongjunnoh

@seongjunnoh seongjunnoh commented Jun 23, 2025

Copy link
Copy Markdown
Collaborator

#️⃣ 연관된 이슈

closes #20

📝 작업 내용

모든 jpa entity (PostJpaEntity 제외) 와 1대1로 대응되는 도메인 엔티티 및 mapper 클래스들을 추가하였습니다

  • 모든 도메인 엔티티들이 가지는 속성값들을 포함하는 BaseDomainEntity 를 정의하고, 모든 도메인 엔티티들이 BaseDomainEntity를 상속받도록 수정하였습니다
  • mapper 에서 도메인 엔티티 객체를 생성하면서 BaseDomainEntity의 속성값들도 초기화할 수 있도록 @SuperBuilder 를 도입하였습니다
    (ref : https://velog.io/@dmsqo1403/SuperBuilder-%EB%9E%80)
  • PostJpaEntity + {FeedJpaEntity, RecordJpaEntity, VoteJpaEntity} <-> {Feed, Record, Vote} 로 매핑되도록 도메인 엔티티와 mapper 클래스를 구현하였습니다
  • 도메인 엔티티를 최대한 외부 의존성 없이 순수하게 유지하기 위해, jpa 엔티티의 enum 타입의 attribute 들을 모두 String 타입으로 정의하였습니다

📸 스크린샷

💬 리뷰 요구사항

📌 PR 진행 시 이러한 점들을 참고해 주세요

* P1 : 꼭 반영해 주세요 (Request Changes) - 이슈가 발생하거나 취약점이 발견되는 케이스 등
* P2 : 반영을 적극적으로 고려해 주시면 좋을 것 같아요 (Comment)
* P3 : 이런 방법도 있을 것 같아요~ 등의 사소한 의견입니다 (Chore)

Summary by CodeRabbit

Summary by CodeRabbit

  • 신규 기능

    • 다양한 도메인 엔티티(책, 카테고리, 댓글, 댓글 좋아요, 피드, 태그, 콘텐츠, 투표, 투표 항목, 방, 게시글 좋아요, 기록, 사용자, 알리아스, 출석 체크, 팔로잉, 알림, 최근 검색, 저장된 책 및 피드, 사용자 방, 사용자 투표 등)와 매퍼 클래스가 대거 추가되었습니다.
    • 각 엔티티에 생성일, 수정일, 상태 등 공통 필드가 포함된 공통 베이스 엔티티 상속 구조와 Lombok의 상속 지원 빌더 패턴이 적용되었습니다.
    • 도메인과 JPA 엔티티 간 변환을 위한 매핑 기능이 추가되어 데이터 변환 및 관리가 용이해졌습니다.
    • 방(Room)과 관련하여 카테고리 정보가 연동되도록 기능이 확장되었습니다.
    • 일부 JPA 엔티티 생성자 및 필드가 개선되어 명확성과 유연성이 향상되었습니다.
  • 버그 수정

    • 일부 필드명 및 타입이 일관성 있게 정정되었습니다(예: 상태 타입 변경, 필드명 camelCase 표준화 등).
  • 리팩터링

    • 기존 엔티티들이 공통 베이스 엔티티를 상속하는 구조로 개선되어 코드 일관성과 재사용성이 향상되었습니다.
    • 일부 JPA 엔티티의 생성자 및 필드 구조가 개선되었습니다.

@seongjunnoh seongjunnoh linked an issue Jun 23, 2025 that may be closed by this pull request
2 tasks
@coderabbitai

coderabbitai Bot commented Jun 23, 2025

Copy link
Copy Markdown

"""

Walkthrough

도메인 엔티티와 매퍼 클래스가 대거 추가 및 리팩토링되었습니다. 각 도메인별로 엔티티 클래스가 신설되거나 필드가 명시적으로 선언되었고, JPA 엔티티와 도메인 엔티티 간 변환을 수행하는 매퍼 클래스가 도입되었습니다. 일부 기존 엔티티 및 매퍼에도 변환 메서드가 추가되었습니다.

Changes

파일/경로 그룹 변경 요약
.../book/domain/Book.java
.../comment/domain/Comment.java
.../feed/domain/Feed.java
.../room/domain/Room.java
.../user/domain/User.java
기존 도메인 엔티티에 BaseDomainEntity 상속, @SuperBuilder 적용, 필드 명시적 선언 등 리팩토링
.../book/domain/Category.java
.../comment/domain/CommentLike.java
.../feed/domain/Tag.java
.../room/domain/Content.java
.../room/domain/PostLike.java
.../room/domain/Record.java
.../room/domain/Vote.java
.../room/domain/VoteItem.java
.../user/domain/Alias.java
.../user/domain/AttendanceCheck.java
.../user/domain/Following.java
.../user/domain/Notification.java
.../user/domain/RecentSearch.java
.../user/domain/SavedBook.java
.../user/domain/SavedFeed.java
.../user/domain/UserRoom.java
.../user/domain/UserVote.java
신규 도메인 엔티티 클래스 추가
.../common/entity/BaseDomainEntity.java BaseDomainEntity 클래스 신설, 생성/수정일 및 상태 필드 추가
.../common/entity/StatusType.java JpaEntityStatus → StatusType로 enum명 변경
.../common/entity/BaseJpaEntity.java status 필드 타입 및 기본값을 StatusType으로 변경
.../book/adapter/out/mapper/BookMapper.java
.../comment/adapter/out/mapper/CommentMapper.java
.../feed/adapter/out/mapper/FeedMapper.java
.../room/adapter/out/mapper/RoomMapper.java
.../user/adapter/out/mapper/UserMapper.java
기존 매퍼에 toJpaEntity, toDomainEntity 메서드 추가
.../book/adapter/out/mapper/CategoryMapper.java
.../comment/adapter/out/mapper/CommentLikeMapper.java
.../feed/adapter/out/mapper/TagMapper.java
.../room/adapter/out/mapper/ContentMapper.java
.../room/adapter/out/mapper/PostLikeMapper.java
.../room/adapter/out/mapper/RecordMapper.java
.../room/adapter/out/mapper/VoteItemMapper.java
.../room/adapter/out/mapper/VoteMapper.java
.../user/adapter/out/mapper/AliasMapper.java
.../user/adapter/out/mapper/AttendanceCheckMapper.java
.../user/adapter/out/mapper/FollowingMapper.java
.../user/adapter/out/mapper/NotificationMapper.java
.../user/adapter/out/mapper/RecentSearchMapper.java
.../user/adapter/out/mapper/SavedBookMapper.java
.../user/adapter/out/mapper/SavedFeedMapper.java
.../user/adapter/out/mapper/UserRoomMapper.java
.../user/adapter/out/mapper/UserVoteMapper.java
신규 매퍼 클래스 및 변환 메서드 대거 추가
.../feed/adapter/out/jpa/FeedJpaEntity.java postJpaEntity 필드 제거, reportCount 생성자 파라미터화
.../room/adapter/out/jpa/PostJpaEntity.java @AllArgsConstructor 제거
.../room/adapter/out/jpa/RecordJpaEntity.java 공백 라인 조정(기능 변화 없음)
.../user/adapter/out/jpa/FollowingJpaEntity.java following_id → followingId로 필드명 변경

Sequence Diagram(s)

sequenceDiagram
    participant Domain as Domain Entity
    participant Mapper as Mapper
    participant JPA as JPA Entity

    Domain->>Mapper: toJpaEntity(domain, [연관 JPA 엔티티])
    Mapper->>JPA: JPA 엔티티 생성 및 반환

    JPA->>Mapper: toDomainEntity(jpaEntity)
    Mapper->>Domain: 도메인 엔티티 생성 및 반환
Loading

Assessment against linked issues

Objective (이슈번호) Addressed Explanation
도메인 엔티티 추가 (#20)
매퍼 추가 (#20)

Assessment against linked issues: Out-of-scope changes

Code Change (파일 경로) Explanation
following_id → followingId로 필드명 변경 (src/main/java/konkuk/thip/user/adapter/out/jpa/FollowingJpaEntity.java) 도메인 엔티티/매퍼 추가와 직접적 관련 없으나, 네이밍 일관성 차원의 변경으로 보임. 다만, 본 이슈 범위에는 포함되지 않음.
FeedJpaEntity에서 postJpaEntity 필드 삭제 및 생성자 변경 (src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java) 매퍼/도메인 엔티티 추가와 무관한 기존 JPA 엔티티 구조 변경. 이슈 목적과 직접적 연관성은 불분명함.
@AllArgsConstructor 제거 (src/main/java/konkuk/thip/room/adapter/out/jpa/PostJpaEntity.java) 도메인 엔티티/매퍼 추가와 무관한 생성자 관련 변경. 이슈 목적과 직접적 연관성은 불분명함.

Suggested labels

🧸 현준

Suggested reviewers

  • hd0rable

Poem

🐇
새로 태어난 엔티티들,
매퍼들이 손을 잡고 춤을 춰요.
도메인과 JPA, 서로를 오가며
데이터의 다리를 놓았죠.
토끼는 기뻐 깡총깡총,
코드의 숲이 더 풍성해졌어요!
🌱✨
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

♻️ Duplicate comments (2)
src/main/java/konkuk/thip/user/adapter/out/mapper/SavedBookMapper.java (2)

12-17: SavedFeedMapper와 동일한 null 안전성 문제

SavedFeedMapper와 동일하게 null 체크가 없어서 NPE 위험이 있습니다.

입력 파라미터에 대한 null 검증을 추가해주세요:

public SavedBookJpaEntity toJpaEntity(UserJpaEntity userJpaEntity, BookJpaEntity bookJpaEntity) {
+    if (userJpaEntity == null || bookJpaEntity == null) {
+        throw new IllegalArgumentException("UserJpaEntity and BookJpaEntity cannot be null");
+    }
    return SavedBookJpaEntity.builder()
            .userJpaEntity(userJpaEntity)
            .bookJpaEntity(bookJpaEntity)
            .build();
}

19-28: 중첩 객체 접근 시 null 안전성 확보 필요

JPA 엔티티의 중첩 객체 접근에서 NPE 방지가 필요합니다.

public SavedBook toDomainEntity(SavedBookJpaEntity savedBookJpaEntity) {
+    if (savedBookJpaEntity == null) {
+        throw new IllegalArgumentException("SavedBookJpaEntity cannot be null");
+    }
    return SavedBook.builder()
            .id(savedBookJpaEntity.getSavedId())
-            .userId(savedBookJpaEntity.getUserJpaEntity().getUserId())
-            .bookId(savedBookJpaEntity.getBookJpaEntity().getBookId())
+            .userId(savedBookJpaEntity.getUserJpaEntity() != null ? 
+                   savedBookJpaEntity.getUserJpaEntity().getUserId() : null)
+            .bookId(savedBookJpaEntity.getBookJpaEntity() != null ? 
+                   savedBookJpaEntity.getBookJpaEntity().getBookId() : null)
            .createdAt(savedBookJpaEntity.getCreatedAt())
            .modifiedAt(savedBookJpaEntity.getModifiedAt())
            .status(savedBookJpaEntity.getStatus())
            .build();
}
🧹 Nitpick comments (19)
src/main/java/konkuk/thip/user/domain/SavedBook.java (1)

7-9: 동등성 비교를 위한 equals/hashCode 자동 생성 고려
도메인 엔티티 간 값 동등성 비교를 위해 Lombok의 @EqualsAndHashCode(callSuper = true)를 추가하여 상위 클래스 필드까지 포함한 equals/hashCode 메서드를 생성하는 것을 권장합니다.

src/main/java/konkuk/thip/room/domain/PostLike.java (2)

11-15: BaseDomainEntity 중복 id 선언 및 필드명 일관성 검토

  • BaseDomainEntity에 이미 id가 정의되어 있는지 확인하고, 중복 선언 시 제거하세요.
  • 도메인 모델 전반의 가독성을 위해 targetPostId 대신 postId로 간단히 명명하는 것을 고려해보세요.

7-9: 도메인 동등성 비교 메서드 자동 생성 고려
Lombok의 @EqualsAndHashCode(callSuper = true)를 추가하여 상위 클래스 필드까지 포함한 equals/hashCode를 생성하면, 도메인 간 비교 로직 구현 시 안전성이 높아집니다.

src/main/java/konkuk/thip/user/domain/UserVote.java (1)

7-9: 값 동등성 비교를 위한 equals/hashCode 추가 고려
Lombok @EqualsAndHashCode(callSuper = true)를 도입하면, 도메인 엔티티 간 비교 시 논리적 동등성 보장이 용이해집니다.

src/main/java/konkuk/thip/user/domain/Following.java (1)

7-9: 도메인 엔티티 동등성 비교 메서드 자동 생성 고려
Lombok @EqualsAndHashCode(callSuper = true)를 추가하여 equals/hashCode를 자동 생성하면, 도메인 로직에서 객체 비교가 간편해집니다.

src/main/java/konkuk/thip/room/domain/VoteItem.java (2)

11-17: BaseDomainEntity 중복 id 선언 및 count 기본값 검토

  • 상위 클래스에 id가 정의되어 있는지 확인하고, 중복 시 제거하세요.
  • count 필드 기본값이 0이어야 할 경우 Lombok @Builder.Default를 사용해 명시적으로 초기값을 설정하는 것을 고려해보세요.

7-9: 도메인 동등성 비교 메서드 자동 생성 고려
값 동등성 비교를 위해 Lombok @EqualsAndHashCode(callSuper = true)를 함께 사용하여 equals/hashCode를 자동 생성하는 것을 권장합니다.

src/main/java/konkuk/thip/user/domain/SavedFeed.java (1)

11-15: 필드 검증 및 문서화 추가를 고려해보세요.

데이터 무결성을 위해 필수 필드에 대한 검증 어노테이션과 클래스 및 필드에 대한 JavaDoc 문서화를 추가하는 것을 권장합니다.

+/**
+ * 사용자가 저장한 피드 정보를 나타내는 도메인 엔티티
+ */
 @Getter
 @SuperBuilder
 public class SavedFeed extends BaseDomainEntity {
 
+    @NotNull
     private Long id;
 
+    @NotNull
     private Long userId;
 
+    @NotNull
     private Long feedId;
 }
src/main/java/konkuk/thip/feed/domain/Tag.java (1)

11-17: 필드 검증 및 비즈니스 규칙 고려사항을 추가해보세요.

태그 시스템의 데이터 무결성을 위해 다음 사항들을 고려해보세요:

  • value 필드의 길이 제한 및 null 체크
  • targetPostId와 categoryId의 필수 여부 확인
+    @NotNull
     private Long id;
 
+    @NotBlank
+    @Size(max = 50)
     private String value;
 
+    @NotNull
     private Long targetPostId;
 
     private Long categoryId; // 선택적 카테고리 분류
src/main/java/konkuk/thip/room/domain/Content.java (1)

13-13: contentUrl 필드에 URL 형식 검증을 추가하는 것을 권장합니다.

콘텐츠 URL의 유효성을 보장하기 위해 URL 형식 검증과 길이 제한을 추가해보세요.

+import org.hibernate.validator.constraints.URL;

+    /**
+     * 콘텐츠 파일의 URL (이미지, 동영상 등)
+     */
+    @NotBlank
+    @URL
+    @Size(max = 2000)
     private String contentUrl;
src/main/java/konkuk/thip/user/domain/UserRoom.java (1)

15-15: userPercentage 필드의 유효성 검증을 고려해보세요.

userPercentage 필드가 0-100 범위를 벗어난 값을 가질 수 있습니다. 도메인 로직에서 유효성 검증이나 제약 조건을 추가하는 것을 권장합니다.

src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java (1)

28-28: 필수 매개변수에 대한 null 검증을 고려해보세요.

생성자의 isPublic, bookJpaEntity 매개변수들이 null이 될 수 없도록 검증하는 것을 권장합니다.

src/main/java/konkuk/thip/common/entity/BaseDomainEntity.java (1)

12-14: 불변성 보장을 위한 final 키워드 고려

도메인 엔티티의 불변성을 더욱 강화하려면 필드들을 final로 선언하는 것을 고려해볼 수 있습니다.

-    private LocalDateTime createdAt;
-    private LocalDateTime modifiedAt;
+    private final LocalDateTime createdAt;
+    private final LocalDateTime modifiedAt;
src/main/java/konkuk/thip/book/adapter/out/mapper/BookMapper.java (1)

23-38: 매핑 로직이 정확하고 완전합니다.

JPA 엔티티에서 도메인 엔티티로의 변환 로직이 모든 필드를 적절히 매핑하고 있으며, 감사 필드들도 올바르게 포함되어 있습니다.

동일하게 null 안전성 검증 추가를 권장합니다:

public Book toDomainEntity(BookJpaEntity bookJpaEntity) {
+   if (bookJpaEntity == null) {
+       return null;
+   }
    return Book.builder()
            // ... 기존 코드
src/main/java/konkuk/thip/user/adapter/out/mapper/AttendanceCheckMapper.java (1)

25-25: 필드명 일관성을 고려해보세요.

creatorId 필드명을 사용하고 있는데, 다른 매퍼들에서는 주로 userId를 사용합니다. 도메인 전체에서 일관된 명명 규칙을 유지하는 것이 좋겠습니다.

만약 의도적으로 역할을 구분하기 위해 creatorId를 사용한 것이라면, 다른 관련 매퍼들에서도 동일한 명명 규칙을 적용하는 것을 고려해주세요.

src/main/java/konkuk/thip/room/domain/Room.java (1)

13-31: 필드 선언과 캡슐화 개선 제안

모든 필드가 private으로 적절히 선언되었으나, 다음 사항들을 고려해보세요:

  1. password 필드가 Integer 타입인데, 보안상 String 타입이나 암호화된 형태가 더 적절할 수 있습니다.
  2. roomPercentage 필드명이 도메인 의미를 명확하게 표현하지 못합니다. progressPercentage 또는 completionRate 등이 더 명확할 수 있습니다.
-    private Integer password;
+    private String password; // 또는 암호화된 형태

-    private double roomPercentage;
+    private double progressPercentage; // 또는 completionRate
src/main/java/konkuk/thip/user/adapter/out/mapper/RecentSearchMapper.java (1)

1-31: 매퍼 클래스들의 일관성을 위한 공통 베이스 클래스 고려

모든 매퍼 클래스에서 동일한 null 체크 패턴이 반복됩니다. 공통 베이스 클래스나 유틸리티 메서드를 도입하여 코드 중복을 줄이는 것을 고려해보세요.

예시:

public abstract class BaseMapper {
    protected void validateNotNull(Object obj, String paramName) {
        if (obj == null) {
            throw new IllegalArgumentException(paramName + " cannot be null");
        }
    }
    
    protected <T> T safeGet(Supplier<T> supplier) {
        try {
            return supplier.get();
        } catch (NullPointerException e) {
            return null;
        }
    }
}
src/main/java/konkuk/thip/comment/domain/Comment.java (1)

11-21: 필드 선언의 final 키워드 고려해보세요

모든 필드가 명시적으로 선언되어 명확성이 향상되었습니다. 불변성을 보장하기 위해 필드에 final 키워드 추가를 고려해보세요.

-    private Long id;
-    private String content;
-    private int reportCount;
-    private Long targetPostId;
-    private Long creatorId;
-    private Long parentCommentId;
+    private final Long id;
+    private final String content;
+    private final int reportCount;
+    private final Long targetPostId;
+    private final Long creatorId;
+    private final Long parentCommentId;
src/main/java/konkuk/thip/book/domain/Book.java (1)

11-27: 필드 선언의 불변성 개선을 고려해보세요

모든 필드가 명시적으로 선언되어 명확성이 향상되었습니다. 도메인 엔티티의 불변성을 보장하기 위해 필드에 final 키워드 추가를 고려해보세요.

-    private Long id;
-    private String title;
-    private String isbn;
-    private String authorName;
-    private boolean bestSeller;
-    private String publisher;
-    private String imageUrl;
-    private Integer pageCount;
-    private String description;
+    private final Long id;
+    private final String title;
+    private final String isbn;
+    private final String authorName;
+    private final boolean bestSeller;
+    private final String publisher;
+    private final String imageUrl;
+    private final Integer pageCount;
+    private final String description;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e7e520 and 211739c.

📒 Files selected for processing (51)
  • src/main/java/konkuk/thip/book/adapter/out/mapper/BookMapper.java (1 hunks)
  • src/main/java/konkuk/thip/book/adapter/out/mapper/CategoryMapper.java (1 hunks)
  • src/main/java/konkuk/thip/book/domain/Book.java (1 hunks)
  • src/main/java/konkuk/thip/book/domain/Category.java (1 hunks)
  • src/main/java/konkuk/thip/comment/adapter/out/mapper/CommentLikeMapper.java (1 hunks)
  • src/main/java/konkuk/thip/comment/adapter/out/mapper/CommentMapper.java (1 hunks)
  • src/main/java/konkuk/thip/comment/domain/Comment.java (1 hunks)
  • src/main/java/konkuk/thip/comment/domain/CommentLike.java (1 hunks)
  • src/main/java/konkuk/thip/common/entity/BaseDomainEntity.java (1 hunks)
  • src/main/java/konkuk/thip/common/entity/BaseJpaEntity.java (1 hunks)
  • src/main/java/konkuk/thip/common/entity/StatusType.java (1 hunks)
  • src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java (1 hunks)
  • src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java (1 hunks)
  • src/main/java/konkuk/thip/feed/adapter/out/mapper/TagMapper.java (1 hunks)
  • src/main/java/konkuk/thip/feed/domain/Feed.java (1 hunks)
  • src/main/java/konkuk/thip/feed/domain/Tag.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/jpa/PostJpaEntity.java (0 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntity.java (2 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/ContentMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/PostLikeMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/RecordMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/VoteItemMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/adapter/out/mapper/VoteMapper.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/Content.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/PostLike.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/Record.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/Room.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/Vote.java (1 hunks)
  • src/main/java/konkuk/thip/room/domain/VoteItem.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/jpa/FollowingJpaEntity.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/AttendanceCheckMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/FollowingMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/NotificationMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/RecentSearchMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/SavedBookMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/SavedFeedMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/UserRoomMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/adapter/out/mapper/UserVoteMapper.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/Alias.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/AttendanceCheck.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/Following.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/Notification.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/RecentSearch.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/SavedBook.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/SavedFeed.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/User.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/UserRoom.java (1 hunks)
  • src/main/java/konkuk/thip/user/domain/UserVote.java (1 hunks)
💤 Files with no reviewable changes (1)
  • src/main/java/konkuk/thip/room/adapter/out/jpa/PostJpaEntity.java
🔇 Additional comments (58)
src/main/java/konkuk/thip/common/entity/StatusType.java (1)

3-5: enum 이름 변경이 적절합니다.

JpaEntityStatus에서 StatusType으로의 이름 변경이 합리적입니다. 도메인 엔티티와 JPA 엔티티 양쪽에서 공통으로 사용할 수 있는 더 일반적인 이름으로 개선되었습니다.

src/main/java/konkuk/thip/room/adapter/out/jpa/RecordJpaEntity.java (1)

13-13: 공백 조정 변경사항입니다.

로직에는 영향이 없는 코드 포맷팅 개선입니다.

Also applies to: 30-30

src/main/java/konkuk/thip/user/adapter/out/jpa/FollowingJpaEntity.java (1)

18-18: Java 네이밍 컨벤션에 맞는 개선입니다.

following_id에서 followingId로의 필드명 변경이 Java camelCase 규칙에 맞춰 개선되었습니다. 데이터베이스 컬럼 매핑은 @Column(name = "following_id")로 그대로 유지되어 적절합니다.

기존 코드에서 이 필드를 직접 참조하는 부분이 있는지 확인해주세요:

#!/bin/bash
# 기존 following_id 필드 참조 확인
rg -A 2 -B 2 "following_id" --type java
src/main/java/konkuk/thip/common/entity/BaseJpaEntity.java (1)

40-40: enum 타입 변경이 일관성 있게 적용되었습니다.

JpaEntityStatus에서 StatusType으로의 타입 변경과 기본값 설정이 적절하게 반영되었습니다. StatusType.java의 enum 이름 변경과 일관성 있는 변경사항입니다.

src/main/java/konkuk/thip/user/domain/Alias.java (1)

1-14: 도메인 엔티티 구조가 적절합니다.

BaseDomainEntity 상속과 @SuperBuilder 어노테이션 사용이 올바르게 구현되었습니다. 별칭을 표현하는 간단하고 명확한 도메인 모델 구조입니다.

src/main/java/konkuk/thip/user/domain/SavedBook.java (2)

1-6: 도메인 엔티티 구조 적절
@Getter@SuperBuilder를 활용해 불변성을 확보하고, 빌더 패턴으로 객체 생성을 명확하게 구성했습니다.


11-15: 다음으로 BaseDomainEntity 파일에서 id 필드 선언이 보호(protected)나 public으로 되어 있진 않은지 추가로 확인해 보겠습니다.

#!/bin/bash
set -e
FILE=src/main/java/konkuk/thip/common/entity/BaseDomainEntity.java
grep -n -E '(private|protected|public)\s+.*\s+id\b' "$FILE" || echo "명시적 id 필드 선언 없음"
src/main/java/konkuk/thip/room/domain/PostLike.java (1)

1-6: 클래스 정의 승인
@Getter, @SuperBuilder 사용으로 도메인 객체 표현이 깔끔하게 잘 구성되었습니다.

src/main/java/konkuk/thip/user/domain/UserVote.java (2)

1-6: 도메인 엔티티 정의 적절
@Getter@SuperBuilder 활용을 통해 도메인 객체 설계가 명확하고 일관성 있습니다.


11-15: BaseDomainEntity에 실제로 id 필드가 선언되어 있는지 추가로 확인해 봅시다. 다음 스크립트를 실행해 주세요:

#!/bin/bash
file="src/main/java/konkuk/thip/common/entity/BaseDomainEntity.java"
echo "=== Checking Long id declarations in $file ==="
grep -n 'Long .*id' "$file" || echo "No Long id declarations found"
echo "=== Checking @Id annotations in $file ==="
grep -n '@Id' "$file" || echo "No @Id annotations found"
src/main/java/konkuk/thip/user/domain/Following.java (2)

1-6: 도메인 엔티티 구조 적절
@Getter@SuperBuilder 사용으로 도메인 모델이 명확하고 확장 가능하게 설계되었습니다.


11-15: 다음 스크립트를 실행하여 Following 클래스의 상속 관계와 BaseDomainEntity에 이미 id가 선언되어 있는지 확인해 주세요.

#!/bin/bash
set -e

echo "== Following.java 클래스 정보 =="
grep -n "class Following" src/main/java/konkuk/thip/user/domain/Following.java || echo "Following.java 파일을 찾을 수 없습니다."
sed -n '1,20p' src/main/java/konkuk/thip/user/domain/Following.java || true

echo ""
echo "== BaseDomainEntity 위치 검색 =="
rg "class BaseDomainEntity" -n src || echo "BaseDomainEntity 클래스를 찾을 수 없습니다."

echo ""
file=$(rg "class BaseDomainEntity" -n src | head -n1 | cut -d: -f1)
if [ -f "$file" ]; then
  echo "== BaseDomainEntity 내용 (앞 200줄) =="
  sed -n '1,200p' "$file"
else
  echo "BaseDomainEntity 파일을 찾을 수 없습니다."
fi
src/main/java/konkuk/thip/room/domain/VoteItem.java (1)

1-6: 도메인 엔티티 선언 승인
@Getter@SuperBuilder 적용으로 도메인 객체 정의와 불변성 확보가 잘 이루어졌습니다.

src/main/java/konkuk/thip/user/domain/SavedFeed.java (1)

7-16: 도메인 엔티티 구조가 깔끔하게 구현되었습니다.

SavedFeed 클래스가 BaseDomainEntity를 상속하고 @SuperBuilder를 사용하여 일관성 있는 패턴을 따르고 있습니다. 사용자와 피드 간의 저장 관계를 명확하게 표현하고 있습니다.

src/main/java/konkuk/thip/book/domain/Category.java (1)

7-16: 카테고리 도메인 엔티티가 적절하게 설계되었습니다.

BaseDomainEntity 상속과 @SuperBuilder 사용으로 일관성 있는 패턴을 따르고 있으며, 필드 타입 선택도 적절합니다.

src/main/java/konkuk/thip/feed/domain/Tag.java (1)

7-18: 태그 도메인 엔티티가 체계적으로 구현되었습니다.

BaseDomainEntity 상속과 @SuperBuilder 패턴을 올바르게 사용하고 있으며, 포스트와 카테고리와의 관계를 명확하게 표현하고 있습니다.

src/main/java/konkuk/thip/user/domain/RecentSearch.java (1)

7-18: 최근 검색 도메인 엔티티가 잘 구조화되었습니다.

BaseDomainEntity 상속과 @SuperBuilder 패턴을 적절히 사용하고 있으며, 사용자의 검색 이력을 효과적으로 모델링하고 있습니다.

src/main/java/konkuk/thip/room/domain/Content.java (1)

7-16: 콘텐츠 도메인 엔티티가 명확하게 구현되었습니다.

BaseDomainEntity 상속과 @SuperBuilder 패턴을 올바르게 사용하고 있으며, 포스트와 연관된 콘텐츠를 효과적으로 모델링하고 있습니다.

src/main/java/konkuk/thip/comment/domain/CommentLike.java (1)

1-16: CommentLike 도메인 엔티티 구조 적절
@SuperBuilder@Getter를 활용해 빌더 및 접근자가 잘 생성되었으며, BaseDomainEntity 상속으로 공통 속성도 포함된 구조가 올바릅니다.

src/main/java/konkuk/thip/user/domain/AttendanceCheck.java (1)

1-18: AttendanceCheck 도메인 엔티티 구조 적절
@SuperBuilder@Getter 적용으로 빌더·접근자 생성, BaseDomainEntity 상속을 통해 공통 필드 일관성이 확보되었습니다.

src/main/java/konkuk/thip/room/domain/Record.java (1)

1-22: Record 도메인 엔티티 구조 적절
@SuperBuilder@Getter를 사용해 일관된 빌더 패턴과 접근자 메서드가 제공되며, BaseDomainEntity 상속으로 공통 속성이 통합되어 있습니다.

src/main/java/konkuk/thip/room/domain/Vote.java (1)

1-22: Vote 도메인 엔티티 구조 적절
@SuperBuilder@Getter를 통해 빌더 패턴과 접근자 메서드가 올바르게 생성되었고, BaseDomainEntity 상속으로 공통 속성도 포함되어 있습니다.

src/main/java/konkuk/thip/user/domain/Notification.java (1)

1-20: Notification 도메인 엔티티 구조 적절
@SuperBuilder@Getter 사용으로 빌더 및 접근자 생성, BaseDomainEntity 상속으로 공통 필드가 잘 포함되어 있습니다.

src/main/java/konkuk/thip/common/entity/BaseDomainEntity.java (1)

8-17: 잘 설계된 기반 클래스입니다.

공통 필드들을 적절하게 추상화하고 @SuperBuilder를 통해 상속 구조에서 빌더 패턴을 지원하는 설계가 우수합니다. 모든 도메인 엔티티의 일관성을 보장할 수 있는 좋은 접근입니다.

src/main/java/konkuk/thip/user/domain/User.java (2)

8-9: BaseDomainEntity 상속과 @SuperBuilder 적용이 훌륭합니다.

기존 코드를 BaseDomainEntity를 상속받도록 적절히 리팩토링하고 @SuperBuilder를 통해 상속 구조에서 빌더 패턴을 지원하는 변경이 우수합니다.


11-20: 명시적 필드 선언으로 가독성이 향상되었습니다.

필드들을 명시적으로 선언하여 도메인 모델의 구조를 명확하게 파악할 수 있게 된 점이 좋습니다.

src/main/java/konkuk/thip/user/adapter/out/mapper/AliasMapper.java (2)

10-14: toJpaEntity 메서드의 사용 용도를 확인해주세요.

현재 구현은 새로운 엔티티 생성에 적합하지만, 기존 엔티티 업데이트가 필요한 경우 id 필드가 누락될 수 있습니다. 이 메서드가 새로운 엔티티 생성 전용인지 확인해주세요.


16-24: 도메인 엔티티 매핑이 올바르게 구현되었습니다.

모든 필드가 적절히 매핑되고 있으며, BaseDomainEntity의 공통 필드들(createdAt, modifiedAt, status)도 올바르게 처리되고 있습니다.

src/main/java/konkuk/thip/feed/domain/Feed.java (2)

3-9: BaseDomainEntity 상속 구조가 올바르게 적용되었습니다.

공통 필드들을 기반 클래스로 분리하고 @SuperBuilder를 사용하여 상속 구조에서의 빌더 패턴을 적절히 지원하고 있습니다.


11-21: 필드 명시적 선언이 코드 가독성을 향상시켰습니다.

모든 필드가 명확히 선언되어 있어 도메인 엔티티의 구조를 쉽게 파악할 수 있습니다.

src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java (2)

12-19: UserJpaEntity 생성 로직이 올바르게 구현되었습니다.

UserRole.from() 메서드를 통한 역할 변환과 AliasJpaEntity를 별도 파라미터로 받는 설계가 적절합니다.


21-32: aliasForUserJpaEntity 필드 선언부와 매핑 어노테이션(@OnetoOne 등) 확인을 위해 아래 스크립트를 실행해주세요.

#!/bin/bash
# aliasForUserJpaEntity 선언 위치 및 어노테이션 확인
rg -n -C5 "aliasForUserJpaEntity"
src/main/java/konkuk/thip/feed/adapter/out/mapper/FeedMapper.java (2)

12-20: FeedJpaEntity 생성 로직이 올바르게 구현되었습니다.

필요한 연관 엔티티들을 파라미터로 받아 매핑하는 설계가 적절하며, reportCount가 명시적으로 설정되는 것도 좋습니다.


22-34: PostJpaEntity의 ID 매핑과 도메인 Feed 클래스의 id 타입을 확인하기 위해 아래 스크립트를 실행해주세요.

#!/bin/bash
# 1) PostJpaEntity 정의 및 매핑 확인
FILE_POST=$(rg -n "class PostJpaEntity" -n src/main/java | grep -v Test | cut -d: -f1 | head -n1)
echo "▶ PostJpaEntity 소스: $FILE_POST"
sed -n '1,200p' "$FILE_POST"
grep -n "@Id" "$FILE_POST"
grep -n "@ManyToOne" "$FILE_POST"
grep -n "private .*JpaEntity" "$FILE_POST"

# 2) 도메인 Feed 클래스의 id 타입 확인
FILE_FEED=$(rg -n "class Feed" -n src/main/java | grep "Feed.java" | cut -d: -f1 | head -n1)
echo "▶ 도메인 Feed 소스: $FILE_FEED"
sed -n '1,200p' "$FILE_FEED"
grep -n "private .*id" "$FILE_FEED"
src/main/java/konkuk/thip/room/adapter/out/mapper/VoteItemMapper.java (2)

11-17: VoteItemJpaEntity 생성 로직이 올바르게 구현되었습니다.

VoteJpaEntity를 별도 파라미터로 받아 의존성을 명확히 분리한 설계가 적절합니다.


19-29: 추가로 VoteItemJpaEntity 클래스의 voteJpaEntity 필드 선언 및 관계 어노테이션(nullable 여부 포함)을 확인하기 위해 다음 스크립트를 실행하겠습니다:

#!/bin/bash
# VoteItemJpaEntity 클래스 정의와 voteJpaEntity 필드 어노테이션 확인
rg -n "class VoteItemJpaEntity" -A10 src/main/java
rg -n "voteJpaEntity" -C3 src/main/java/konkuk/thip
src/main/java/konkuk/thip/room/adapter/out/mapper/PostLikeMapper.java (1)

1-29: 매퍼 구현이 일관되고 적절합니다.

PostLike 도메인 엔티티와 PostLikeJpaEntity 간의 변환 로직이 올바르게 구현되었습니다. 양방향 변환 메서드와 관련 엔티티 처리가 적절하게 구현되어 있습니다.

src/main/java/konkuk/thip/user/adapter/out/mapper/UserRoomMapper.java (2)

17-17: 열거형 변환 메서드 확인이 필요합니다.

UserRoomRole.from() 메서드가 올바르게 구현되어 있는지 확인해주세요. null 값 처리와 유효하지 않은 값에 대한 예외 처리가 적절히 되어 있는지 검증이 필요합니다.

#!/bin/bash
# UserRoomRole enum의 from() 메서드 구현 확인
rg -A 10 "public static.*from" --type java | grep -A 10 "UserRoomRole"

28-28: 아래 스크립트로 getType() 구현과 도메인 엔티티의 userRoomRole 필드 타입을 다시 확인해주세요.

#!/bin/bash
set -e

echo "1. UserRoomRole#getType() 구현 확인"
rg -n "getType" -A5 src/main/java/konkuk/thip/user/adapter/out/jpa/UserRoomRole.java

echo ""
echo "2. 도메인 엔티티 UserRoom 클래스 정의 확인"
rg -n "class UserRoom" -A10 src/main/java/konkuk/thip/user/domain

echo ""
echo "3. UserRoom의 userRoomRole 필드 타입 확인"
rg -n "userRoomRole" -A5 src/main/java/konkuk/thip/user/domain
src/main/java/konkuk/thip/room/adapter/out/mapper/ContentMapper.java (1)

1-28: 매퍼 구현이 깔끔하고 일관됩니다.

Content 도메인 엔티티와 ContentJpaEntity 간의 변환이 올바르게 구현되었습니다. 다른 매퍼 클래스들과 일관된 패턴을 따르고 있어 유지보수성이 좋습니다.

src/main/java/konkuk/thip/book/adapter/out/mapper/CategoryMapper.java (1)

1-28: 매퍼 구현이 적절하고 관계 처리가 올바릅니다.

Category 도메인 엔티티와 CategoryJpaEntity 간의 변환이 올바르게 구현되었습니다. AliasJpaEntity와의 관계 매핑도 적절하게 처리되었습니다.

src/main/java/konkuk/thip/user/adapter/out/mapper/AttendanceCheckMapper.java (1)

1-32: 전반적으로 잘 구현된 매퍼입니다.

AttendanceCheck 엔티티 간 변환 로직이 올바르게 구현되었고, 관련 엔티티들과의 관계 매핑도 적절합니다.

src/main/java/konkuk/thip/user/adapter/out/mapper/FollowingMapper.java (2)

11-16: JPA 엔티티 변환 메서드가 올바르게 구현되었습니다.

도메인 엔티티를 JPA 엔티티로 변환하는 로직이 정확합니다. 필요한 연관 엔티티들을 적절히 설정하고 있습니다.


18-27: ```shell
#!/bin/bash

Locate and inspect the FollowingJpaEntity to check nullability of userJpaEntity relations

Find the file path

FOLLOWING_JPA_FILE=$(fd -t f FollowingJpaEntity.java)

Print path and first 50 lines to inspect annotations

echo "File: $FOLLOWING_JPA_FILE"
sed -n '1,50p' "$FOLLOWING_JPA_FILE"


</details>
<details>
<summary>src/main/java/konkuk/thip/user/adapter/out/mapper/UserVoteMapper.java (2)</summary>

`12-17`: **JPA 엔티티 변환 로직이 적절합니다.**

사용자와 투표 아이템 간의 관계를 올바르게 매핑하고 있습니다.

---

`19-28`: **도메인 엔티티 변환에서 null 안전성을 고려해야 합니다.**

`getUserJpaEntity().getUserId()`와 `getVoteItemJpaEntity().getVoteItemId()` 호출에서 중간 객체가 null일 경우 NPE가 발생할 수 있습니다. 다른 매퍼 클래스들과 일관성 있는 null 처리 방식을 적용하는 것을 권장합니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/comment/adapter/out/mapper/CommentLikeMapper.java (1)</summary>

`12-17`: **댓글 좋아요 엔티티 매핑이 올바르게 구현되었습니다.**

사용자와 댓글 간의 좋아요 관계를 적절히 설정하고 있습니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/room/adapter/out/mapper/VoteMapper.java (1)</summary>

`12-20`: **도메인 엔티티에서 JPA 엔티티로의 변환이 올바릅니다.**

Vote 도메인 엔티티의 모든 필드가 적절히 매핑되고 있습니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/comment/adapter/out/mapper/CommentMapper.java (1)</summary>

`12-20`: **댓글 엔티티 변환 로직이 적절합니다.**

댓글의 모든 필드와 연관 관계가 올바르게 매핑되고 있습니다. 부모 댓글 설정도 적절히 처리되고 있습니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/room/domain/Room.java (1)</summary>

`10-11`: **@SuperBuilder 패턴 적용이 적절합니다.**

BaseDomainEntity 상속을 위한 @SuperBuilder 사용이 올바르게 적용되었습니다. 상속 기반 빌더 패턴이 정상적으로 동작할 것입니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/comment/domain/Comment.java (1)</summary>

`3-9`: **BaseDomainEntity 상속 및 @SuperBuilder 적용이 올바르게 구현되었습니다**

도메인 엔티티의 공통 속성을 상속받고 계층적 빌더 패턴을 지원하기 위한 변경사항이 적절합니다.

</details>
<details>
<summary>src/main/java/konkuk/thip/room/adapter/out/mapper/RoomMapper.java (2)</summary>

`11-23`: **도메인에서 JPA 엔티티로의 매핑이 적절하게 구현되었습니다**

모든 필드가 올바르게 매핑되었고 빌더 패턴을 적절히 사용하고 있습니다.

---

`25-41`: 추가로 `RoomJpaEntity` 내부에서 `BookJpaEntity` 필드의 어노테이션과 nullable 여부를 정확히 확인해 보겠습니다:


```shell
#!/bin/bash
# 1) BookJpaEntity 선언부 및 어노테이션 확인
echo "=== BookJpaEntity 필드 주변 ==="
rg -n -C3 "BookJpaEntity" src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java

# 2) @JoinColumn(nullable) 설정 확인
echo "=== @JoinColumn(nullable) 설정 ==="
rg -n "@JoinColumn" -C2 src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java
src/main/java/konkuk/thip/feed/adapter/out/mapper/TagMapper.java (2)

12-18: 도메인에서 JPA 엔티티로의 매핑이 올바르게 구현되었습니다

필드 매핑이 정확하고 다른 매퍼들과 일관된 패턴을 따르고 있습니다.


20-30: 추가 검증: TagJpaEntity.java에서 연관 필드 선언부와 적용된 어노테이션(@ManyToOne, @JoinColumn 등)을 확인해주세요.

#!/bin/bash
# TagJpaEntity 파일 경로 찾기
FILE=$(rg --files-with-matches "class TagJpaEntity")
echo "→ TagJpaEntity 파일: $FILE"

# 클래스 선언부와 연관 필드 선언부 출력
rg -n "class TagJpaEntity" -A5 "$FILE"
rg -n "private.*PostJpaEntity" -A2 "$FILE"
rg -n "private.*CategoryJpaEntity" -A2 "$FILE"

# ManyToOne, JoinColumn 어노테이션 유무 확인
rg -n "@ManyToOne" -A1 "$FILE"
rg -n "@JoinColumn" -A1 "$FILE"
src/main/java/konkuk/thip/user/adapter/out/mapper/NotificationMapper.java (2)

11-18: 도메인에서 JPA 엔티티로의 매핑이 적절하게 구현되었습니다

필드 매핑이 정확하고 일관된 패턴을 따르고 있습니다.


20-31: 아래 스크립트로 NotificationJpaEntity 내부의 userJpaEntity 필드 선언 및 애노테이션(@manytoone, @joincolumn)의 null 허용 여부를 재검증해주세요.

#!/bin/bash
# NotificationJpaEntity 파일 경로 찾기
file=$(fd NotificationJpaEntity.java -t f)
echo "NotificationJpaEntity 파일: $file"

# 클래스 선언 확인
rg -n "class NotificationJpaEntity" "$file"

# userJpaEntity 필드와 애노테이션 확인
rg -n -A3 -B3 "UserJpaEntity" "$file"

# @ManyToOne 애노테이션 확인
rg -n -A3 -B3 "ManyToOne" "$file"

# @JoinColumn 애노테이션 확인
rg -n -A3 -B3 "JoinColumn" "$file"
src/main/java/konkuk/thip/book/domain/Book.java (1)

3-9: BaseDomainEntity 상속 및 @SuperBuilder 적용이 올바르게 구현되었습니다

Comment 도메인과 동일한 패턴으로 일관성 있게 구현되었습니다.


private String value;

private Long aliasId;

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

aliasId 필드의 용도에 대한 문서화가 필요합니다.

aliasId 필드가 어떤 관계를 나타내는지 명확하지 않습니다. 자기 참조인지 다른 엔티티와의 관계인지 JavaDoc으로 설명을 추가해주세요.

+    /**
+     * 카테고리 별칭 ID (자기 참조 또는 관련 카테고리 참조)
+     */
     private Long aliasId;
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/book/domain/Category.java at line 15, the aliasId
field lacks documentation explaining its purpose and relationship. Add a JavaDoc
comment above the aliasId field clearly describing whether it represents a
self-reference or a relation to another entity, and explain its role within the
Category class.


private String searchTerm;

private String type;

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

type 필드를 enum으로 변경하는 것을 고려해보세요.

검색 타입을 문자열로 관리하는 것보다 enum을 사용하면 타입 안전성과 코드 가독성을 향상시킬 수 있습니다.

+import konkuk.thip.user.domain.type.SearchType;

 @Getter
 @SuperBuilder
 public class RecentSearch extends BaseDomainEntity {
 
     private Long id;
 
+    @NotBlank
     private String searchTerm;
 
-    private String type;
+    private SearchType type;
 
+    @NotNull
     private Long userId;
 }
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/domain/RecentSearch.java at line 15, the
'type' field is currently a String, which reduces type safety and readability.
Change the 'type' field to use an enum that defines the possible search types.
Create an enum representing the allowed search types and update all references
to 'type' accordingly to use this enum instead of a String.


private double userPercentage;

private String userRoomRole;

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

타입 안전성을 위해 enum 사용을 고려해보세요.

userRoomRole 필드가 String 타입으로 선언되어 있어 런타임에 잘못된 값이 할당될 가능성이 있습니다. 타입 안전성과 코드 명확성을 위해 enum 타입 사용을 권장합니다.

-    private String userRoomRole;
+    private UserRoomRole userRoomRole;

별도의 UserRoomRole enum 클래스를 생성하는 것도 고려해보세요:

public enum UserRoomRole {
    OWNER, ADMIN, MEMBER, READER
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/domain/UserRoom.java at line 17, the
userRoomRole field is declared as a String, which risks invalid values at
runtime. To fix this, define a separate enum class UserRoomRole with constants
like OWNER, ADMIN, MEMBER, and READER, then change the userRoomRole field's type
from String to UserRoomRole to enforce type safety and improve code clarity.

Comment on lines +28 to 32
public FeedJpaEntity(String content, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity) {
super(content, userJpaEntity);
this.isPublic = isPublic;
this.reportCount = 0; // Default 값
this.reportCount = reportCount;
this.bookJpaEntity = bookJpaEntity;

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

생성자 매개변수 검증을 추가해보세요.

reportCount 매개변수가 음수값을 가질 수 없도록 검증 로직을 추가하는 것을 권장합니다.

public FeedJpaEntity(String content, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity) {
    super(content, userJpaEntity);
    this.isPublic = isPublic;
+   if (reportCount < 0) {
+       throw new IllegalArgumentException("신고 횟수는 음수가 될 수 없습니다");
+   }
    this.reportCount = reportCount;
    this.bookJpaEntity = bookJpaEntity;
}
📝 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
public FeedJpaEntity(String content, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity) {
super(content, userJpaEntity);
this.isPublic = isPublic;
this.reportCount = 0; // Default 값
this.reportCount = reportCount;
this.bookJpaEntity = bookJpaEntity;
public FeedJpaEntity(String content, UserJpaEntity userJpaEntity, Boolean isPublic, int reportCount, BookJpaEntity bookJpaEntity) {
super(content, userJpaEntity);
this.isPublic = isPublic;
if (reportCount < 0) {
throw new IllegalArgumentException("신고 횟수는 음수가 될 수 없습니다");
}
this.reportCount = reportCount;
this.bookJpaEntity = bookJpaEntity;
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/feed/adapter/out/jpa/FeedJpaEntity.java around
lines 28 to 32, the constructor lacks validation for the reportCount parameter.
Add a check to ensure reportCount is not negative, and if it is, throw an
IllegalArgumentException or handle it appropriately to prevent invalid state.

Comment on lines +10 to +21
public BookJpaEntity toJpaEntity(Book book) {
return BookJpaEntity.builder()
.title(book.getTitle())
.isbn(book.getIsbn())
.authorName(book.getAuthorName())
.bestSeller(book.isBestSeller())
.publisher(book.getPublisher())
.imageUrl(book.getImageUrl())
.pageCount(book.getPageCount())
.description(book.getDescription())
.build();
}

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

null 안전성 검증을 추가해보세요.

매핑 메소드에서 입력 매개변수의 null 검증을 추가하는 것을 권장합니다.

public BookJpaEntity toJpaEntity(Book book) {
+   if (book == null) {
+       return null;
+   }
    return BookJpaEntity.builder()
            .title(book.getTitle())
            .isbn(book.getIsbn())
            .authorName(book.getAuthorName())
            .bestSeller(book.isBestSeller())
            .publisher(book.getPublisher())
            .imageUrl(book.getImageUrl())
            .pageCount(book.getPageCount())
            .description(book.getDescription())
            .build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/book/adapter/out/mapper/BookMapper.java between
lines 10 and 21, add a null check for the input parameter 'book' at the start of
the toJpaEntity method. If 'book' is null, handle it appropriately by either
returning null or throwing an IllegalArgumentException to prevent
NullPointerExceptions during mapping.

Comment on lines +12 to +17
public SavedFeedJpaEntity toJpaEntity(UserJpaEntity userJpaEntity, FeedJpaEntity feedJpaEntity) {
return SavedFeedJpaEntity.builder()
.userJpaEntity(userJpaEntity)
.feedJpaEntity(feedJpaEntity)
.build();
}

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

null 안전성 검증이 필요합니다.

매퍼 메서드에 null 체크가 없어서 NPE 위험이 있습니다. 입력 파라미터에 대한 검증을 추가하는 것이 좋습니다.

public SavedFeedJpaEntity toJpaEntity(UserJpaEntity userJpaEntity, FeedJpaEntity feedJpaEntity) {
+    if (userJpaEntity == null || feedJpaEntity == null) {
+        throw new IllegalArgumentException("UserJpaEntity and FeedJpaEntity cannot be null");
+    }
    return SavedFeedJpaEntity.builder()
            .userJpaEntity(userJpaEntity)
            .feedJpaEntity(feedJpaEntity)
            .build();
}
📝 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
public SavedFeedJpaEntity toJpaEntity(UserJpaEntity userJpaEntity, FeedJpaEntity feedJpaEntity) {
return SavedFeedJpaEntity.builder()
.userJpaEntity(userJpaEntity)
.feedJpaEntity(feedJpaEntity)
.build();
}
public SavedFeedJpaEntity toJpaEntity(UserJpaEntity userJpaEntity, FeedJpaEntity feedJpaEntity) {
if (userJpaEntity == null || feedJpaEntity == null) {
throw new IllegalArgumentException("UserJpaEntity and FeedJpaEntity cannot be null");
}
return SavedFeedJpaEntity.builder()
.userJpaEntity(userJpaEntity)
.feedJpaEntity(feedJpaEntity)
.build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/adapter/out/mapper/SavedFeedMapper.java
between lines 12 and 17, the toJpaEntity method lacks null checks for its input
parameters userJpaEntity and feedJpaEntity, which can cause
NullPointerExceptions. Add null validation at the start of the method to verify
that neither parameter is null, and handle the null case appropriately, such as
throwing an IllegalArgumentException or returning null, to ensure null safety.

Comment on lines +12 to +20
public RecordJpaEntity toJpaEntity(Record record, UserJpaEntity userJpaEntity, RoomJpaEntity roomJpaEntity) {
return RecordJpaEntity.builder()
.content(record.getContent())
.userJpaEntity(userJpaEntity)
.page(record.getPage())
.isOverview(record.isOverview())
.roomJpaEntity(roomJpaEntity)
.build();
}

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

복잡한 매핑에서 null 안전성과 검증 강화 필요

3개의 파라미터를 받는 메서드에서 더 철저한 검증이 필요합니다.

public RecordJpaEntity toJpaEntity(Record record, UserJpaEntity userJpaEntity, RoomJpaEntity roomJpaEntity) {
+    if (record == null) {
+        throw new IllegalArgumentException("Record cannot be null");
+    }
+    if (userJpaEntity == null || roomJpaEntity == null) {
+        throw new IllegalArgumentException("UserJpaEntity and RoomJpaEntity cannot be null");
+    }
    return RecordJpaEntity.builder()
            .content(record.getContent())
            .userJpaEntity(userJpaEntity)
            .page(record.getPage())
            .isOverview(record.isOverview())
            .roomJpaEntity(roomJpaEntity)
            .build();
}
📝 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
public RecordJpaEntity toJpaEntity(Record record, UserJpaEntity userJpaEntity, RoomJpaEntity roomJpaEntity) {
return RecordJpaEntity.builder()
.content(record.getContent())
.userJpaEntity(userJpaEntity)
.page(record.getPage())
.isOverview(record.isOverview())
.roomJpaEntity(roomJpaEntity)
.build();
}
public RecordJpaEntity toJpaEntity(Record record, UserJpaEntity userJpaEntity, RoomJpaEntity roomJpaEntity) {
if (record == null) {
throw new IllegalArgumentException("Record cannot be null");
}
if (userJpaEntity == null || roomJpaEntity == null) {
throw new IllegalArgumentException("UserJpaEntity and RoomJpaEntity cannot be null");
}
return RecordJpaEntity.builder()
.content(record.getContent())
.userJpaEntity(userJpaEntity)
.page(record.getPage())
.isOverview(record.isOverview())
.roomJpaEntity(roomJpaEntity)
.build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/mapper/RecordMapper.java around
lines 12 to 20, the toJpaEntity method takes three parameters but lacks null
checks and validation. Add null safety checks for each parameter and validate
critical fields before mapping to ensure robustness and prevent potential
NullPointerExceptions or invalid data propagation.

Comment on lines +22 to +34
public Record toDomainEntity(RecordJpaEntity recordJpaEntity) {
return Record.builder()
.id(recordJpaEntity.getPostId())
.content(recordJpaEntity.getContent())
.creatorId(recordJpaEntity.getUserJpaEntity().getUserId())
.page(recordJpaEntity.getPage())
.isOverview(recordJpaEntity.isOverview())
.roomId(recordJpaEntity.getRoomJpaEntity().getRoomId())
.createdAt(recordJpaEntity.getCreatedAt())
.modifiedAt(recordJpaEntity.getModifiedAt())
.status(recordJpaEntity.getStatus())
.build();
}

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

중첩 객체 접근에서 null 안전성 보장 필요

복잡한 도메인 매핑에서 null 체크가 더욱 중요합니다.

public Record toDomainEntity(RecordJpaEntity recordJpaEntity) {
+    if (recordJpaEntity == null) {
+        throw new IllegalArgumentException("RecordJpaEntity cannot be null");
+    }
    return Record.builder()
            .id(recordJpaEntity.getPostId())
            .content(recordJpaEntity.getContent())
-            .creatorId(recordJpaEntity.getUserJpaEntity().getUserId())
+            .creatorId(recordJpaEntity.getUserJpaEntity() != null ? 
+                      recordJpaEntity.getUserJpaEntity().getUserId() : null)
            .page(recordJpaEntity.getPage())
            .isOverview(recordJpaEntity.isOverview())
-            .roomId(recordJpaEntity.getRoomJpaEntity().getRoomId())
+            .roomId(recordJpaEntity.getRoomJpaEntity() != null ? 
+                   recordJpaEntity.getRoomJpaEntity().getRoomId() : null)
            .createdAt(recordJpaEntity.getCreatedAt())
            .modifiedAt(recordJpaEntity.getModifiedAt())
            .status(recordJpaEntity.getStatus())
            .build();
}
📝 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
public Record toDomainEntity(RecordJpaEntity recordJpaEntity) {
return Record.builder()
.id(recordJpaEntity.getPostId())
.content(recordJpaEntity.getContent())
.creatorId(recordJpaEntity.getUserJpaEntity().getUserId())
.page(recordJpaEntity.getPage())
.isOverview(recordJpaEntity.isOverview())
.roomId(recordJpaEntity.getRoomJpaEntity().getRoomId())
.createdAt(recordJpaEntity.getCreatedAt())
.modifiedAt(recordJpaEntity.getModifiedAt())
.status(recordJpaEntity.getStatus())
.build();
}
public Record toDomainEntity(RecordJpaEntity recordJpaEntity) {
if (recordJpaEntity == null) {
throw new IllegalArgumentException("RecordJpaEntity cannot be null");
}
return Record.builder()
.id(recordJpaEntity.getPostId())
.content(recordJpaEntity.getContent())
.creatorId(recordJpaEntity.getUserJpaEntity() != null
? recordJpaEntity.getUserJpaEntity().getUserId()
: null)
.page(recordJpaEntity.getPage())
.isOverview(recordJpaEntity.isOverview())
.roomId(recordJpaEntity.getRoomJpaEntity() != null
? recordJpaEntity.getRoomJpaEntity().getRoomId()
: null)
.createdAt(recordJpaEntity.getCreatedAt())
.modifiedAt(recordJpaEntity.getModifiedAt())
.status(recordJpaEntity.getStatus())
.build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/room/adapter/out/mapper/RecordMapper.java around
lines 22 to 34, the method toDomainEntity accesses nested objects without null
checks, risking NullPointerExceptions. Add null safety checks before accessing
nested properties like getUserJpaEntity() and getRoomJpaEntity(), returning
default values or handling null cases appropriately to ensure the method is
null-safe.

Comment on lines +12 to +18
public RecentSearchJpaEntity toJpaEntity(RecentSearch recentSearch, UserJpaEntity userJpaEntity) {
return RecentSearchJpaEntity.builder()
.searchTerm(recentSearch.getSearchTerm())
.type(SearchType.from(recentSearch.getType()))
.userJpaEntity(userJpaEntity)
.build();
}

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

SearchType 변환과 null 안전성 개선 필요

SearchType 변환 로직에서 예외가 발생할 수 있고, null 체크가 필요합니다.

public RecentSearchJpaEntity toJpaEntity(RecentSearch recentSearch, UserJpaEntity userJpaEntity) {
+    if (recentSearch == null || userJpaEntity == null) {
+        throw new IllegalArgumentException("RecentSearch and UserJpaEntity cannot be null");
+    }
+    
+    SearchType searchType;
+    try {
+        searchType = SearchType.from(recentSearch.getType());
+    } catch (Exception e) {
+        throw new IllegalArgumentException("Invalid search type: " + recentSearch.getType(), e);
+    }
+    
    return RecentSearchJpaEntity.builder()
            .searchTerm(recentSearch.getSearchTerm())
-            .type(SearchType.from(recentSearch.getType()))
+            .type(searchType)
            .userJpaEntity(userJpaEntity)
            .build();
}
📝 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
public RecentSearchJpaEntity toJpaEntity(RecentSearch recentSearch, UserJpaEntity userJpaEntity) {
return RecentSearchJpaEntity.builder()
.searchTerm(recentSearch.getSearchTerm())
.type(SearchType.from(recentSearch.getType()))
.userJpaEntity(userJpaEntity)
.build();
}
public RecentSearchJpaEntity toJpaEntity(RecentSearch recentSearch, UserJpaEntity userJpaEntity) {
if (recentSearch == null || userJpaEntity == null) {
throw new IllegalArgumentException("RecentSearch and UserJpaEntity cannot be null");
}
SearchType searchType;
try {
searchType = SearchType.from(recentSearch.getType());
} catch (Exception e) {
throw new IllegalArgumentException("Invalid search type: " + recentSearch.getType(), e);
}
return RecentSearchJpaEntity.builder()
.searchTerm(recentSearch.getSearchTerm())
.type(searchType)
.userJpaEntity(userJpaEntity)
.build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/adapter/out/mapper/RecentSearchMapper.java
between lines 12 and 18, the conversion of SearchType using
SearchType.from(recentSearch.getType()) can throw exceptions and lacks null
safety. Modify the code to safely handle null values from recentSearch.getType()
before conversion and catch or prevent exceptions during the conversion. Ensure
that if the type is null or invalid, a default or null value is set without
throwing an error.

Comment on lines +20 to +30
public RecentSearch toDomainEntity(RecentSearchJpaEntity recentSearchJpaEntity) {
return RecentSearch.builder()
.id(recentSearchJpaEntity.getRecentSearchId())
.searchTerm(recentSearchJpaEntity.getSearchTerm())
.type(recentSearchJpaEntity.getType().getSearchType())
.userId(recentSearchJpaEntity.getUserJpaEntity().getUserId())
.createdAt(recentSearchJpaEntity.getCreatedAt())
.modifiedAt(recentSearchJpaEntity.getModifiedAt())
.status(recentSearchJpaEntity.getStatus())
.build();
}

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

enum 역변환과 null 안전성 처리 필요

SearchType enum의 역변환과 중첩 객체 접근에서 안전성을 보장해야 합니다.

public RecentSearch toDomainEntity(RecentSearchJpaEntity recentSearchJpaEntity) {
+    if (recentSearchJpaEntity == null) {
+        throw new IllegalArgumentException("RecentSearchJpaEntity cannot be null");
+    }
    return RecentSearch.builder()
            .id(recentSearchJpaEntity.getRecentSearchId())
            .searchTerm(recentSearchJpaEntity.getSearchTerm())
-            .type(recentSearchJpaEntity.getType().getSearchType())
-            .userId(recentSearchJpaEntity.getUserJpaEntity().getUserId())
+            .type(recentSearchJpaEntity.getType() != null ? 
+                  recentSearchJpaEntity.getType().getSearchType() : null)
+            .userId(recentSearchJpaEntity.getUserJpaEntity() != null ? 
+                   recentSearchJpaEntity.getUserJpaEntity().getUserId() : null)
            .createdAt(recentSearchJpaEntity.getCreatedAt())
            .modifiedAt(recentSearchJpaEntity.getModifiedAt())
            .status(recentSearchJpaEntity.getStatus())
            .build();
}
📝 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
public RecentSearch toDomainEntity(RecentSearchJpaEntity recentSearchJpaEntity) {
return RecentSearch.builder()
.id(recentSearchJpaEntity.getRecentSearchId())
.searchTerm(recentSearchJpaEntity.getSearchTerm())
.type(recentSearchJpaEntity.getType().getSearchType())
.userId(recentSearchJpaEntity.getUserJpaEntity().getUserId())
.createdAt(recentSearchJpaEntity.getCreatedAt())
.modifiedAt(recentSearchJpaEntity.getModifiedAt())
.status(recentSearchJpaEntity.getStatus())
.build();
}
public RecentSearch toDomainEntity(RecentSearchJpaEntity recentSearchJpaEntity) {
if (recentSearchJpaEntity == null) {
throw new IllegalArgumentException("RecentSearchJpaEntity cannot be null");
}
return RecentSearch.builder()
.id(recentSearchJpaEntity.getRecentSearchId())
.searchTerm(recentSearchJpaEntity.getSearchTerm())
.type(recentSearchJpaEntity.getType() != null
? recentSearchJpaEntity.getType().getSearchType()
: null)
.userId(recentSearchJpaEntity.getUserJpaEntity() != null
? recentSearchJpaEntity.getUserJpaEntity().getUserId()
: null)
.createdAt(recentSearchJpaEntity.getCreatedAt())
.modifiedAt(recentSearchJpaEntity.getModifiedAt())
.status(recentSearchJpaEntity.getStatus())
.build();
}
🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/user/adapter/out/mapper/RecentSearchMapper.java
around lines 20 to 30, the method toDomainEntity lacks null safety checks and
does not properly convert the SearchType enum from the JPA entity to the domain
enum. Add null checks for recentSearchJpaEntity, its nested objects, and fields
to prevent NullPointerExceptions. Implement a safe enum conversion method to map
the JPA SearchType to the domain SearchType, handling possible null or unknown
values gracefully.

@hd0rable hd0rable left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

수고하셨어요!! 💯💯

super(content, userJpaEntity);
this.isPublic = isPublic;
this.reportCount = 0; // Default 값
this.reportCount = reportCount;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

이거는 왜 수정하신건가용?.. 단순궁금
새로 생성되는 FeedJpaEntity들은 신고횟수가 0이지 않나용..?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

이건 도메인 -> jpa 로 매핑시에 도메인의 reportCount 값을 jpa의 reportCount 값으로 매핑하는게 더 직관적이지 않나 싶어서 이렇게 수정했습니다!

피드를 최초로 create 하는 시점에 Feed 도메인 엔티티의 reportCount 값이 0일텐데, 이 값을 jpa로 그대로 매핑하는 느낌을 생각했습니다!

@buzz0331 buzz0331 left a comment

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.

수고하셨어용~~🤩

Comment on lines +22 to +34
public Comment toDomainEntity(CommentJpaEntity commentJpaEntity) {
return Comment.builder()
.id(commentJpaEntity.getCommentId())
.content(commentJpaEntity.getContent())
.reportCount(commentJpaEntity.getReportCount())
.targetPostId(commentJpaEntity.getPostJpaEntity().getPostId())
.creatorId(commentJpaEntity.getUserJpaEntity().getUserId())
.parentCommentId(commentJpaEntity.getParent().getCommentId())
.createdAt(commentJpaEntity.getCreatedAt())
.modifiedAt(commentJpaEntity.getModifiedAt())
.status(commentJpaEntity.getStatus())
.build();
}

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.

P1: 여기서 CommentJpaEntity가 부모 Comment가 없을 경우 NPE가 발생할 것 같은데 어떻게 생각하시나욥

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

당연히 그렇네요! 이거 매퍼에서 null 체크하도록 코드 수정하겠습니다!

buzz0331
buzz0331 previously approved these changes Jun 24, 2025
null 체크하도록 수정
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java (1)

56-68: CategoryJpaEntity 생성 로직을 개선할 수 있습니다.

현재 하드코딩된 값들("칭호1", "카테고리1")을 사용하고 있습니다. 테스트의 가독성과 유지보수성을 위해 상수로 추출하는 것을 고려해보세요.

+ private static final String TEST_ALIAS_VALUE = "칭호1";
+ private static final String TEST_CATEGORY_VALUE = "카테고리1";

  AliasJpaEntity alias = AliasJpaEntity.builder()
-         .value("칭호1")
+         .value(TEST_ALIAS_VALUE)
          .build();

  CategoryJpaEntity category = CategoryJpaEntity.builder()
-         .value("카테고리1")
+         .value(TEST_CATEGORY_VALUE)
          .aliasForCategoryJpaEntity(alias)
          .build();
src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java (1)

91-99: 코드 중복을 줄일 수 있습니다.

이 createCategory 메서드는 VoteJpaEntityTest의 동일한 메서드와 거의 같습니다. 공통 테스트 유틸리티 클래스로 추출하는 것을 고려해보세요.

테스트 간 공통 엔티티 생성 로직을 별도의 TestEntityFactory 클래스로 추출할 수 있습니다:

public class TestEntityFactory {
    public static CategoryJpaEntity createCategory(AliasJpaRepository aliasRepository, 
                                                  CategoryJpaRepository categoryRepository) {
        AliasJpaEntity alias = AliasJpaEntity.builder().value("테스트_별칭").build();
        aliasRepository.save(alias);
        
        return categoryRepository.save(CategoryJpaEntity.builder()
                .value("테스트_카테고리")
                .aliasForCategoryJpaEntity(alias)
                .build());
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 72e8301 and 26ba42a.

📒 Files selected for processing (4)
  • src/main/java/konkuk/thip/book/adapter/out/persistence/CategoryJpaRepository.java (1 hunks)
  • src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java (4 hunks)
  • src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java (4 hunks)
  • src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/konkuk/thip/book/adapter/out/persistence/CategoryJpaRepository.java
🔇 Additional comments (8)
src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RoomJpaEntityTest.java (2)

6-6: 새로운 의존성 추가가 적절하게 구현되었습니다.

CategoryJpaEntity와 AliasJpaEntity 관련 의존성들이 일관성 있게 추가되었습니다.

Also applies to: 8-8, 11-12, 30-31, 33-34


77-77: RoomJpaEntity와 CategoryJpaEntity의 연관관계 설정이 올바릅니다.

새로운 categoryJpaEntity 필드가 적절하게 설정되었습니다.

src/test/java/konkuk/thip/domain/room/adapter/out/jpa/RecordJpaEntityTest.java (3)

5-5: CategoryJpaEntity 관련 의존성이 적절하게 추가되었습니다.

새로운 엔티티 지원을 위한 import와 repository 의존성이 올바르게 추가되었습니다.

Also applies to: 7-7, 49-50


78-89: createRoom 메서드의 시그니처 변경이 적절합니다.

CategoryJpaEntity 파라미터를 받아 RoomJpaEntity에 설정하는 로직이 올바르게 구현되었습니다.


105-105: 테스트 로직 변경이 적절합니다.

createCategory()를 호출하여 CategoryJpaEntity를 생성하고 createRoom에 전달하는 로직이 올바릅니다.

src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java (3)

6-6: CategoryJpaEntity 관련 의존성이 적절하게 추가되었습니다.

새로운 엔티티 지원을 위한 import와 repository 의존성이 올바르게 추가되었습니다.

Also applies to: 8-8, 50-51


79-90: createRoom 메서드의 시그니처 변경이 적절합니다.

CategoryJpaEntity 파라미터를 받아 RoomJpaEntity에 설정하는 로직이 올바르게 구현되었습니다.


106-106: 테스트 로직 변경이 적절합니다.

createCategory()를 호출하여 CategoryJpaEntity를 생성하고 createRoom에 전달하는 로직이 올바릅니다.

Comment on lines +92 to 100
private CategoryJpaEntity createCategory() {
AliasJpaEntity alias = AliasJpaEntity.builder().value("익명1").build();
aliasRepository.save(alias);

return categoryRepository.save(CategoryJpaEntity.builder()
.value("카테고리1")
.aliasForCategoryJpaEntity(alias)
.build());
}

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

중복 코드를 반드시 제거해야 합니다.

이 createCategory 메서드는 RecordJpaEntityTest의 동일한 메서드와 완전히 같습니다. 이는 DRY 원칙에 위배되며, 유지보수 시 일관성 문제를 야기할 수 있습니다.

공통 테스트 유틸리티로 추출하거나, 최소한 상수를 사용하여 하드코딩을 피해주세요:

// 옵션 1: 공통 유틸리티 클래스 생성
// 옵션 2: 상수 사용으로 최소 개선
private static final String TEST_ALIAS_VALUE = "테스트_별칭";
private static final String TEST_CATEGORY_VALUE = "테스트_카테고리";

private CategoryJpaEntity createCategory() {
    AliasJpaEntity alias = AliasJpaEntity.builder().value(TEST_ALIAS_VALUE).build();
    aliasRepository.save(alias);

    return categoryRepository.save(CategoryJpaEntity.builder()
            .value(TEST_CATEGORY_VALUE)
            .aliasForCategoryJpaEntity(alias)
            .build());
}
🤖 Prompt for AI Agents
In src/test/java/konkuk/thip/domain/room/adapter/out/jpa/VoteJpaEntityTest.java
around lines 92 to 100, the createCategory method duplicates code found in
RecordJpaEntityTest, violating the DRY principle. Refactor by extracting this
method into a shared test utility class or at least replace hardcoded string
literals with static final constants for alias and category values to improve
maintainability and consistency across tests.

@hd0rable hd0rable self-requested a review June 24, 2025 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[THIP2025-46] [chore] 도메인 엔티티, 매퍼 추가

3 participants