feat(recommend): 홈 추천 전체보기 페이징 조회를 추가한다

This commit is contained in:
2026-06-01 13:54:40 +09:00
parent f77bd7b8e2
commit 1f3a38a404
5 changed files with 111 additions and 29 deletions

View File

@@ -88,6 +88,17 @@ class HomeRecommendationQueryServiceTest {
val creators = service.findRecentlyActiveCreators()
assertEquals(10, port.activeCreatorLimit)
assertEquals(false, port.activeCreatorIncludeAdultActivities)
assertEquals(port.activeCreators, creators)
}
@Test
@DisplayName("최근 활동 크리에이터는 성인 활동 노출 여부를 조회 포트에 위임한다")
fun shouldFindRecentlyActiveCreatorsWithAdultVisibilityPolicy() {
val creators = service.findRecentlyActiveCreators(limit = 8, includeAdultActivities = true)
assertEquals(8, port.activeCreatorLimit)
assertEquals(true, port.activeCreatorIncludeAdultActivities)
assertEquals(port.activeCreators, creators)
}
@@ -389,12 +400,19 @@ class HomeRecommendationQueryServiceTest {
private class FakeHomeRecommendationQueryPort : HomeRecommendationQueryPort {
var liveLimit: Int? = null
var liveOffset: Int? = null
var liveIncludeAdultLives: Boolean? = null
var bannerLimit: Int? = null
var activeCreatorLimit: Int? = null
var activeCreatorIncludeAdultActivities: Boolean? = null
var recentDebutNow: LocalDateTime? = null
var recentDebutLimit: Int? = null
var recentDebutOffset: Int? = null
var recentDebutIncludeAdultContents: Boolean? = null
var firstAudioNow: LocalDateTime? = null
var firstAudioLimit: Int? = null
var firstAudioOffset: Int? = null
var firstAudioIncludeAdultContents: Boolean? = null
var aiCharacterDetailIds: List<Long> = emptyList()
var cheerCreatorDetailIds: List<Long> = emptyList()
var popularCommunityDetailIds: List<Long> = emptyList()
@@ -466,8 +484,14 @@ class HomeRecommendationQueryServiceTest {
var popularCommunityDetails: List<HomePopularCommunityRecommendationRecord> = emptyList()
var genreCreatorRecommendations: List<HomeGenreCreatorRecommendationGroup> = emptyList()
override fun findLiveRecommendations(limit: Int): List<HomeLiveRecommendationRecord> {
override fun findLiveRecommendations(
offset: Int,
limit: Int,
includeAdultLives: Boolean
): List<HomeLiveRecommendationRecord> {
liveOffset = offset
liveLimit = limit
liveIncludeAdultLives = includeAdultLives
return liveRecommendations
}
@@ -476,20 +500,38 @@ class HomeRecommendationQueryServiceTest {
return banners
}
override fun findRecentlyActiveCreators(limit: Int): List<RecentlyActiveCreatorRecord> {
override fun findRecentlyActiveCreators(
limit: Int,
includeAdultActivities: Boolean
): List<RecentlyActiveCreatorRecord> {
activeCreatorLimit = limit
activeCreatorIncludeAdultActivities = includeAdultActivities
return activeCreators
}
override fun findRecentDebutCreators(now: LocalDateTime, limit: Int): List<RecentDebutCreatorRecord> {
override fun findRecentDebutCreators(
now: LocalDateTime,
offset: Int,
limit: Int,
includeAdultContents: Boolean
): List<RecentDebutCreatorRecord> {
recentDebutNow = now
recentDebutOffset = offset
recentDebutLimit = limit
recentDebutIncludeAdultContents = includeAdultContents
return recentDebutCreators
}
override fun findFirstAudioContents(now: LocalDateTime, limit: Int): List<HomeFirstAudioContentRecord> {
override fun findFirstAudioContents(
now: LocalDateTime,
offset: Int,
limit: Int,
includeAdultContents: Boolean
): List<HomeFirstAudioContentRecord> {
firstAudioNow = now
firstAudioOffset = offset
firstAudioLimit = limit
firstAudioIncludeAdultContents = includeAdultContents
return firstAudioContents
}
@@ -548,14 +590,21 @@ class HomeRecommendationQueryServiceTest {
private class FakeHomeRecommendationSnapshotPort : RecommendationSnapshotPort {
private val snapshots = mutableListOf<RecommendationSnapshotRecord>()
override fun findLatestSnapshots(sectionType: RecommendedSectionType): List<RecommendationSnapshotRecord> {
override fun findLatestSnapshots(
sectionType: RecommendedSectionType,
offset: Int,
limit: Int
): List<RecommendationSnapshotRecord> {
val latestSnapshotAt = snapshots
.filter { it.sectionType == sectionType }
.maxOfOrNull { it.snapshotAt }
return snapshots
val all = snapshots
.filter { it.sectionType == sectionType && it.snapshotAt == latestSnapshotAt }
.sortedWith(compareByDescending<RecommendationSnapshotRecord> { it.score }.thenBy { it.randomTieBreaker })
if (offset == 0 && limit == Int.MAX_VALUE) return all
return all.drop(offset).take(limit)
}
override fun replaceSnapshots(

View File

@@ -176,14 +176,21 @@ class RecommendationSnapshotRefreshServiceTest {
private class FakeRecommendationSnapshotPort : RecommendationSnapshotPort {
private val snapshots = mutableListOf<RecommendationSnapshotRecord>()
override fun findLatestSnapshots(sectionType: RecommendedSectionType): List<RecommendationSnapshotRecord> {
override fun findLatestSnapshots(
sectionType: RecommendedSectionType,
offset: Int,
limit: Int
): List<RecommendationSnapshotRecord> {
val latestSnapshotAt = snapshots
.filter { it.sectionType == sectionType }
.maxOfOrNull { it.snapshotAt }
return snapshots
val all = snapshots
.filter { it.sectionType == sectionType && it.snapshotAt == latestSnapshotAt }
.sortedWith(compareByDescending<RecommendationSnapshotRecord> { it.score }.thenBy { it.randomTieBreaker })
if (offset == 0 && limit == Int.MAX_VALUE) return all
return all.drop(offset).take(limit)
}
override fun replaceSnapshots(