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

[Feat/#615] 프로비저닝 컨텐츠 카테고리 추가 #616

Merged
merged 4 commits into from
Mar 24, 2025

Conversation

hun-ca
Copy link
Member

@hun-ca hun-ca commented Mar 20, 2025

🎫 연관 이슈

resolved #615

💁‍♂️ PR 내용

🙏 작업

  • 프로비저닝 카테고리에 13개의 카테고리가 추가되었습니다
  • 카테고리는 지피티가 본문을 읽고 결정합니다

🙈 PR 참고 사항

📸 스크린샷

image

🚩 추가된 SQL 운영계 실행계획

🤖 테스트 체크리스트

  • 체크 미완료
  • 체크 완료

Summary by CodeRabbit

  • New Features
    • 콘텐츠 응답에 새로운 “카테고리” 필드가 추가되어, 각 콘텐츠의 분류 정보를 제공하게 되었습니다.
    • 콘텐츠 생성 및 조회 과정에서 카테고리 선택 및 매핑 기능이 개선되어, 보다 풍부한 콘텐츠 경험을 즐기실 수 있습니다.

@hun-ca hun-ca added the feature label Mar 20, 2025
@hun-ca hun-ca self-assigned this Mar 20, 2025
Copy link

coderabbitai bot commented Mar 20, 2025

Walkthrough

이번 변경 사항은 프로비저닝 컨텐츠에 새롭게 카테고리 정보를 포함하도록 API 응답 및 도메인 모델을 확장하는 작업입니다. 프롬프트 생성 로직에도 카테고리 선택을 위한 기능이 추가되었으며, 관련 데이터 클래스 및 열거형(enum)이 도입되고, 일부 상수 값이 비트 시프트 방식으로 수정되었습니다. 또한, 서비스 로직 내에서 카테고리 생성 및 저장 절차가 추가되었습니다.

Changes

File(s) Change Summary
domain/generator/.../controller/ContentsGeneratorController.kt
domain/generator/.../controller/response/BrowseContentsResponse.kt
domain/generator/.../usecase/RawContentsBrowseContentUseCase.kt
domain/generator/.../usecase/out/BrowseContentsUsecaseOut.kt
응답 객체와 유스케이스 아웃풋에 category 필드 추가 및 조회 로직 수정
domain/generator/.../core/gpt/prompt/PromptGenerator.kt
domain/generator/.../core/gpt/prompt/schema/CategorySchema.kt
Gson 인스턴스 주입 및 toCategory 메서드 추가, 카테고리 선택을 위한 JSON 스키마 제공
domain/generator/.../domain/Category.kt
domain/generator/.../domain/ProvisioningContents.kt
신규 Category enum 추가 및 ProvisioningContentscategory 속성 도입 (기본값 포함)
domain/generator/.../domain/GenType.kt 기존 상수 값들을 비트 시프트 연산으로 변경하여 수정
domain/generator/.../service/ProvisioningService.kt makeCategory 메서드 추가 및 create 메서드 내에서 카테고리 값 생성 및 할당 로직 도입

Sequence Diagram(s)

sequenceDiagram
    participant Client as 클라이언트
    participant Controller as 컨트롤러
    participant Service as ProvisioningService
    participant Prompt as PromptGenerator
    participant Domain as 도메인 (Category, ProvisioningContents)

    Client->>Controller: 요청 전송
    Controller->>Service: create(프로비저닝 데이터)
    Service->>Prompt: makeCategory(제목, 설명, coreTexts)
    Prompt-->>Service: CategorySchema 반환
    Service->>Domain: ProvisioningContents 저장 (category 포함)
    Domain-->>Controller: 저장된 데이터 반환
    Controller->>Client: 응답 전송 (Category.from(code) 적용)
Loading

Assessment against linked issues

Objective Addressed Explanation
프롬프트 수정 (#615: 카테고리는 지피티가 지정할 것)
컨텐츠 조회 API에 카테고리 필드 추가 (#615)

Poem

나는 작은 토끼, 코드 숲을 뛰놀며
카테고리 필드 깡충깡충 달려와
GPT 프롬프트에 햇살 같은 아이디어 뿌리고
데이터와 열거형 속삭임에 귀를 기울이네
즐거운 변화 속에서 당근처럼 달콤한 코드를 노래하네
🐰✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c298741 and 3592778.

📒 Files selected for processing (1)
  • domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: api-test
  • GitHub Check: docs
  • GitHub Check: lint

🪧 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 generate docstrings to generate docstrings for 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.

Copy link
Member Author

@hun-ca hun-ca left a comment

Choose a reason for hiding this comment

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

프로비저닝 컨텐츠에 카테고리 16개 추가되었습니다.
확인 부탁드립니다

Comment on lines 3 to 23
enum class Category(
val code: Int,
val title: String,
) {
TECHNOLOGY(1 shl 1, "Technology"),
SCIENCE(1 shl 2, "Science"),
HEALTH(1 shl 3, "Health"),
BUSINESS(1 shl 4, "Business"),
ENTERTAINMENT(1 shl 5, "Entertainment"),
SPORTS(1 shl 6, "Sports"),
POLITICS(1 shl 7, "Politics"),
ENVIRONMENT(1 shl 8, "Environment"),
ECONOMY(1 shl 9, "Economy"),
CULTURE(1 shl 10, "Culture"),
TRAVEL(1 shl 11, "Travel"),
APPLE(1 shl 12, "Apple"),
EV(1 shl 13, "EV"),
EDUCATION(1 shl 14, "Education"),
FOOD(1 shl 15, "Food"),
ETC(1 shl 16, "Etc"),

Copy link
Member Author

Choose a reason for hiding this comment

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

지피티가 결정할 카테고리 16개

@hun-ca hun-ca requested a review from belljun3395 March 20, 2025 11:39
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

🧹 Nitpick comments (3)
domain/generator/src/main/kotlin/com/few/generator/core/gpt/prompt/PromptGenerator.kt (1)

389-423: 카테고리 선택을 위한 새로운 프롬프트 생성 메서드가 잘 구현되었습니다.

toCategory 메서드는 기존 메서드들과 일관된 패턴을 따르고 있으며, 필요한 모든 정보(제목, 요약, 본문)를 활용하여 적절한 카테고리를 선택하도록 GPT에 지시하고 있습니다. 몇 가지 개선 사항을 제안합니다:

  1. 카테고리 목록을 JSON으로 직렬화할 때 Category.values().map { it.title }을 사용하는 대신, 카테고리 정보를 더 풍부하게 제공하는 것이 좋을 수 있습니다.
  2. 프롬프트에 카테고리별 간단한 설명을 추가하면 GPT가 더 정확한 분류를 할 수 있을 것입니다.

다음과 같이 카테고리 정보를 더 풍부하게 제공하는 방법을 고려해보세요:

- val categories = gson.toJson(Category.values().map { it.title })
+ val categories = gson.toJson(Category.values().map { mapOf("title" to it.title, "code" to it.code) })

그리고 프롬프트에 카테고리 설명을 추가하는 것도 고려해보세요:

  ## 지시사항
  1. 제목, 요약 및 본문을 검토하여 주요 주제와 내용을 파악하세요.
  2. 아래 카테고리 목록에서 가장 적합한 항목을 선택하세요:
     $categories
+ 3. 카테고리 설명:
+    - Technology: 기술 관련 주제 (IT, 소프트웨어, 하드웨어 등)
+    - Science: 과학 관련 주제 (물리, 화학, 생물학 등)
+    (기타 카테고리 설명...)
  3. 주어진 카테고리 중 적합한 것이 없는 경우에만 'etc' 카테고리를 선택하세요.
domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt (2)

7-22: 비트 시프트를 활용한 코드 값 할당이 적절합니다.

비트 시프트 연산(1 shl n)을 사용하여 각 카테고리에 2의 거듭제곱 값을 할당한 것은 여러 카테고리를 조합해 사용할 수 있도록 한 좋은 접근입니다. 이는 향후 복합 카테고리 지원 시 유용합니다.

다만, 현재 코드에서는 이러한 비트 연산의 장점이 활용되지 않는 것으로 보입니다. 카테고리를 조합해서 사용할 계획이 없다면 간단한 순차적 값(1, 2, 3, ...)을 사용하는 것이 더 직관적일 수 있습니다.

비트 연산의 장점을 활용하고자 한다면, 다음과 같은 메서드를 추가하는 것이 좋을 것 같습니다:

fun hasCategory(categories: Int): Boolean = (code and categories) == code

companion object {
    // 기존 코드...
    
    fun combine(vararg categories: Category): Int =
        categories.fold(0) { acc, category -> acc or category.code }
}

26-34: Companion 객체의 유틸리티 메서드가 유용합니다.

from(code: Int)from(title: String) 메서드는 카테고리를 조회하는 유용한 유틸리티 기능을 제공합니다. 특히 title 기반 조회 시 대소문자를 무시하는 것이 사용자 친화적입니다.

한 가지 개선점은 유효하지 않은 입력에 대한 처리입니다. 현재는 예외를 발생시키지만, 상황에 따라 기본 카테고리(ETC)를 반환하거나 null을 반환하는 메서드도 추가하면 좋을 것 같습니다.

다음과 같은 추가 메서드를 고려해보세요:

companion object {
    // 기존 코드...
    
    fun fromOrNull(code: Int): Category? =
        values().find { it.code == code }
    
    fun fromOrNull(title: String): Category? =
        values().find { it.title.equals(title, ignoreCase = true) }
    
    fun fromOrDefault(code: Int, default: Category = ETC): Category =
        fromOrNull(code) ?: default
    
    fun fromOrDefault(title: String, default: Category = ETC): Category =
        fromOrNull(title) ?: default
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5b06681 and abaf5fc.

📒 Files selected for processing (10)
  • domain/generator/src/main/kotlin/com/few/generator/controller/ContentsGeneratorController.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/controller/response/BrowseContentsResponse.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/core/gpt/prompt/PromptGenerator.kt (2 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/core/gpt/prompt/schema/CategorySchema.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/domain/GenType.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/domain/ProvisioningContents.kt (1 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/service/ProvisioningService.kt (3 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/usecase/RawContentsBrowseContentUseCase.kt (2 hunks)
  • domain/generator/src/main/kotlin/com/few/generator/usecase/out/BrowseContentsUsecaseOut.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: api-test
  • GitHub Check: lint
  • GitHub Check: docs
🔇 Additional comments (16)
domain/generator/src/main/kotlin/com/few/generator/controller/response/BrowseContentsResponse.kt (1)

30-30: 카테고리 필드 추가 적절히 구현됨

프로비저닝 컨텐츠 응답에 카테고리 정보를 포함시키기 위한 category 필드가 적절히 추가되었습니다. 이 변경으로 클라이언트는 컨텐츠의 분류 정보를 받을 수 있게 되었습니다.

domain/generator/src/main/kotlin/com/few/generator/usecase/out/BrowseContentsUsecaseOut.kt (1)

28-28: 유스케이스 출력에 카테고리 필드 적절히 추가됨

프로비저닝 컨텐츠 유스케이스 출력에 category 필드가 잘 추가되었습니다. 이는 컨트롤러 응답 모델과 일관성을 유지하며, 도메인 계층에서 카테고리 정보가 적절히 전달될 수 있도록 합니다.

domain/generator/src/main/kotlin/com/few/generator/controller/ContentsGeneratorController.kt (1)

71-71: 컨트롤러 응답에 카테고리 필드 매핑 적절히 구현됨

유스케이스로부터 받은 카테고리 정보가 API 응답 객체에 올바르게 매핑되었습니다. 이로써 클라이언트는 프로비저닝 컨텐츠의 카테고리 정보를 응답에서 받을 수 있게 됩니다.

domain/generator/src/main/kotlin/com/few/generator/core/gpt/prompt/schema/CategorySchema.kt (1)

1-22:

✅ Verification successful

카테고리 스키마 구현이 적절함

GPT 응답을 위한 카테고리 스키마가 적절히 정의되었습니다. 이 스키마는 카테고리 정보를 JSON 형식으로 구조화하고 필수 필드를 명시하여 유효성 검사를 가능하게 합니다.

다만, 허용 가능한 카테고리 값에 대한 제약이나 열거형이 스키마에 정의되어 있지 않습니다. 카테고리 값이 다른 파일에서 열거형으로 관리되고 있는지 확인하는 것이 좋겠습니다.


🏁 Script executed:

#!/bin/bash
# 카테고리 열거형이 정의된 파일이 있는지 확인
fd -e kt | xargs grep -l "enum class Category"

Length of output: 183


스키마 및 열거형 관리 검증 결과 확인됨

카테고리 스키마 구현은 적절하며, 필수 필드와 JSON 구조가 잘 정의되어 있습니다.
다만, 스키마에서 직접 열거형 제약 조건이 정의되어 있지는 않으나,
아래 파일에서 열거형으로 관리되고 있음을 확인했습니다.

  • api/src/main/kotlin/com/few/api/domain/common/vo/CategoryType.kt
  • domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt

따라서 현재 스키마 구현에 추가 수정은 필요하지 않은 것으로 보입니다.
필요하다면 추후 열거형 목록을 스키마에 포함하는 것도 고려해볼 수 있습니다.

domain/generator/src/main/kotlin/com/few/generator/service/ProvisioningService.kt (4)

30-30: 카테고리 생성 기능이 추가되었습니다.

새로운 카테고리 생성 로직이 create 메서드에 추가되었네요. 이제 컨텐츠에 대한 카테고리가 자동으로 생성됩니다.


35-35: 카테고리 완료 ID가 completionIds 목록에 추가되었습니다.

GPT를 통해 생성된 카테고리의 completionId가 ProvisioningContents의 completionIds 목록에 포함되도록 수정되었습니다.


38-38: 카테고리 코드가 ProvisioningContents에 저장됩니다.

CategorySchema의 category 값을 Category enum을 통해 코드 값으로 변환하여 ProvisioningContents에 저장하고 있습니다.


63-71: makeCategory 메서드 구현이 적절합니다.

새롭게 추가된 makeCategory 메서드는 제목, 설명, 핵심 텍스트를 바탕으로 GPT를 통해 카테고리를 결정하는 로직을 구현합니다. 기존의 makeBodyTextsmakeCoreTexts 메서드와 유사한 패턴을 따르고 있어 일관성이 있습니다.

domain/generator/src/main/kotlin/com/few/generator/domain/ProvisioningContents.kt (2)

24-25: ProvisioningContents에 카테고리 필드가 추가되었습니다.

category 필드가 Int 타입으로 추가되었고, @Column(nullable = false) 어노테이션을 통해 DB에서 null을 허용하지 않도록 설정되었습니다.


33-33: 보호된 생성자에 카테고리 기본값이 설정되었습니다.

기본 생성자에서 category의 기본값을 0으로 설정하여 JPA 요구사항을 충족시켰습니다.

domain/generator/src/main/kotlin/com/few/generator/usecase/RawContentsBrowseContentUseCase.kt (2)

4-4: 도메인 패키지 임포트가 와일드카드로 변경되었습니다.

개별 클래스 임포트 대신 com.few.generator.domain.*으로 변경하여 코드가 더 간결해졌습니다.


58-58: 응답에 카테고리 정보가 포함되도록 구현되었습니다.

BrowseProvisioningContentsUsecaseOut에 category = Category.from(provContents.category).name을 추가하여 카테고리 코드를 이름으로 변환하여 응답에 포함시켰습니다.

domain/generator/src/main/kotlin/com/few/generator/domain/GenType.kt (1)

9-12: GenType 열거형 상수 값이 비트 시프트 연산으로 변경되었습니다.

기존의 고정된 정수 값(2, 4, 8, 16) 대신 비트 시프트 연산(1 shl 1, 1 shl 2 등)을 사용하여 값을 정의하도록 변경되었습니다. 이는 값 자체는 변경되지 않으면서도 각 상수가 고유한 비트 플래그를 나타낸다는 의도를 명확히 합니다.

STRATEGY_NAME_BASIC: 1 shl 1 = 2
STRATEGY_NAME_KOREAN: 1 shl 2 = 4
STRATEGY_NAME_KOREAN_QUESTION: 1 shl 3 = 8
STRATEGY_NAME_KOREAN_LONG_QUESTION: 1 shl 4 = 16

이 방식은 비트 마스킹 연산이 필요할 때 더 명확하고 유지보수하기 쉽습니다.

domain/generator/src/main/kotlin/com/few/generator/core/gpt/prompt/PromptGenerator.kt (2)

3-7: 새로운 의존성 추가가 적절합니다.

필요한 의존성을 추가하여 카테고리 기능을 구현할 수 있도록 했습니다. Gson을 주입받아 카테고리 목록을 JSON으로 직렬화하는 것은 좋은 접근 방식입니다.


11-14: 생성자에 Gson 의존성 주입이 적절합니다.

@Qualifier(GSON_BEAN_NAME) 어노테이션을 사용하여 특정 Gson 인스턴스를 주입받도록 한 점이 좋습니다. 이를 통해 애플리케이션의 다른 부분에서 사용하는 Gson 설정과 충돌 없이 일관된 직렬화가 가능합니다.

domain/generator/src/main/kotlin/com/few/generator/domain/Category.kt (1)

3-6: 카테고리 열거형이 잘 정의되었습니다.

Category 열거형은 코드와 제목을 가지고 있어 다양한 용도로 활용할 수 있습니다. 각 카테고리마다 고유한 코드와 사람이 읽을 수 있는 제목을 갖는 구조가 잘 설계되었습니다.

Copy link
Collaborator

@belljun3395 belljun3395 left a comment

Choose a reason for hiding this comment

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

확인했습니다~~!

Comment on lines 27 to 33
fun from(code: Int): Category =
Category.values().find { it.code == code }
?: throw IllegalArgumentException("Invalid Category code: $code")

fun from(title: String): Category =
values().find { it.title.equals(title, ignoreCase = true) }
?: throw IllegalArgumentException("Invalid Category title: $title")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Category.values()values() 통일하면 좋을 것 같아요

val code: Int,
val title: String,
) {
TECHNOLOGY(1 shl 1, "Technology"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

shl 은 어떤 의미에요?

Copy link
Member Author

Choose a reason for hiding this comment

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

쉬프트 연산 <<

bodyTextsJson = gson.toJson(bodyTexts.texts), // TODO: DB 저장 타입 등 정의, 수정 필요
coreTextsJson = gson.toJson(coreTexts.texts),
category = Category.from(categorySchema.category).code,
Copy link
Collaborator

Choose a reason for hiding this comment

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

없을 것 같은데 혹시라도 gpt가 선언한 카테고리 이외의 값을 반환했을 때는 Category.from에서 발생하는 예외로 충분하겠죠?

Copy link
Member Author

Choose a reason for hiding this comment

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

네네 그럴 경우엔 아에 실행중단하는게 맞을거 같네여 (무조건 ETC 카테고리로 지정하는건 옳지 않아보임)

@hun-ca hun-ca merged commit eb81205 into dev Mar 24, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

프로비저닝 컨텐츠 카테고리 추가
2 participants