fix(character): 인기 캐릭터 응답을 DTO로 변경하여 jackson 직렬화 오류 해결
- ChatCharacterService.getPopularCharacters 반환을 List<ChatCharacter> → List<Character> DTO로 변경 - 캐시 대상도 DTO로 전환(@Cacheable 유지, 동적 키/고정 TTL 그대로 사용) - 컨트롤러에서 불필요한 매핑 제거(서비스가 DTO로 반환) - Character DTO 직렬화 안정성 확보(@JsonProperty 추가) - 이미지 URL 생성 로직을 서비스로 이동하고 imageHost(@Value) 주입해 구성
This commit is contained in:
parent
58a46a09c3
commit
27a3f450ef
|
@ -66,14 +66,6 @@ class ChatCharacterController(
|
||||||
|
|
||||||
// 인기 캐릭터 조회
|
// 인기 캐릭터 조회
|
||||||
val popularCharacters = service.getPopularCharacters()
|
val popularCharacters = service.getPopularCharacters()
|
||||||
.map {
|
|
||||||
Character(
|
|
||||||
characterId = it.id!!,
|
|
||||||
name = it.name,
|
|
||||||
description = it.description,
|
|
||||||
imageUrl = "$imageHost/${it.imagePath ?: "profile/default-profile.png"}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 최신 캐릭터 조회 (최대 10개)
|
// 최신 캐릭터 조회 (최대 10개)
|
||||||
val newCharacters = service.getNewCharacters(50)
|
val newCharacters = service.getNewCharacters(50)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package kr.co.vividnext.sodalive.chat.character.dto
|
package kr.co.vividnext.sodalive.chat.character.dto
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
|
|
||||||
data class CharacterMainResponse(
|
data class CharacterMainResponse(
|
||||||
val banners: List<CharacterBannerResponse>,
|
val banners: List<CharacterBannerResponse>,
|
||||||
val recentCharacters: List<RecentCharacter>,
|
val recentCharacters: List<RecentCharacter>,
|
||||||
|
@ -15,10 +17,10 @@ data class CurationSection(
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Character(
|
data class Character(
|
||||||
val characterId: Long,
|
@JsonProperty("characterId") val characterId: Long,
|
||||||
val name: String,
|
@JsonProperty("name") val name: String,
|
||||||
val description: String,
|
@JsonProperty("description") val description: String,
|
||||||
val imageUrl: String
|
@JsonProperty("imageUrl") val imageUrl: String
|
||||||
)
|
)
|
||||||
|
|
||||||
data class RecentCharacter(
|
data class RecentCharacter(
|
||||||
|
|
|
@ -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.ChatCharacterHobby
|
||||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag
|
import kr.co.vividnext.sodalive.chat.character.ChatCharacterTag
|
||||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacterValue
|
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.ChatCharacterGoalRepository
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepository
|
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.ChatCharacterRepository
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository
|
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository
|
||||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository
|
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.cache.annotation.Cacheable
|
||||||
import org.springframework.data.domain.PageRequest
|
import org.springframework.data.domain.PageRequest
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
@ -28,7 +30,10 @@ class ChatCharacterService(
|
||||||
private val valueRepository: ChatCharacterValueRepository,
|
private val valueRepository: ChatCharacterValueRepository,
|
||||||
private val hobbyRepository: ChatCharacterHobbyRepository,
|
private val hobbyRepository: ChatCharacterHobbyRepository,
|
||||||
private val goalRepository: ChatCharacterGoalRepository,
|
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 경계 기준 지난 윈도우의 메시지 수 상위 캐릭터 조회
|
* UTC 20:00 경계 기준 지난 윈도우의 메시지 수 상위 캐릭터 조회
|
||||||
|
@ -39,10 +44,18 @@ class ChatCharacterService(
|
||||||
cacheNames = ["popularCharacters_24h"],
|
cacheNames = ["popularCharacters_24h"],
|
||||||
key = "T(kr.co.vividnext.sodalive.chat.character.service.RankingWindowCalculator).now('popular-chat-character').cacheKey"
|
key = "T(kr.co.vividnext.sodalive.chat.character.service.RankingWindowCalculator).now('popular-chat-character').cacheKey"
|
||||||
)
|
)
|
||||||
fun getPopularCharacters(limit: Long = 20): List<ChatCharacter> {
|
fun getPopularCharacters(limit: Long = 20): List<Character> {
|
||||||
val window = RankingWindowCalculator.now("popular-chat-character")
|
val window = RankingWindowCalculator.now("popular-chat-character")
|
||||||
val topIds = popularCharacterQuery.findPopularCharacterIds(window.windowStart, window.nextBoundary, limit)
|
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<Long>): List<ChatCharacter> {
|
private fun loadCharactersInOrder(ids: List<Long>): List<ChatCharacter> {
|
||||||
|
|
Loading…
Reference in New Issue