From d387030a38c9fdf44c86737875d3560b061ee63d Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 23 Jun 2026 16:11:26 +0900 Subject: [PATCH] =?UTF-8?q?refactor(home-recommendation):=20=EC=B6=94?= =?UTF-8?q?=EC=B2=9C=20=EB=B0=B0=EB=84=88=20=EC=9D=91=EB=8B=B5=EC=9D=84=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=ED=99=94=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/RecommendationBannerResponse.kt | 24 +++++++++++++++++++ .../application/HomeRecommendationFacade.kt | 8 ++++--- .../HomeRecommendationResponse.kt | 12 ++-------- .../v2/common/domain/RecommendationBanner.kt | 11 +++++++++ .../HomeRecommendationResponseTest.kt | 17 ++++++++++++- 5 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/api/common/dto/RecommendationBannerResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/v2/common/domain/RecommendationBanner.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/common/dto/RecommendationBannerResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/common/dto/RecommendationBannerResponse.kt new file mode 100644 index 00000000..e020bba9 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/common/dto/RecommendationBannerResponse.kt @@ -0,0 +1,24 @@ +package kr.co.vividnext.sodalive.v2.api.common.dto + +import kr.co.vividnext.sodalive.event.EventItem +import kr.co.vividnext.sodalive.v2.common.domain.RecommendationBanner + +data class RecommendationBannerResponse( + val imageUrl: String, + val eventItem: EventItem?, + val creatorId: Long?, + val seriesId: Long?, + val link: String? +) { + companion object { + fun from(banner: RecommendationBanner): RecommendationBannerResponse { + return RecommendationBannerResponse( + imageUrl = banner.imageUrl, + eventItem = banner.eventItem, + creatorId = banner.creatorId, + seriesId = banner.seriesId, + link = banner.link + ) + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/application/HomeRecommendationFacade.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/application/HomeRecommendationFacade.kt index 4283b8e1..b727ba5d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/application/HomeRecommendationFacade.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/application/HomeRecommendationFacade.kt @@ -4,9 +4,9 @@ import kr.co.vividnext.sodalive.event.EventItem import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService import kr.co.vividnext.sodalive.member.contentpreference.isAdultVisibleByPolicy +import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeActiveCreatorItem import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeAiCharacterItem -import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeBannerItem import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeCreatorItem import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeFirstAudioContentItem import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeGenreCreatorGroupItem @@ -17,6 +17,7 @@ import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.HomeRecommendatio import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.imageUrl import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.profileImageUrl import kr.co.vividnext.sodalive.v2.api.home.dto.recommendation.toUtcIso +import kr.co.vividnext.sodalive.v2.common.domain.RecommendationBanner import kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeAiCharacterRecommendationRecord import kr.co.vividnext.sodalive.v2.recommendation.port.out.HomeBannerRecommendationRecord @@ -53,7 +54,8 @@ class HomeRecommendationFacade( memberId = member?.id, includeAdultLives = includeAdult ).map { it.toItem() }, - banners = queryService.findHomeBanners(HOME_BANNER_LIMIT, member?.id).map { it.toItem() }, + banners = queryService.findHomeBanners(HOME_BANNER_LIMIT, member?.id) + .map { RecommendationBannerResponse.from(it.toBanner()) }, recentlyActiveCreators = queryService.findRecentlyActiveCreators( HOME_ACTIVE_CREATOR_LIMIT, member?.id, @@ -235,7 +237,7 @@ class HomeRecommendationFacade( creatorProfileImage = profileImageUrl(cloudFrontHost, creatorProfileImage) ) - private fun HomeBannerRecommendationRecord.toItem() = HomeBannerItem( + private fun HomeBannerRecommendationRecord.toBanner() = RecommendationBanner( imageUrl = imageUrl(cloudFrontHost, thumbnailImage) ?: "", eventItem = eventItem(), creatorId = creatorId, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponse.kt index a5248f37..e61b81f0 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponse.kt @@ -1,7 +1,7 @@ package kr.co.vividnext.sodalive.v2.api.home.dto.recommendation import com.fasterxml.jackson.annotation.JsonProperty -import kr.co.vividnext.sodalive.event.EventItem +import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse import java.time.LocalDateTime import java.time.ZoneOffset @@ -19,7 +19,7 @@ internal fun profileImageUrl(cloudFrontHost: String, path: String?): String { data class HomeRecommendationResponse( val lives: List, - val banners: List, + val banners: List, val recentlyActiveCreators: List, val recentDebutCreators: List, val firstAudioContents: List, @@ -35,14 +35,6 @@ data class HomeLiveItem( val creatorProfileImage: String ) -data class HomeBannerItem( - val imageUrl: String, - val eventItem: EventItem?, - val creatorId: Long?, - val seriesId: Long?, - val link: String? -) - data class HomeActiveCreatorItem( val creatorNickname: String, val creatorProfileImage: String, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/common/domain/RecommendationBanner.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/common/domain/RecommendationBanner.kt new file mode 100644 index 00000000..b7d1a3d5 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/common/domain/RecommendationBanner.kt @@ -0,0 +1,11 @@ +package kr.co.vividnext.sodalive.v2.common.domain + +import kr.co.vividnext.sodalive.event.EventItem + +data class RecommendationBanner( + val imageUrl: String, + val eventItem: EventItem?, + val creatorId: Long?, + val seriesId: Long?, + val link: String? +) diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponseTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponseTest.kt index d1a15022..785110a5 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponseTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponseTest.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.v2.api.home.dto.recommendation import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import kr.co.vividnext.sodalive.v2.api.common.dto.RecommendationBannerResponse import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Test @@ -12,7 +13,15 @@ class HomeRecommendationResponseTest { fun shouldSerializeNewHomeRecommendationFields() { val response = HomeRecommendationResponse( lives = emptyList(), - banners = emptyList(), + banners = listOf( + RecommendationBannerResponse( + imageUrl = "https://cdn.test/banner.png", + eventItem = null, + creatorId = 11L, + seriesId = 12L, + link = "https://banner.test" + ) + ), recentlyActiveCreators = emptyList(), recentDebutCreators = emptyList(), firstAudioContents = listOf( @@ -83,6 +92,12 @@ class HomeRecommendationResponseTest { val json = objectMapper.readTree(objectMapper.writeValueAsString(response)) + assertEquals("https://cdn.test/banner.png", json["banners"][0]["imageUrl"].asText()) + assertEquals(true, json["banners"][0]["eventItem"].isNull) + assertEquals(11L, json["banners"][0]["creatorId"].asLong()) + assertEquals(12L, json["banners"][0]["seriesId"].asLong()) + assertEquals("https://banner.test", json["banners"][0]["link"].asText()) + assertEquals(5, json["banners"][0].size()) assertEquals(9, json["firstAudioContents"][0]["price"].asInt()) assertEquals(true, json["firstAudioContents"][0]["isPointAvailable"].asBoolean()) assertFalse(json["firstAudioContents"][0].has("pointAvailable"))