Skip to content

feat: 사용자 도서 추천 기능(홈)#108

Merged
icarus0616 merged 2 commits into
devfrom
feat/107/home
Feb 2, 2026
Merged

feat: 사용자 도서 추천 기능(홈)#108
icarus0616 merged 2 commits into
devfrom
feat/107/home

Conversation

@millkk04
Copy link
Copy Markdown
Collaborator

@millkk04 millkk04 commented Jan 31, 2026

홈 화면 상단에 있는 내가 좋아하는 ~ 책 추천 기능입니다.
사용한 AI 모델은 gpt-4o-mini이고, 책 정보는 카카오 API KEY를 이용하였습니다.

  1. 사용자 서재가 있는 경우 -> 서재를 바탕으로 책을 추천
  2. 서재가 없는 경우, 온보딩을 기준으로 책 추천
  3. 둘 다 없는 경우, 인기 도서 기준으로 책 추천

Summary by CodeRabbit

  • New Features

    • New personalized recommendations endpoint using onboarding data, library history, and popularity fallback.
    • AI-powered keyword generation and book analysis (author/genre keywords; mood/style/immersion) to improve matching.
    • Configurable OpenAI model/key with sensible defaults for local/dev setups.
  • Bug Fixes

    • Graceful handling for users without onboarding profiles—returns an empty profile rather than throwing an error.

✏️ Tip: You can customize this high-level summary in your review settings.

@millkk04 millkk04 self-assigned this Jan 31, 2026
@millkk04 millkk04 added the enhancement New feature or request label Jan 31, 2026
@millkk04 millkk04 linked an issue Jan 31, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 31, 2026

📝 Walkthrough

Walkthrough

Adds an AI-powered recommendation feature: OpenAI GPT integration, DTOs, a GptService, onboarding recommendation orchestration, controller endpoint, utility matcher, config changes, and application.yaml defaults for OpenAI settings.

Changes

Cohort / File(s) Summary
AI & GPT Integration
booklog/src/main/java/com/example/booklog/domain/ai/entity/GptRecommendationRequest.java, booklog/src/main/java/com/example/booklog/domain/ai/entity/GptRecommendationResponse.java, booklog/src/main/java/com/example/booklog/domain/ai/service/GptService.java, booklog/src/main/java/com/example/booklog/global/config/GptConfig.java
Adds DTOs and a GptService that calls OpenAI chat completions for recommendation keyword generation and book keyword analysis; includes GptConfig exposing RestTemplate and secret/model properties.
Onboarding Recommendation DTOs
booklog/src/main/java/com/example/booklog/domain/onboarding/dto/BookRecommendationCardResponse.java, booklog/src/main/java/com/example/booklog/domain/onboarding/dto/OnboardingBasedRecommendationResponse.java
New DTOs for individual recommendation cards and aggregated recommendation response with metadata.
Recommendation Orchestration
booklog/src/main/java/com/example/booklog/domain/onboarding/service/OnboardingRecommendationService.java
New service orchestrating recommendations via library-based, onboarding-profile-based, or popularity-based flows; integrates DB, GptService, and external Kakao book searches to build recommendation cards.
Keyword Matching Utility
booklog/src/main/java/com/example/booklog/domain/onboarding/service/KeywordSimilarityMatcher.java
New component implementing character-level Jaccard similarity and helpers to match mood/style/immersion keywords and extract enum labels/descriptions.
Controller & Onboarding changes
booklog/src/main/java/com/example/booklog/domain/onboarding/controller/OnboardingController.java, booklog/src/main/java/com/example/booklog/domain/onboarding/service/OnboardingService.java, booklog/src/main/java/com/example/booklog/domain/onboarding/dto/OnboardingProfileResponse.java
Adds GET /api/v1/onboarding/recommendations endpoint wired to OnboardingRecommendationService; modifies OnboardingService to return empty profile instead of throwing; adds OnboardingProfileResponse.empty() factory.
Configuration
booklog/src/main/resources/application.yaml
Updates OpenAI model and secret-key to use environment variables with fallback defaults.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Controller as OnboardingController
    participant Service as OnboardingRecommendationService
    participant GptService as GptService
    participant KakaoAPI as Kakao Book API
    participant OpenAI as OpenAI GPT API
    participant DB as Database

    User->>Controller: GET /api/v1/onboarding/recommendations
    Controller->>Service: generateRecommendations(userId)
    Service->>DB: fetch user library / onboarding profile / popular books
    alt library path
        Service->>GptService: generateRecommendationKeyword(request)
        GptService->>OpenAI: POST chat/completions
        OpenAI-->>GptService: response
        GptService-->>Service: GptRecommendationResponse
        Service->>KakaoAPI: search books with keyword
        KakaoAPI-->>Service: book results
        Service->>GptService: analyzeBookKeywords(title, author, publisher)
        GptService->>OpenAI: POST chat/completions
        OpenAI-->>GptService: response
        GptService-->>Service: mood/style/immersion
    else onboarding path
        loop per criterion
            Service->>GptService: generateRecommendationKeyword(request)
            GptService->>OpenAI: POST chat/completions
            OpenAI-->>GptService: response
            GptService-->>Service: GptRecommendationResponse
            Service->>KakaoAPI: search books with keyword
            KakaoAPI-->>Service: book results
        end
    else popular path
        loop per book
            Service->>GptService: analyzeBookKeywords(title, author, publisher)
            GptService->>OpenAI: POST chat/completions
            OpenAI-->>GptService: response
            GptService-->>Service: mood/style/immersion
        end
    end
    Service-->>Controller: OnboardingBasedRecommendationResponse
    Controller-->>User: 200 OK + recommendations
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Feat/99/onboarding #100: Overlaps onboarding domain changes (controllers, DTOs, services, onboarding profile types) and may conflict with onboarding-related edits.

Suggested reviewers

  • jaehyeon4406
  • ktg3891
  • icarus0616

Poem

🐰 Hopping through fields of bookish light,
I fetch keywords by GPT's bright sight,
From library, profile, or what’s trending near,
I bundle recommendations, snacking on cheer,
A tiny rabbit’s hop to reading delight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.95% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: 사용자 도서 추천 기능(홈)' directly describes the main feature added: a user book recommendation function for the home page, which aligns with the core objective of adding a recommendation feature to the home screen.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/107/home

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 4

🤖 Fix all issues with AI agents
In `@booklog/src/main/java/com/example/booklog/domain/ai/service/GptService.java`:
- Around line 52-55: When returning the parsed GPT result in GptService (after
calling parseGptResponse and before the log/return), guard against an empty
response.getSearchKeyword(): if it's null/blank, construct a safe fallback
(e.g., combine non-empty genre and authorType, or use a default token like
"general" or the original prompt-derived hint) and set it on the
GptRecommendationResponse so downstream code never receives an empty query;
apply the same defensive check and fallback at the other occurrence referenced
(around lines 280–283) where GptRecommendationResponse is returned.

In
`@booklog/src/main/java/com/example/booklog/domain/onboarding/service/KeywordSimilarityMatcher.java`:
- Around line 9-12: The class JavaDoc and any inline comments claiming "cosine
similarity" and "jamo decomposition" are inaccurate; update the documentation on
KeywordSimilarityMatcher and any related comment blocks (including the other
comment span around lines 45-47) to state that the implementation uses
character-set Jaccard similarity (describe that it decomposes strings into
character sets and computes |A∩B|/|A∪B|), replace references to "cosine" and
"jamo" with "character-set Jaccard" or "character set decomposition", and ensure
the class-level and method-level docs (e.g., the KeywordSimilarityMatcher
JavaDoc and any compute/score method comments) correctly describe the actual
algorithm and any parameters/threshold semantics.

In `@booklog/src/main/java/com/example/booklog/global/config/GptConfig.java`:
- Around line 3-20: The RestTemplate bean in GptConfig.restTemplate() lacks
connect/read timeouts; update the bean to use RestTemplateBuilder (inject it
into the method or constructor) and configure setConnectTimeout and
setReadTimeout (e.g., 2000ms) before building the RestTemplate so external GPT
API calls can't hang indefinitely; ensure the bean signature still returns
RestTemplate and remove the direct new RestTemplate() usage.

In `@booklog/src/main/resources/application.yaml`:
- Around line 58-59: The secret-key property currently defaults to
"dummy-key-for-development", letting the app start without GPT_SECRET_API_KEY;
change the application.yaml entry for secret-key to make the environment
variable required (fail fast) by using the environment variable syntax that
throws on missing values for GPT_SECRET_API_KEY so the application fails at
startup when the key is not set; update the documentation/comment near
model/secret-key to reflect the new required behavior.
🧹 Nitpick comments (5)
booklog/src/main/java/com/example/booklog/domain/onboarding/service/OnboardingRecommendationService.java (4)

100-105: Broad exception handling may hide bugs.

The catch (Exception e) swallows all exceptions including potential programming errors (e.g., NullPointerException, IllegalStateException). While returning an empty response provides resilience, it may mask underlying bugs that should surface during development/testing.

Consider catching more specific exceptions or at minimum logging at error level with stack trace (which you do), but also consider whether certain exceptions should propagate (e.g., database connectivity issues might warrant a 503 response).


288-338: Misleading method name and potential performance bottleneck.

Two concerns:

  1. Misleading naming: The method generatePopularBooksRecommendations and variable popularBooks suggest popularity-based ranking, but the implementation uses Sort.by("publishedDate") - fetching the most recently published books, not the most popular ones. Consider renaming to generateLatestBooksRecommendations or implementing actual popularity metrics.

  2. Sequential GPT calls in stream: Line 306 calls gptService.analyzeBookKeywords() inside stream.map(), resulting in 6 sequential blocking API calls. This could significantly slow down response times.

♻️ Suggested fix for naming clarity
-    private OnboardingBasedRecommendationResponse generatePopularBooksRecommendations() {
+    private OnboardingBasedRecommendationResponse generateLatestBooksRecommendations() {
         try {
-            // 최근 출판된 인기 도서 조회 (publishedDate 기준 최신순)
+            // 최근 출판된 도서 조회 (publishedDate 기준 최신순)
             PageRequest pageRequest = PageRequest.of(0, MAX_RECOMMENDATIONS,
                     Sort.by(Sort.Direction.DESC, "publishedDate").and(Sort.by(Sort.Direction.DESC, "id")));

-            List<Books> popularBooks = booksRepository.findAll(pageRequest).getContent();
+            List<Books> latestBooks = booksRepository.findAll(pageRequest).getContent();

-            List<BookRecommendationCardResponse> recommendations = popularBooks.stream()
+            List<BookRecommendationCardResponse> recommendations = latestBooks.stream()

519-541: Consider using a Java record for this immutable data carrier.

Since the codebase appears to use Java 17+ (evidenced by the switch expression on line 416), this inner class could be replaced with a more concise record:

♻️ Suggested refactor to record
-    private static class RecommendationCriteria {
-        private final String fieldName;
-        private final String fieldValue;
-        private final String fieldDescription;
-
-        public RecommendationCriteria(String fieldName, String fieldValue, String fieldDescription) {
-            this.fieldName = fieldName;
-            this.fieldValue = fieldValue;
-            this.fieldDescription = fieldDescription;
-        }
-
-        public String getFieldName() {
-            return fieldName;
-        }
-
-        public String getFieldValue() {
-            return fieldValue;
-        }
-
-        public String getFieldDescription() {
-            return fieldDescription;
-        }
-    }
+    private record RecommendationCriteria(String fieldName, String fieldValue, String fieldDescription) {}

185-235: Performance: Up to 12 sequential GPT API calls per recommendation card generation.

Each library-based card makes 2 blocking GPT calls:

  1. generateRecommendationKeyword() (line 198)
  2. analyzeBookKeywords() (line 218)

With MAX_RECOMMENDATIONS = 6, this results in up to 12 sequential blocking API calls, significantly impacting response latency. The codebase has Redis caching infrastructure in place (RedisCacheConfig), but GptService methods currently lack @Cacheable annotations.

Consider:

  • Adding @Cacheable to both methods (infrastructure is already configured)
  • Batching GPT requests where possible
  • Making keyword analysis optional or lazy-loaded
booklog/src/main/java/com/example/booklog/domain/onboarding/controller/OnboardingController.java (1)

133-149: API documentation is slightly inconsistent with other endpoints.

Two minor observations:

  1. Missing 404 response: Other endpoints in this controller document a 404 response for "사용자를 찾을 수 없음", but this endpoint only documents 200 and 401. While the service returns an empty response on errors (making 404 technically unreachable), consider documenting consistently for API consumers.

  2. Description accuracy: The description states "온보딩 키워드와 최근 검색어를 바탕으로" but the service also uses library data (priority 1) and falls back to popular books. Consider updating the description to reflect all recommendation strategies:

📝 Suggested documentation update
     `@Operation`(
             summary = "온보딩 기반 도서 추천",
             description = """
-                    사용자의 온보딩 키워드와 최근 검색어를 바탕으로 개인화된 도서를 추천합니다.
+                    사용자의 서재 도서, 온보딩 키워드, 최근 검색어를 바탕으로 개인화된 도서를 추천합니다.
+                    - 서재에 도서가 있으면 서재 기반 추천
+                    - 서재가 없고 온보딩이 있으면 온보딩 기반 추천
+                    - 둘 다 없으면 최신 도서 추천
                     - 최대 6개의 추천 카드를 반환합니다.
                     - 추천 결과가 0개여도 200 OK를 반환합니다.
-                    - 각 추천 카드는 온보딩 필드 1개를 기준으로 생성됩니다.
                     """
     )

Comment on lines +52 to +55
GptRecommendationResponse response = parseGptResponse(gptResponse);

log.info("GPT 추천 키워드 생성 완료 - keyword: {}", response.getSearchKeyword());
return response;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Guard against empty GPT keywords before returning

If GPT responds off‑format, searchKeyword can end up blank (especially if genre and authorType are also empty). Add a fallback to avoid empty queries downstream.

✅ Example fallback
 GptRecommendationResponse response = parseGptResponse(gptResponse);
+String keyword = response.getSearchKeyword();
+if (keyword == null || keyword.isBlank()) {
+    String fallback = request.getFieldDescription();
+    if (fallback == null || fallback.isBlank()) {
+        fallback = request.getFieldValue();
+    }
+    keyword = (fallback == null || fallback.isBlank())
+            ? "추천 소설"
+            : fallback + " 소설";
+    response = GptRecommendationResponse.builder()
+            .authorType(response.getAuthorType())
+            .genre(response.getGenre())
+            .searchKeyword(keyword)
+            .build();
+}

 log.info("GPT 추천 키워드 생성 완료 - keyword: {}", response.getSearchKeyword());
 return response;

Also applies to: 280-283

🤖 Prompt for AI Agents
In `@booklog/src/main/java/com/example/booklog/domain/ai/service/GptService.java`
around lines 52 - 55, When returning the parsed GPT result in GptService (after
calling parseGptResponse and before the log/return), guard against an empty
response.getSearchKeyword(): if it's null/blank, construct a safe fallback
(e.g., combine non-empty genre and authorType, or use a default token like
"general" or the original prompt-derived hint) and set it on the
GptRecommendationResponse so downstream code never receives an empty query;
apply the same defensive check and fallback at the other occurrence referenced
(around lines 280–283) where GptRecommendationResponse is returned.

Comment on lines +9 to +12
/**
* 키워드 유사도 매칭 유틸리티
* - 코사인 유사도 기반 키워드 매칭
* - 사전 정의된 키워드 집합 관리
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align the docs with the actual similarity algorithm

The comments say “cosine similarity” and “jamo decomposition,” but the implementation is character‑set Jaccard. Please update the docs to reflect what’s implemented.

📝 Suggested doc update
- * - 코사인 유사도 기반 키워드 매칭
+ * - 문자 집합 기반 Jaccard 유사도 매칭
 ...
- * 한글 자모 분해 기반 간단한 유사도 계산
+ * 문자 집합 기반 간단한 유사도 계산 (Jaccard)
  * - 실제 프로덕션에서는 Word2Vec, BERT 등 사용 권장
- * - 여기서는 문자열 유사도 기반 간이 구현
+ * - 여기서는 문자 집합 유사도 기반 간이 구현

Also applies to: 45-47

🤖 Prompt for AI Agents
In
`@booklog/src/main/java/com/example/booklog/domain/onboarding/service/KeywordSimilarityMatcher.java`
around lines 9 - 12, The class JavaDoc and any inline comments claiming "cosine
similarity" and "jamo decomposition" are inaccurate; update the documentation on
KeywordSimilarityMatcher and any related comment blocks (including the other
comment span around lines 45-47) to state that the implementation uses
character-set Jaccard similarity (describe that it decomposes strings into
character sets and computes |A∩B|/|A∪B|), replace references to "cosine" and
"jamo" with "character-set Jaccard" or "character set decomposition", and ensure
the class-level and method-level docs (e.g., the KeywordSimilarityMatcher
JavaDoc and any compute/score method comments) correctly describe the actual
algorithm and any parameters/threshold semantics.

Comment on lines +3 to +20
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class GptConfig {

@Value("${spring.openai.secret-key}")
private String secretKey;

@Value("${spring.openai.model}")
private String model;

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Verify whether timeouts are configured elsewhere for RestTemplate usage
rg -n --type=java "RestTemplateBuilder|RestTemplateCustomizer|setConnectTimeout|setReadTimeout"

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


🏁 Script executed:

# Search for RestTemplate usage and any timeout configurations
rg -n --type=java "new RestTemplate\(\)|restTemplate()" -A 3 -B 1

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 1848


🏁 Script executed:

# Check for timeout configurations in properties or YAML files
rg -n "timeout|connect-timeout|read-timeout|socket-timeout" --type=yaml --type=properties

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 109


🏁 Script executed:

# Look for all RestTemplate bean definitions in the codebase
rg -n "@Bean" --type=java -A 5 | grep -A 5 "RestTemplate"

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 652


🏁 Script executed:

# Find configuration files
fd -e yml -e yaml -e properties | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 167


🏁 Script executed:

# Read application configuration
fd application -e yml -e yaml -e properties | xargs cat 2>/dev/null

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 3036


🏁 Script executed:

# Check GptService for the actual RestTemplate usage context
rg -n "restTemplate\.exchange|restTemplate\." --type=java -B 2 -A 5 booklog/src/main/java/com/example/booklog/domain/ai/service/GptService.java

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 439


Add HTTP timeouts to the RestTemplate bean

The RestTemplate bean lacks connect and read timeouts, which can cause request threads to hang indefinitely on external GPT API calls. While Redis is configured with a 2000ms timeout, the RestTemplate has no such protection. Use RestTemplateBuilder to set appropriate timeouts.

🔧 Suggested fix
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.client.RestTemplate;
+import java.time.Duration;

 `@Bean`
-public RestTemplate restTemplate() {
-    return new RestTemplate();
+public RestTemplate restTemplate(RestTemplateBuilder builder) {
+    return builder
+            .setConnectTimeout(Duration.ofSeconds(3))
+            .setReadTimeout(Duration.ofSeconds(10))
+            .build();
 }
🤖 Prompt for AI Agents
In `@booklog/src/main/java/com/example/booklog/global/config/GptConfig.java`
around lines 3 - 20, The RestTemplate bean in GptConfig.restTemplate() lacks
connect/read timeouts; update the bean to use RestTemplateBuilder (inject it
into the method or constructor) and configure setConnectTimeout and
setReadTimeout (e.g., 2000ms) before building the RestTemplate so external GPT
API calls can't hang indefinitely; ensure the bean signature still returns
RestTemplate and remove the direct new RestTemplate() usage.

Comment on lines +58 to +59
model: ${OPENAI_MODEL:gpt-4o-mini}
secret-key: ${GPT_SECRET_API_KEY:dummy-key-for-development}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, find all application config files
echo "=== All application config files ==="
fd -a 'application.*ya?ml' booklog/

echo -e "\n=== Current application.yaml content (lines 50-70) ==="
if [ -f "booklog/src/main/resources/application.yaml" ]; then
  sed -n '50,70p' booklog/src/main/resources/application.yaml
else
  echo "File not found"
fi

echo -e "\n=== Search for secret-key in all yaml files ==="
rg -n 'secret-key' -g '*.ya?ml' booklog/src/main/resources/

echo -e "\n=== Check for profile-specific files ==="
ls -la booklog/src/main/resources/application-*.yaml 2>/dev/null || echo "No profile-specific files found"

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 913


🏁 Script executed:

#!/bin/bash

echo "=== Search for README or setup docs ==="
fd -i readme -t f booklog/ | head -5

echo -e "\n=== Check pom.xml for Spring Boot version ==="
if [ -f "booklog/pom.xml" ]; then
  grep -A 2 "spring-boot-starter" booklog/pom.xml | head -10
fi

echo -e "\n=== Search for environment variable documentation ==="
rg -i 'environment|openai.*key|gpt.*secret' -t md -t txt booklog/ | head -10

echo -e "\n=== Check for deployment/docker configs ==="
fd -a 'Dockerfile|docker-compose|\.env' booklog/

echo -e "\n=== Check for other references to OpenAI config ==="
rg 'OPENAI_MODEL|GPT_SECRET_API_KEY' booklog/ --type yaml --type java --type properties | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 366


🏁 Script executed:

#!/bin/bash

echo "=== Check entire pom.xml for Spring Boot ==="
find booklog -name "pom.xml" -exec head -50 {} \;

echo -e "\n=== Look for any setup or configuration documentation ==="
find booklog -type f \( -name "*.md" -o -name "*.txt" -o -name "*.adoc" \) | head -10

echo -e "\n=== Check application.yaml structure to understand full config ==="
head -100 booklog/src/main/resources/application.yaml

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 2858


Make OpenAI secret-key fail fast on missing configuration

The current default dummy-key-for-development allows the application to start even when GPT_SECRET_API_KEY is not provided, surfacing the error only at runtime when the API is called. This is inconsistent with how other required API keys are configured (database, Kakao OAuth, Kakao REST API) which have no defaults and fail immediately at startup. Use a fail-fast placeholder instead:

Recommended fix
-    secret-key: ${GPT_SECRET_API_KEY:dummy-key-for-development}
+    secret-key: ${GPT_SECRET_API_KEY:?missing_gpt_key}
📝 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
model: ${OPENAI_MODEL:gpt-4o-mini}
secret-key: ${GPT_SECRET_API_KEY:dummy-key-for-development}
model: ${OPENAI_MODEL:gpt-4o-mini}
secret-key: ${GPT_SECRET_API_KEY:?missing_gpt_key}
🤖 Prompt for AI Agents
In `@booklog/src/main/resources/application.yaml` around lines 58 - 59, The
secret-key property currently defaults to "dummy-key-for-development", letting
the app start without GPT_SECRET_API_KEY; change the application.yaml entry for
secret-key to make the environment variable required (fail fast) by using the
environment variable syntax that throws on missing values for GPT_SECRET_API_KEY
so the application fails at startup when the key is not set; update the
documentation/comment near model/secret-key to reflect the new required
behavior.

@icarus0616
Copy link
Copy Markdown
Collaborator

check

@icarus0616 icarus0616 merged commit 9060800 into dev Feb 2, 2026
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 온보딩 기반 사용자 책 추천 기능

2 participants