Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ 프로필 위젯 추가 API #33

Merged
merged 2 commits into from
Nov 11, 2024
Merged

✨ 프로필 위젯 추가 API #33

merged 2 commits into from
Nov 11, 2024

Conversation

waterfogSW
Copy link
Member

@waterfogSW waterfogSW commented Nov 11, 2024

Summary by CodeRabbit

  • 새로운 기능

    • 사용자 프로필 위젯 업데이트를 위한 새로운 인터페이스 및 메서드 추가.
    • 사용자 정보 응답에 프로필 위젯을 포함하도록 업데이트.
    • 프로필 위젯을 추가하거나 교체할 수 있는 기능 추가.
  • 버그 수정

    • 사용자 ID로 사용자를 검색할 때 명확한 예외 처리 추가.
  • 테스트

    • 프로필 위젯 추가 및 업데이트 기능에 대한 테스트 케이스 추가.
  • 데이터베이스 변경

    • 사용자 프로필과 관련된 새로운 테이블 user_profile_widgets 생성.

Copy link

coderabbitai bot commented Nov 11, 2024

Walkthrough

이 변경 사항은 PutProfileWidget이라는 새로운 인터페이스를 도입하여 사용자 프로필 위젯을 업데이트하고 관리하는 기능을 추가합니다. 이 인터페이스는 Command라는 데이터 클래스를 통해 사용자 ID와 프로필 위젯 정보를 캡슐화합니다. 또한, UserService, UserController, User, UserProfile 클래스에 새로운 메서드가 추가되어 프로필 위젯의 추가 및 업데이트를 지원하며, 데이터베이스 스키마에 새로운 테이블이 생성되어 이러한 위젯 정보를 저장합니다.

Changes

파일 경로 변경 요약
application/src/main/kotlin/com/threedays/application/user/port/inbound/PutProfileWidget.kt 새로운 인터페이스 PutProfileWidget 추가, 메서드 invoke(command: Command) 및 데이터 클래스 Command 추가
application/src/main/kotlin/com/threedays/application/user/service/UserService.kt UserService 클래스가 PutProfileWidget 인터페이스를 구현하도록 수정, 메서드 invoke(command: PutProfileWidget.Command) 추가
bootstrap/api/src/main/kotlin/com/threedays/bootstrap/api/user/UserController.kt UserController 클래스에 새로운 메서드 putProfileWidget 추가, 생성자에 putProfileWidget 매개변수 추가
domain/src/main/kotlin/com/threedays/domain/user/entity/ProfileWidget.kt ProfileWidget 클래스의 comment 속성을 content로 변경
domain/src/main/kotlin/com/threedays/domain/user/entity/User.kt User 클래스에 putProfileWidget(widget: ProfileWidget): User 메서드 추가
domain/src/main/kotlin/com/threedays/domain/user/entity/UserProfile.kt UserProfile 클래스에 putProfileWidget(profileWidget: ProfileWidget): UserProfile 메서드 추가
domain/src/main/kotlin/com/threedays/domain/user/repository/UserRepository.kt UserRepository 인터페이스에 get(id: User.Id): User 메서드 추가
domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt User 클래스의 putProfileWidget 메서드에 대한 테스트 추가
infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/ProfileWidgetJpaEmbeddable.kt 새로운 클래스 ProfileWidgetJpaEmbeddable 추가, 변환 메서드 추가
infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/UserProfileJpaEntity.kt UserProfileJpaEntity 클래스에 profileWidgets 속성 추가
infrastructure/persistence/src/main/resources/db/migration/V1__init_user.sql user_profile_widgets 테이블 생성 SQL 추가
openapi 서브프로젝트의 커밋 참조가 업데이트됨

Possibly related PRs

Suggested reviewers

  • dojinyou

🐇 새로운 위젯 추가해,
프로필을 채워가네,
사용자와 함께,
즐거운 변화라네!
위젯이 빛나는,
우리의 세상 속,
함께 만들어가요! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (14)
domain/src/main/kotlin/com/threedays/domain/user/entity/ProfileWidget.kt (2)

Line range hint 1-21: 문서화 개선이 필요합니다.

클래스와 enum에 대한 KDoc 문서화를 추가하여 각 위젯 타입의 용도와 content 필드에 들어갈 수 있는 값의 형식을 명확히 설명하면 좋을 것 같습니다.

예시:

/**
 * 사용자 프로필에 표시되는 위젯을 나타내는 데이터 클래스
 *
 * @property type 위젯의 종류
 * @property content 위젯에 표시될 내용
 */
data class ProfileWidget(
    val type: Type,
    val content: String,
) {
    /**
     * 프로필 위젯의 가능한 종류들을 정의
     */
    enum class Type {
        /** 취미 정보 */
        HOBBY,
        // ... 다른 타입들에 대한 설명
    }
}

5-5: content 필드에 대한 유효성 검증이 필요합니다.

content 필드의 길이 제한이나 필수 값 여부 등의 제약 조건을 추가하는 것이 좋을 것 같습니다.

예시:

data class ProfileWidget(
    val type: Type,
    val content: String,
) {
    init {
        require(content.isNotBlank()) { "content는 비어있을 수 없습니다" }
        require(content.length <= MAX_CONTENT_LENGTH) { "content는 ${MAX_CONTENT_LENGTH}자를 초과할 수 없습니다" }
    }

    companion object {
        const val MAX_CONTENT_LENGTH = 100
    }
}
application/src/main/kotlin/com/threedays/application/user/port/inbound/PutProfileWidget.kt (3)

6-7: 인터페이스에 KDoc 문서화를 추가해주세요.

이 인터페이스의 목적과 책임을 명확히 설명하는 문서화가 필요합니다.

다음과 같은 문서화를 제안드립니다:

+/**
+ * 사용자의 프로필 위젯을 추가하거나 업데이트하는 인바운드 포트
+ *
+ * @see ProfileWidget
+ * @see User
+ */
 interface PutProfileWidget {

8-8: 메서드 문서화와 예외 처리 명세가 필요합니다.

메서드의 동작, 파라미터, 발생 가능한 예외 상황에 대한 명세가 필요합니다.

다음과 같은 개선을 제안드립니다:

+    /**
+     * 사용자의 프로필 위젯을 추가하거나 업데이트합니다.
+     *
+     * @param command 프로필 위젯 업데이트 명령
+     * @throws UserNotFoundException 사용자를 찾을 수 없는 경우
+     * @throws InvalidWidgetDataException 위젯 데이터가 유효하지 않은 경우
+     */
     fun invoke(command: Command)

10-13: Command 클래스의 속성 문서화와 유효성 검증이 필요합니다.

데이터 클래스의 각 속성에 대한 설명과 제약 조건을 명시하면 좋겠습니다.

다음과 같은 개선을 제안드립니다:

     data class Command(
+        /**
+         * 프로필 위젯을 업데이트할 사용자의 ID
+         */
         val userId: User.Id,
+        /**
+         * 업데이트할 프로필 위젯 정보
+         */
         val profileWidget: ProfileWidget
-    )
+    ) {
+        init {
+            require(profileWidget.isValid()) { "프로필 위젯 데이터가 유효하지 않습니다" }
+        }
+    }
domain/src/main/kotlin/com/threedays/domain/user/repository/UserRepository.kt (1)

10-11: KDoc 문서화 추가를 제안드립니다.

메서드의 목적과 발생 가능한 예외에 대한 문서화를 추가하면 좋을 것 같습니다.

다음과 같은 문서화를 추가해보세요:

+    /**
+     * 주어진 ID로 사용자를 조회합니다.
+     *
+     * @param id 조회할 사용자의 ID
+     * @return 조회된 사용자 객체
+     * @throws NotFoundException 해당 ID의 사용자가 존재하지 않는 경우
+     */
     fun get(id: User.Id): User = find(id)
infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/ProfileWidgetJpaEmbeddable.kt (2)

8-13: 클래스 문서화가 필요합니다.

데이터 클래스의 구조는 잘 되어있지만, 다음 사항들에 대한 KDoc 문서화를 추가하면 좋을 것 같습니다:

  • 클래스의 목적과 사용 사례
  • 각 프로퍼티의 의미와 제약 조건
  • @Embeddable을 사용한 이유

예시:

/**
 * 사용자 프로필 위젯의 영속성을 위한 임베디드 클래스입니다.
 * 
 * @property type 위젯의 종류
 * @property content 위젯의 내용
 */
@Embeddable
data class ProfileWidgetJpaEmbeddable(

15-22: null 안전성 개선이 필요합니다.

도메인 객체를 JPA 엔티티로 변환하는 과정에서 null 안전성을 고려해야 합니다.

다음과 같이 개선을 제안합니다:

     companion object {
-        fun ProfileWidget.toJpaEmbeddable() = ProfileWidgetJpaEmbeddable(
+        fun ProfileWidget?.toJpaEmbeddable(): ProfileWidgetJpaEmbeddable? = this?.let {
+            ProfileWidgetJpaEmbeddable(
                 type = type,
                 content = content,
-        )
+            )
+        }
     }
domain/src/main/kotlin/com/threedays/domain/user/entity/UserProfile.kt (1)

18-27: 구현이 깔끔하고 적절합니다!

불변성을 유지하면서 위젯을 추가하거나 업데이트하는 로직이 잘 구현되어 있습니다.

다만, 다음 사항들을 고려해보시면 좋을 것 같습니다:

  • KDoc을 추가하여 메서드의 동작을 문서화
  • profileWidget 파라미터에 대한 유효성 검사 추가
  • 프로필 위젯 최대 개수 제한 고려

다음과 같이 개선해 보는 것은 어떨까요?

+    /**
+     * 프로필 위젯을 추가하거나 업데이트합니다.
+     * 동일한 타입의 위젯이 이미 존재하는 경우 새로운 위젯으로 교체됩니다.
+     *
+     * @param profileWidget 추가하거나 업데이트할 프로필 위젯
+     * @return 업데이트된 UserProfile 인스턴스
+     * @throws IllegalArgumentException 위젯이 null이거나 최대 개수를 초과하는 경우
+     */
     fun putProfileWidget(profileWidget: ProfileWidget): UserProfile {
+        require(profileWidget.isValid()) { "프로필 위젯이 유효하지 않습니다" }
+        require(profileWidgets.size < MAX_WIDGETS || profileWidgets.any { it.type == profileWidget.type }) {
+            "프로필 위젯은 최대 ${MAX_WIDGETS}개까지만 추가할 수 있습니다"
+        }
+
         val existingProfileWidget: ProfileWidget? =
             profileWidgets.find { it.type == profileWidget.type }

         return if (existingProfileWidget == null) {
             copy(profileWidgets = profileWidgets + profileWidget)
         } else {
             copy(profileWidgets = profileWidgets.map { if (it.type == profileWidget.type) profileWidget else it })
         }
     }
+
+    companion object {
+        const val MAX_WIDGETS = 5
+    }
infrastructure/persistence/src/main/resources/db/migration/V1__init_user.sql (1)

63-70: 기본 구조는 적절하나 몇 가지 개선사항이 있습니다.

테이블 구조가 전반적으로 잘 설계되어 있습니다. 복합 기본키와 외래키 제약조건이 적절히 구현되어 있습니다.

다음과 같은 개선사항을 고려해보시기 바랍니다:

 CREATE TABLE user_profile_widgets
 (
     user_profile_id BINARY(16)   NOT NULL,
     type            VARCHAR(255) NOT NULL,
     content         VARCHAR(255) NOT NULL,
+    created_at      TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    updated_at      TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     PRIMARY KEY (user_profile_id, type),
+    INDEX idx_user_profile_widgets_type (type),
     FOREIGN KEY (user_profile_id) REFERENCES user_profiles (id) ON DELETE CASCADE
 );
  1. 위젯 타입별 조회를 위한 인덱스 추가
  2. 생성/수정 시간 컬럼 추가로 감사 추적 지원
  3. 필요한 경우 content 컬럼의 크기를 TEXT로 변경하는 것을 고려해보세요 (위젯 콘텐츠의 예상 크기에 따라)
domain/src/main/kotlin/com/threedays/domain/user/entity/User.kt (1)

89-91: 구현이 깔끔하나 유효성 검증이 필요할 수 있습니다.

메서드 구현이 불변성을 잘 유지하고 있으며 책임을 적절히 위임하고 있습니다. 하지만 widget 파라미터에 대한 유효성 검증을 고려해보시면 좋을 것 같습니다.

다음과 같은 방식으로 검증 로직을 추가하는 것을 고려해보세요:

 fun putProfileWidget(widget: ProfileWidget): User {
+    require(widget.userId == id) { "위젯의 사용자 ID가 일치하지 않습니다." }
     return copy(profile = profile.putProfileWidget(widget))
 }
infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/UserProfileJpaEntity.kt (1)

68-74: JPA 어노테이션 설정을 검토해주세요.

현재 설정된 FetchType.EAGER는 성능에 영향을 미칠 수 있습니다:

  • 프로필을 조회할 때마다 위젯 데이터도 함께 로드됩니다
  • 위젯 데이터가 많아질 경우 성능 저하가 발생할 수 있습니다

다음과 같은 개선을 고려해보세요:

-    @ElementCollection(fetch = FetchType.EAGER)
+    @ElementCollection(fetch = FetchType.LAZY)
bootstrap/api/src/main/kotlin/com/threedays/bootstrap/api/user/UserController.kt (1)

109-114: enum 매핑 방식 개선 제안

현재 구현된 enum 매핑 방식은 도메인 모델과 API 모델 간의 결합도가 높습니다. 향후 유지보수성을 높이기 위해 다음과 같은 개선을 고려해보세요.

- type = com.threedays.oas.model.ProfileWidgetType.valueOf(it.type.name),
+ type = it.type.toApiModel(), // Extension 함수로 분리

도메인 모델에 다음과 같은 확장 함수를 추가하는 것을 추천드립니다:

fun ProfileWidget.Type.toApiModel(): com.threedays.oas.model.ProfileWidgetType {
    return when (this) {
        Type.SOME_TYPE -> ProfileWidgetType.SOME_TYPE
        // ... 다른 케이스들
    }
}
domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (1)

168-184: 테스트 케이스 보완이 필요합니다.

기본 기능에 대한 테스트는 잘 작성되어 있으나, 다음과 같은 엣지 케이스들도 검증이 필요해 보입니다:

  1. 최대 허용 위젯 개수를 초과하는 경우
  2. 유효하지 않은 위젯 데이터가 입력된 경우
  3. 동일한 위젯을 중복 추가하는 경우

추가 테스트 케이스 작성을 도와드릴까요?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0f14154 and e64cad2.

📒 Files selected for processing (12)
  • application/src/main/kotlin/com/threedays/application/user/port/inbound/PutProfileWidget.kt (1 hunks)
  • application/src/main/kotlin/com/threedays/application/user/service/UserService.kt (3 hunks)
  • bootstrap/api/src/main/kotlin/com/threedays/bootstrap/api/user/UserController.kt (4 hunks)
  • domain/src/main/kotlin/com/threedays/domain/user/entity/ProfileWidget.kt (1 hunks)
  • domain/src/main/kotlin/com/threedays/domain/user/entity/User.kt (1 hunks)
  • domain/src/main/kotlin/com/threedays/domain/user/entity/UserProfile.kt (1 hunks)
  • domain/src/main/kotlin/com/threedays/domain/user/repository/UserRepository.kt (1 hunks)
  • domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (2 hunks)
  • infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/ProfileWidgetJpaEmbeddable.kt (1 hunks)
  • infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/UserProfileJpaEntity.kt (5 hunks)
  • infrastructure/persistence/src/main/resources/db/migration/V1__init_user.sql (1 hunks)
  • openapi (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • openapi
🔇 Additional comments (14)
domain/src/main/kotlin/com/threedays/domain/user/entity/ProfileWidget.kt (1)

4-6: 속성 이름 변경이 적절해 보입니다.

'comment'에서 'content'로의 변경은 위젯의 내용을 더 잘 표현하는 이름입니다.

application/src/main/kotlin/com/threedays/application/user/port/inbound/PutProfileWidget.kt (1)

1-5: 패키지 구조와 임포트가 적절합니다!

헥사고날 아키텍처의 포트 계층에 맞게 잘 구성되어 있으며, 필요한 도메인 엔티티만 임포트하고 있습니다.

domain/src/main/kotlin/com/threedays/domain/user/repository/UserRepository.kt (1)

10-11: 구현이 깔끔하고 적절합니다!

기존의 getByPhoneNumber 메서드와 일관된 방식으로 구현되었으며, 명확한 예외 처리가 포함되어 있습니다.

infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/ProfileWidgetJpaEmbeddable.kt (2)

1-7: 패키지 구조와 임포트가 적절합니다!

영속성 계층에 맞는 패키지 구조와 필요한 임포트들이 잘 정의되어 있습니다.


24-28: 양방향 변환 패턴 검증이 필요합니다.

도메인 객체로의 변환도 null 안전성이 필요하며, 양방향 변환 패턴이 일관되게 사용되는지 확인이 필요합니다.

다음과 같은 개선을 제안합니다:

-    fun toValueObject() = ProfileWidget(
+    fun toValueObject(): ProfileWidget = ProfileWidget(
         type = type,
         content = content,
     )
✅ Verification successful

Let me gather more information about the conversion patterns and null safety.


Let me check the ProfileWidget domain class to understand its structure better.


양방향 변환 패턴이 적절하게 구현되어 있습니다.

검증 결과:

  • 도메인 객체(ProfileWidget)와 JPA 엔티티(ProfileWidgetJpaEmbeddable) 모두 non-null 프로퍼티만 사용
  • 양방향 변환 메서드가 일관되게 구현되어 있음
  • 타입 안전성이 보장됨

리턴 타입 명시는 선택적이며, 현재 구현에서는 불필요합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: 양방향 변환 패턴의 일관성 검증

# 다른 JPA 엔티티에서 유사한 변환 패턴 검색
rg -t kotlin "fun.*toValueObject|fun.*toJpaEmbeddable" --glob "infrastructure/persistence/**/*.kt"

Length of output: 437


Script:

#!/bin/bash
# Check the implementation details of both conversion methods
rg -A 5 -B 5 "fun.*toValueObject|fun.*toJpaEmbeddable" --glob "infrastructure/persistence/**/*.kt"

# Check if there are any nullable properties in the ProfileWidget class
ast-grep --pattern 'class ProfileWidget($$$)'

Length of output: 2446


Script:

#!/bin/bash
# Find and check the ProfileWidget domain class implementation
rg -A 10 "class ProfileWidget" --glob "**/domain/**/*.kt"

# Check if there are any nullable properties in ProfileWidgetJpaEmbeddable
rg -A 5 "class ProfileWidgetJpaEmbeddable" --glob "infrastructure/persistence/**/*.kt"

Length of output: 1936

application/src/main/kotlin/com/threedays/application/user/service/UserService.kt (3)

5-5: LGTM - 필요한 import 추가됨

PutProfileWidget 인터페이스 구현을 위한 import가 적절히 추가되었습니다.


23-23: LGTM - 인터페이스 구현이 명확히 선언됨

PutProfileWidget 인터페이스가 기존 RegisterUser 인터페이스와 함께 적절히 구현 선언되었습니다.


57-63: 🛠️ Refactor suggestion

트랜잭션 범위와 에러 처리 개선 필요

현재 구현에서 몇 가지 개선이 필요한 부분이 있습니다:

  1. 트랜잭션 전파 속성이 명시되어 있지 않습니다.
  2. 사용자를 찾지 못했을 때의 예외 처리가 명시적이지 않습니다.
  3. 프로필 위젯 업데이트 실패에 대한 예외 처리가 없습니다.

다음과 같이 개선을 제안드립니다:

-    @Transactional
+    @Transactional(rollbackFor = [Exception::class])
     override fun invoke(command: PutProfileWidget.Command) {
-        userRepository
-            .get(command.userId)
-            .putProfileWidget(command.profileWidget)
-            .also { userRepository.save(it) }
+        try {
+            val user = userRepository.get(command.userId)
+                ?: throw UserNotFoundException("사용자를 찾을 수 없습니다: ${command.userId}")
+            
+            user.putProfileWidget(command.profileWidget)
+                .also { userRepository.save(it) }
+        } catch (e: Exception) {
+            throw ProfileWidgetUpdateException("프로필 위젯 업데이트 실패", e)
+        }
     }

프로필 위젯 업데이트 관련 예외 클래스들이 정의되어 있는지 확인이 필요합니다:

domain/src/main/kotlin/com/threedays/domain/user/entity/User.kt (1)

89-91: UserProfile 클래스와의 통합 검증이 필요합니다.

profile.putProfileWidget() 메서드가 UserProfile 클래스에 올바르게 구현되어 있는지 확인이 필요합니다.

✅ Verification successful

UserProfile 클래스의 putProfileWidget 메서드가 올바르게 구현되어 있음을 확인했습니다.

UserProfile 클래스에서 putProfileWidget 메서드는 다음과 같이 적절하게 구현되어 있습니다:

  • 동일한 타입의 위젯이 있는 경우 업데이트
  • 새로운 타입의 위젯인 경우 목록에 추가
  • 불변성을 유지하며 새로운 UserProfile 인스턴스를 반환

따라서 User 클래스의 putProfileWidget 메서드에서 이를 호출하는 것이 안전합니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# UserProfile 클래스에서 putProfileWidget 메서드 구현 확인
ast-grep --pattern 'class UserProfile {
  $$$
  fun putProfileWidget($_) {
    $$$
  }
  $$$
}'

Length of output: 97


Script:

#!/bin/bash
# UserProfile 관련 파일 찾기
fd "UserProfile.kt"

# UserProfile 클래스 내용 확인
rg -A 5 "class UserProfile" 

# putProfileWidget 메서드 검색
rg "putProfileWidget"

Length of output: 2979


Script:

#!/bin/bash
# UserProfile 클래스의 putProfileWidget 메서드 구현 확인
cat domain/src/main/kotlin/com/threedays/domain/user/entity/UserProfile.kt

Length of output: 1066

infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/UserProfileJpaEntity.kt (3)

9-9: 새로운 임포트 구문이 적절히 추가되었습니다.

ProfileWidget 관련 기능을 위한 필수 임포트들이 잘 추가되었습니다.

Also applies to: 12-12


34-34: 프로필 위젯 속성이 적절히 추가되었습니다.

생성자에 profileWidgets 매개변수가 잘 추가되었습니다.


85-85: 도메인 변환 메서드가 적절히 수정되었습니다.

toJpaEntity()와 toDomainEntity() 메서드에 profileWidgets 변환 로직이 올바르게 추가되었습니다.

하지만 다음 사항을 확인해주세요:

Also applies to: 97-97

✅ Verification successful

ProfileWidget 변환 메서드가 모두 적절히 구현되어 있음을 확인했습니다.

ProfileWidgetJpaEmbeddable에 도메인 객체와 JPA 엔티티 간의 변환을 위한 toJpaEmbeddable()과 toValueObject() 메서드가 올바르게 구현되어 있습니다. 변환 로직이 완전하게 구현되어 있어 추가 검증이 필요하지 않습니다.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# ProfileWidget 관련 변환 메서드들이 구현되어 있는지 확인
rg -l "toValueObject|toJpaEmbeddable" --type kotlin

Length of output: 269


Script:

#!/bin/bash
# ProfileWidgetJpaEmbeddable.kt 파일의 변환 메서드 구현 확인
rg "toValueObject|toJpaEmbeddable" -A 5 -B 5 infrastructure/persistence/src/main/kotlin/com/threedays/persistence/user/entity/ProfileWidgetJpaEmbeddable.kt

Length of output: 457

bootstrap/api/src/main/kotlin/com/threedays/bootstrap/api/user/UserController.kt (1)

3-5: 의존성 주입이 올바르게 구현되었습니다!

Spring의 생성자 주입 패턴을 잘 따르고 있으며, 필요한 의존성들이 명확하게 정의되어 있습니다.

Also applies to: 30-30

domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (1)

6-6: LGTM!

FixtureMonkey의 set 함수를 import하여 테스트 데이터 설정에 적절히 활용하고 있습니다.

Copy link

sonarcloud bot commented Nov 11, 2024

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (1)

192-225: 테스트 케이스 보완이 필요합니다.

현재 구현에 다음과 같은 테스트 케이스를 추가하면 좋을 것 같습니다:

  1. 실패 케이스 테스트:

    • 유효하지 않은 위젯 데이터 처리
    • null 값 처리
  2. 검증 로직 강화:

    • 이전 위젯이 실제로 제거되었는지 확인
    • 위젯 개수가 정확한지 검증
    • 다른 타입의 위젯들은 영향받지 않았는지 확인

예시 구현:

context("위젯 데이터가 유효하지 않은 경우") {
    it("예외가 발생한다") {
        // arrange
        val invalidWidget: ProfileWidget = fixtureMonkey
            .giveMeBuilder<ProfileWidget>()
            .set(ProfileWidget::content, "") // 빈 컨텐츠
            .sample()

        // act & assert
        shouldThrow<IllegalArgumentException> {
            user.putProfileWidget(invalidWidget)
        }
    }
}

context("동일한 타입의 위젯을 업데이트하는 경우") {
    it("이전 위젯은 제거되고 새 위젯만 존재한다") {
        // arrange
        val oldWidget = // ... 기존 코드와 동일
        val newWidget = // ... 기존 코드와 동일
        
        // act
        val result = user.putProfileWidget(newWidget)
        
        // assert
        result.profile.profileWidgets.count { it.type == widgetType } shouldBe 1
        result.profile.profileWidgets.find { it == oldWidget } shouldBe null
        result.profile.profileWidgets.find { it == newWidget } shouldBe newWidget
    }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e64cad2 and 2f24aca.

📒 Files selected for processing (1)
  • domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (2 hunks)
🔇 Additional comments (2)
domain/src/test/kotlin/com/threedays/domain/user/entity/UserTest.kt (2)

6-6: LGTM!

FixtureMonkey의 set 함수 import가 새로운 테스트 케이스에 적절하게 추가되었습니다.


167-190: 테스트 구현이 잘 되었습니다!

다음과 같은 장점들이 있습니다:

  • Arrange/Act/Assert 패턴을 명확하게 따르고 있습니다
  • FixtureMonkey를 활용한 테스트 데이터 생성이 잘 구현되었습니다
  • 테스트 의도가 명확합니다

@waterfogSW waterfogSW merged commit 373f965 into main Nov 11, 2024
3 checks passed
@waterfogSW waterfogSW deleted the feat/profile-widget branch November 11, 2024 05: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.

1 participant