Skip to content

Commit 828f9e4

Browse files
JIWONKIMSclaude
andcommitted
fix(be): Fix WebSocket chat connection and reduce production logs (#issue)
- Change AI Tool logs from INFO to DEBUG to reduce production log volume - WeatherTool: All log.info() -> log.debug() - TourTool: All log.info() -> log.debug() - GuideFinderTool: All log.info() -> log.debug() - Fix AuthController NullPointerException for unauthenticated users - Make authentication parameter nullable in updateUserRole() - Add proper null check with error message - Fix WebSocket chat message publishing in production - Change RabbitChatMessagePublisher to use SimpMessagingTemplate - Replace AMQP direct publishing with STOMP Broker Relay - Fixes 'chat.reconnecting' issue where messages weren't delivered to STOMP subscribers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 6d24f35 commit 828f9e4

File tree

5 files changed

+23
-22
lines changed

5 files changed

+23
-22
lines changed

src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/GuideFinderTool.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ class GuideFinderTool(
2323
)
2424
region: String,
2525
): String {
26-
log.info("🔧 [TOOL CALLED] findGuidesByRegion - region: $region")
26+
log.debug("🔧 [TOOL CALLED] findGuidesByRegion - region: $region")
2727

2828
val guides = guideService.findGuidesByRegion(region)
2929

3030
return try {
3131
if (guides.isEmpty()) {
32-
log.info("✅ [TOOL RESULT] findGuidesByRegion - 결과 없음")
32+
log.debug("✅ [TOOL RESULT] findGuidesByRegion - 결과 없음")
3333
return "해당 지역에서 활동하는 가이드를 찾을 수 없습니다."
3434
}
3535
val result = objectMapper.writeValueAsString(guides)
36-
log.info("✅ [TOOL RESULT] findGuidesByRegion - 결과: ${result.take(200)}...")
36+
log.debug("✅ [TOOL RESULT] findGuidesByRegion - 결과: ${result.take(200)}...")
3737
result
3838
} catch (e: Exception) {
3939
log.error("❌ [TOOL ERROR] findGuidesByRegion - 예외 발생: ${e.javaClass.name}", e)

src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/TourTool.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class TourTool(
4949
)
5050
areaAndSigunguCode: String,
5151
): String {
52-
log.info(
52+
log.debug(
5353
"🔧 [TOOL CALLED] getAreaBasedTourInfo - " +
5454
"contentTypeId: $contentTypeId, areaAndSigunguCode: $areaAndSigunguCode, languageCode: $languageCode",
5555
)
@@ -59,7 +59,7 @@ class TourTool(
5959

6060
return try {
6161
val result = tourInfo.let { objectMapper.writeValueAsString(it) }
62-
log.info("✅ [TOOL RESULT] getAreaBasedTourInfo - 결과: ${result.take(100)}...")
62+
log.debug("✅ [TOOL RESULT] getAreaBasedTourInfo - 결과: ${result.take(100)}...")
6363
result
6464
} catch (e: Exception) {
6565
log.error("❌ [TOOL ERROR] getAreaBasedTourInfo - 예외 발생", e)
@@ -110,7 +110,7 @@ class TourTool(
110110
@ToolParam(description = "검색 반경(미터 단위)", required = true)
111111
radius: String = "100",
112112
): String {
113-
log.info(
113+
log.debug(
114114
"🔧 [TOOL CALLED] getLocationBasedTourInfo - " +
115115
"contentTypeId: $contentTypeId, area: $areaAndSigunguCode, " +
116116
"mapX: $mapX, mapY: $mapY, radius: $radius, languageCode: $languageCode",
@@ -122,7 +122,7 @@ class TourTool(
122122

123123
return try {
124124
val result = tourLocationBasedInfo.let { objectMapper.writeValueAsString(it) }
125-
log.info("✅ [TOOL RESULT] getLocationBasedTourInfo - 결과: ${result.take(100)}...")
125+
log.debug("✅ [TOOL RESULT] getLocationBasedTourInfo - 결과: ${result.take(100)}...")
126126
result
127127
} catch (e: Exception) {
128128
log.error("❌ [TOOL ERROR] getLocationBasedTourInfo - 예외 발생", e)
@@ -153,14 +153,14 @@ class TourTool(
153153
)
154154
contentId: String,
155155
): String {
156-
log.info("🔧 [TOOL CALLED] getTourDetailInfo - contentId: $contentId, languageCode: $languageCode")
156+
log.debug("🔧 [TOOL CALLED] getTourDetailInfo - contentId: $contentId, languageCode: $languageCode")
157157

158158
val tourDetailParams = TourDetailParams(contentId)
159159
val tourDetailInfo = tourService.fetchTourDetail(tourDetailParams, languageCode)
160160

161161
return try {
162162
val result = tourDetailInfo.let { objectMapper.writeValueAsString(it) }
163-
log.info("✅ [TOOL RESULT] getTourDetailInfo - 결과: ${result.take(100)}...")
163+
log.debug("✅ [TOOL RESULT] getTourDetailInfo - 결과: ${result.take(100)}...")
164164
result
165165
} catch (e: Exception) {
166166
log.error("❌ [TOOL ERROR] getTourDetailInfo - 예외 발생", e)

src/main/kotlin/com/back/koreaTravelGuide/domain/ai/aiChat/tool/WeatherTool.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ class WeatherTool(
1515
) {
1616
@Tool(description = "전국 중기예보를 조회합니다")
1717
fun getWeatherForecast(): String {
18-
log.info("🔧 [TOOL CALLED] getWeatherForecast")
18+
log.debug("🔧 [TOOL CALLED] getWeatherForecast")
1919

2020
val forecasts = weatherService.getWeatherForecast()
21-
log.info("📦 [DATA] forecasts is null? ${forecasts == null}")
22-
log.info("📦 [DATA] forecasts 타입: ${forecasts?.javaClass?.name}")
23-
log.info("📦 [DATA] forecasts 내용: $forecasts")
21+
log.debug("📦 [DATA] forecasts is null? ${forecasts == null}")
22+
log.debug("📦 [DATA] forecasts 타입: ${forecasts?.javaClass?.name}")
23+
log.debug("📦 [DATA] forecasts 내용: $forecasts")
2424

2525
return try {
2626
val result = forecasts?.let { objectMapper.writeValueAsString(it) } ?: "중기예보 데이터를 가져올 수 없습니다."
27-
log.info("✅ [TOOL RESULT] getWeatherForecast - 결과: $result")
27+
log.debug("✅ [TOOL RESULT] getWeatherForecast - 결과: $result")
2828
result
2929
} catch (e: Exception) {
3030
log.error("❌ [TOOL ERROR] getWeatherForecast - 예외 발생: ${e.javaClass.name}", e)
@@ -41,13 +41,13 @@ class WeatherTool(
4141
)
4242
location: String,
4343
): String {
44-
log.info("🔧 [TOOL CALLED] getRegionalWeatherDetails - location: $location")
44+
log.debug("🔧 [TOOL CALLED] getRegionalWeatherDetails - location: $location")
4545

4646
val forecasts = weatherService.getTemperatureAndLandForecast(location)
4747

4848
return try {
4949
val result = forecasts?.let { objectMapper.writeValueAsString(it) } ?: "$location 지역의 상세 날씨 정보를 가져올 수 없습니다."
50-
log.info("✅ [TOOL RESULT] getRegionalWeatherDetails - 결과: $result")
50+
log.debug("✅ [TOOL RESULT] getRegionalWeatherDetails - 결과: $result")
5151
result
5252
} catch (e: Exception) {
5353
log.error("❌ [TOOL ERROR] getRegionalWeatherDetails - 예외 발생: ${e.javaClass.name}", e)

src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ class AuthController(
4646
@Operation(summary = "신규 사용자 역할 선택")
4747
@PostMapping("/role")
4848
fun updateUserRole(
49-
authentication: Authentication,
49+
authentication: Authentication?,
5050
@RequestBody request: UserRoleUpdateRequest,
5151
response: HttpServletResponse,
5252
): ResponseEntity<ApiResponse<AccessTokenResponse>> {
53-
val userId = authentication.getUserId()
53+
val userId = authentication?.getUserId() ?: throw IllegalArgumentException("인증되지 않은 사용자입니다.")
5454
val (accessToken, refreshToken) = authService.updateRoleAndLogin(userId, request.role)
5555

5656
val cookie =
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
package com.back.koreaTravelGuide.domain.userChat.chatmessage.usecase
22

3-
import org.springframework.amqp.rabbit.core.RabbitTemplate
43
import org.springframework.context.annotation.Profile
4+
import org.springframework.messaging.simp.SimpMessagingTemplate
55
import org.springframework.stereotype.Component
66

77
@Profile("prod")
88
@Component
99
class RabbitChatMessagePublisher(
10-
private val rabbitTemplate: RabbitTemplate,
10+
private val messagingTemplate: SimpMessagingTemplate,
1111
) : ChatMessagePublisher {
1212
override fun publishUserChat(
1313
roomId: Long,
1414
payload: Any,
1515
) {
16-
val routingKey = "userchat.$roomId"
17-
rabbitTemplate.convertAndSend("amq.topic", routingKey, payload)
16+
// STOMP Broker Relay를 통해 RabbitMQ로 메시지 발행
17+
// enableStompBrokerRelay("/topic") 설정에 의해 자동으로 RabbitMQ STOMP Broker로 라우팅됨
18+
messagingTemplate.convertAndSend("/topic/userchat/$roomId", payload)
1819
}
1920
}

0 commit comments

Comments
 (0)