From 27a3f450eff64fd2a9c94b869f5502bc031bed44 Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 11 Sep 2025 18:53:27 +0900 Subject: [PATCH] =?UTF-8?q?fix(character):=20=EC=9D=B8=EA=B8=B0=20?= =?UTF-8?q?=EC=BA=90=EB=A6=AD=ED=84=B0=20=EC=9D=91=EB=8B=B5=EC=9D=84=20DTO?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20jackson=20?= =?UTF-8?q?=EC=A7=81=EB=A0=AC=ED=99=94=20=EC=98=A4=EB=A5=98=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatCharacterService.getPopularCharacters 반환을 List → List DTO로 변경 - 캐시 대상도 DTO로 전환(@Cacheable 유지, 동적 키/고정 TTL 그대로 사용) - 컨트롤러에서 불필요한 매핑 제거(서비스가 DTO로 반환) - Character DTO 직렬화 안정성 확보(@JsonProperty 추가) - 이미지 URL 생성 로직을 서비스로 이동하고 imageHost(@Value) 주입해 구성 --- .../controller/ChatCharacterController.kt | 8 -------- .../character/dto/CharacterHomeResponse.kt | 10 ++++++---- .../character/service/ChatCharacterService.kt | 19 ++++++++++++++++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt index 65b551f..aaefbce 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/controller/ChatCharacterController.kt @@ -66,14 +66,6 @@ class ChatCharacterController( // 인기 캐릭터 조회 val popularCharacters = service.getPopularCharacters() - .map { - Character( - characterId = it.id!!, - name = it.name, - description = it.description, - imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}" - ) - } // 최신 캐릭터 조회 (최대 10개) val newCharacters = service.getNewCharacters(50) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterHomeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterHomeResponse.kt index b471315..e54ba93 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterHomeResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/dto/CharacterHomeResponse.kt @@ -1,5 +1,7 @@ package kr.co.vividnext.sodalive.chat.character.dto +import com.fasterxml.jackson.annotation.JsonProperty + data class CharacterMainResponse( val banners: List, val recentCharacters: List, @@ -15,10 +17,10 @@ data class CurationSection( ) data class Character( - val characterId: Long, - val name: String, - val description: String, - val imageUrl: String + @JsonProperty("characterId") val characterId: Long, + @JsonProperty("name") val name: String, + @JsonProperty("description") val description: String, + @JsonProperty("imageUrl") val imageUrl: String ) data class RecentCharacter( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt index 84422d5..c72c17a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterService.kt @@ -11,11 +11,13 @@ import kr.co.vividnext.sodalive.chat.character.ChatCharacterGoal import kr.co.vividnext.sodalive.chat.character.ChatCharacterHobby import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag import kr.co.vividnext.sodalive.chat.character.ChatCharacterValue +import kr.co.vividnext.sodalive.chat.character.dto.Character import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterGoalRepository import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepository import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository +import org.springframework.beans.factory.annotation.Value import org.springframework.cache.annotation.Cacheable import org.springframework.data.domain.PageRequest import org.springframework.stereotype.Service @@ -28,7 +30,10 @@ class ChatCharacterService( private val valueRepository: ChatCharacterValueRepository, private val hobbyRepository: ChatCharacterHobbyRepository, private val goalRepository: ChatCharacterGoalRepository, - private val popularCharacterQuery: PopularCharacterQuery + private val popularCharacterQuery: PopularCharacterQuery, + + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String ) { /** * UTC 20:00 경계 기준 지난 윈도우의 메시지 수 상위 캐릭터 조회 @@ -39,10 +44,18 @@ class ChatCharacterService( cacheNames = ["popularCharacters_24h"], key = "T(kr.co.vividnext.sodalive.chat.character.service.RankingWindowCalculator).now('popular-chat-character').cacheKey" ) - fun getPopularCharacters(limit: Long = 20): List { + fun getPopularCharacters(limit: Long = 20): List { val window = RankingWindowCalculator.now("popular-chat-character") val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit) - return loadCharactersInOrder(topIds) + val list = loadCharactersInOrder(topIds) + return list.map { + Character( + characterId = it.id!!, + name = it.name, + description = it.description, + imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}" + ) + } } private fun loadCharactersInOrder(ids: List): List {