Feat(#76): 챗봇 API 프록시 구현 - #78
Conversation
📝 WalkthroughWalkthroughChangesChat proxy feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
actor Client
participant ChatController
participant ChatService
participant AnalysisRepository
participant AiChatClient
participant FastAPI
Client->>ChatController: POST /api/v1/chat
ChatController->>ChatService: chat(userId, request)
ChatService->>AnalysisRepository: Load analysis and indicators
AnalysisRepository-->>ChatService: Analysis context
ChatService->>AiChatClient: Forward context and messages
AiChatClient->>FastAPI: POST /api/chat
FastAPI-->>AiChatClient: Chat response
AiChatClient-->>ChatService: AiChatResponse
ChatService-->>ChatController: ChatResponse
ChatController-->>Client: ApiResponse success
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java (1)
1-112: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd a test for the timeout-mapping branch.
The tests cover the success path, a 5xx failure, and a missing-message response, but none exercise
hasSocketTimeoutCauseinAiChatClient.java(Lines 80-89), which maps aSocketTimeoutExceptioncause toCHAT_SERVICE_TIMEOUT. This branch is called out directly in the PR objectives as a required failure mapping. Add a test that injects aRestTemplatewhose request factory throws aResourceAccessExceptionwrapping aSocketTimeoutException, and assertErrorCode.CHAT_SERVICE_TIMEOUT.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java` around lines 1 - 112, Add a test method to AiChatClientTest that uses a RestTemplate configured with a request factory throwing a ResourceAccessException whose cause is SocketTimeoutException, then invokes AiChatClient.chat(request()) and asserts the resulting BusinessException has ErrorCode.CHAT_SERVICE_TIMEOUT. Keep the existing request fixture and test coverage unchanged.src/main/java/com/gold/safefam/domain/chat/controller/ChatController.java (1)
34-43: 🚀 Performance & Scalability | 🔵 TrivialConsider rate limiting for this AI-backed endpoint.
This endpoint forwards every request to an external AI chat service, which is latency-sensitive and potentially costly per call. The codebase already defines
ANALYSIS_RATE_LIMIT_EXCEEDEDfor a similar costly flow (analysis submission). Consider applying a comparable rate limit to/api/v1/chatto prevent abuse or runaway costs, since a single authenticated user can otherwise issue unlimited multi-turn requests to the AI service.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/gold/safefam/domain/chat/controller/ChatController.java` around lines 34 - 43, Apply the existing rate-limiting mechanism used by the analysis submission flow to the ChatController.chat endpoint, using the established ANALYSIS_RATE_LIMIT_EXCEEDED response or equivalent configured limit for authenticated users. Ensure requests exceeding the per-user limit are rejected before invoking chatService.chat, while preserving the current successful response behavior.src/main/java/com/gold/safefam/domain/chat/client/AiChatClient.java (1)
24-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse an HTTP client that supports custom request timeouts.
RestClientdoes not exposeSimpleClientHttpRequestFactory-style connect/read timeout settings the way this constructor does. If this is a new synchronous chat client on Spring Boot 4.1.0, build it with the timeout requirements in mind instead of adding anotherRestTemplatepath.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/gold/safefam/domain/chat/client/AiChatClient.java` around lines 24 - 43, Update the primary AiChatClient constructor to use the Spring HTTP client implementation that supports configuring both connectTimeout and readTimeout, rather than constructing a RestTemplate with SimpleClientHttpRequestFactory. Preserve the injected timeout properties and the existing chatUrl normalization, and keep the package-private constructor’s injected client behavior consistent with the selected client type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/gold/safefam/domain/chat/client/AiChatClient.java`:
- Around line 45-72: Add a logger to AiChatClient and, in the final catch
(RuntimeException exception) branch of chat, log the caught exception with its
stack trace and relevant context before converting it to
BusinessException(ErrorCode.CHAT_INVALID_RESPONSE). Leave the existing handling
for expected BusinessException, ResourceAccessException, and
HttpStatusCodeException cases unchanged.
---
Nitpick comments:
In `@src/main/java/com/gold/safefam/domain/chat/client/AiChatClient.java`:
- Around line 24-43: Update the primary AiChatClient constructor to use the
Spring HTTP client implementation that supports configuring both connectTimeout
and readTimeout, rather than constructing a RestTemplate with
SimpleClientHttpRequestFactory. Preserve the injected timeout properties and the
existing chatUrl normalization, and keep the package-private constructor’s
injected client behavior consistent with the selected client type.
In `@src/main/java/com/gold/safefam/domain/chat/controller/ChatController.java`:
- Around line 34-43: Apply the existing rate-limiting mechanism used by the
analysis submission flow to the ChatController.chat endpoint, using the
established ANALYSIS_RATE_LIMIT_EXCEEDED response or equivalent configured limit
for authenticated users. Ensure requests exceeding the per-user limit are
rejected before invoking chatService.chat, while preserving the current
successful response behavior.
In `@src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java`:
- Around line 1-112: Add a test method to AiChatClientTest that uses a
RestTemplate configured with a request factory throwing a
ResourceAccessException whose cause is SocketTimeoutException, then invokes
AiChatClient.chat(request()) and asserts the resulting BusinessException has
ErrorCode.CHAT_SERVICE_TIMEOUT. Keep the existing request fixture and test
coverage unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f277b373-9420-41dd-a530-ec0fa3ec6fb4
📒 Files selected for processing (18)
.env.example.env.prod.exampleREADME.mddocker-compose.ymldocs/safefam-backend.mdsrc/main/java/com/gold/safefam/domain/analysis/repository/AnalysisRepository.javasrc/main/java/com/gold/safefam/domain/chat/client/AiChatClient.javasrc/main/java/com/gold/safefam/domain/chat/controller/ChatController.javasrc/main/java/com/gold/safefam/domain/chat/dto/ChatMessage.javasrc/main/java/com/gold/safefam/domain/chat/dto/ChatRequest.javasrc/main/java/com/gold/safefam/domain/chat/dto/ChatResponse.javasrc/main/java/com/gold/safefam/domain/chat/dto/ChatRole.javasrc/main/java/com/gold/safefam/domain/chat/service/ChatService.javasrc/main/java/com/gold/safefam/global/exception/ErrorCode.javasrc/main/resources/application.ymlsrc/test/java/com/gold/safefam/SafefamApplicationTests.javasrc/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.javasrc/test/java/com/gold/safefam/domain/chat/service/ChatServiceTest.java
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java (1)
31-53: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd a multi-turn payload assertion.
The success case sends only one
usermessage. It does not verify that anassistantmessage and a laterusermessage preserve role values and order. Add a multi-turn fixture and assert every message in the JSON request body.Also applies to: 119-129
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java` around lines 31 - 53, Add a multi-turn message fixture to callsFastApiChatContractAndReadsMessage, including user, assistant, and later user entries, then update the content.json assertion to verify every message’s role, content, and order in the POST request payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java`:
- Around line 31-53: Add a multi-turn message fixture to
callsFastApiChatContractAndReadsMessage, including user, assistant, and later
user entries, then update the content.json assertion to verify every message’s
role, content, and order in the POST request payload.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: bf233e61-70e5-4fed-b0b7-7afe82260e04
📒 Files selected for processing (11)
src/main/java/com/gold/safefam/domain/analysis/controller/AnalysisController.javasrc/main/java/com/gold/safefam/domain/auth/controller/AuthController.javasrc/main/java/com/gold/safefam/domain/chat/client/AiChatClient.javasrc/main/java/com/gold/safefam/domain/family/controller/FamilyController.javasrc/main/java/com/gold/safefam/domain/family/safety/controller/FamilySafetyCaseController.javasrc/main/java/com/gold/safefam/domain/notification/controller/DeviceController.javasrc/main/java/com/gold/safefam/domain/report/controller/ReportController.javasrc/main/java/com/gold/safefam/domain/statistics/controller/StatisticsController.javasrc/main/java/com/gold/safefam/domain/user/controller/UserController.javasrc/main/java/com/gold/safefam/domain/whitelist/controller/WhitelistController.javasrc/test/java/com/gold/safefam/domain/chat/client/AiChatClientTest.java
📋 작업 내용
POST /api/v1/chatSpring 챗봇 프록시 엔드포인트를 추가했습니다.analysisId로 본인 소유 분석 결과를 조회하고, 위험 점수·등급·피싱 유형·설명·탐지 근거를 FastAPI 컨텍스트로 자동 변환합니다.USER/ASSISTANT메시지를 FastAPIPOST /api/chat계약으로 전달합니다.analysisId와 현재 대화 이력만 전송하며, 응답은data.message에서 확인합니다.🧪 테스트 결과
.\gradlew.bat test— 전체 144개 테스트 통과.\gradlew.bat bootJar— Spring Boot JAR 빌드 성공docker compose config --quiet— 일회성 더미 환경변수로 Compose 문법 검증docker compose build/up— PostgreSQL, RabbitMQ, Spring Backend 모두 healthy 및 Swagger/api/v1/chat반영 확인🔗 관련 이슈
Closes #76
✅ 체크리스트
Summary by CodeRabbit
New Features
POST /api/v1/chat.Documentation
Tests