diff --git a/docs/20260313_라이브추천팔로잉전체채널조회그룹바이오류수정.md b/docs/20260313_라이브추천팔로잉전체채널조회그룹바이오류수정.md new file mode 100644 index 00000000..2e58ee4f --- /dev/null +++ b/docs/20260313_라이브추천팔로잉전체채널조회그룹바이오류수정.md @@ -0,0 +1,14 @@ +- [x] getFollowingAllChannelList 오류 재현 경로와 원인 쿼리 위치를 확인한다. +- [x] only_full_group_by 호환 방식으로 조회 쿼리를 수정한다. +- [x] 관련 응답/페이징 동작이 유지되는지 확인한다. +- [x] 변경 파일 진단과 테스트/빌드를 수행한다. + +## 검증 기록 + +### 1차 구현 +- 무엇을: `getCreatorFollowingAllList` 쿼리의 `groupBy` 컬럼을 `member.id`, `member.nickname`, `member.profileImage`, `creatorFollowing.isNotify`로 확장하고, 회귀 방지를 위해 `LiveRecommendRepositoryTest.shouldReturnFollowingCreatorListWithNotifyFlag` 테스트를 추가했다. +- 왜: `only_full_group_by` 모드에서 SELECT에 포함된 비집계 컬럼(`creatorFollowing.isNotify`)이 GROUP BY에 없어 발생하는 SQL 오류를 제거하고, 팔로잉 목록 응답(`isNotify` 포함) 동작을 재검증하기 위해서다. +- 어떻게: + - 명령: `./gradlew test --tests "kr.co.vividnext.sodalive.live.recommend.LiveRecommendRepositoryTest.shouldReturnFollowingCreatorListWithNotifyFlag"` / 결과: 성공 + - 명령: `./gradlew build` / 결과: 성공 + - 명령: `lsp_diagnostics` / 결과: `.kt` 확장 LSP 미구성으로 실행 불가(대신 Gradle 컴파일/테스트 성공으로 검증) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt index e7592698..50901f77 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepository.kt @@ -262,7 +262,12 @@ class LiveRecommendRepository( .from(creatorFollowing) .innerJoin(creatorFollowing.creator, member) .where(where) - .groupBy(member.id) + .groupBy( + member.id, + member.nickname, + member.profileImage, + creatorFollowing.isNotify + ) .offset(offset) .limit(limit) .fetch() diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepositoryTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepositoryTest.kt index bdd50ee4..f0a75628 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepositoryTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/live/recommend/LiveRecommendRepositoryTest.kt @@ -7,6 +7,7 @@ import kr.co.vividnext.sodalive.member.MemberRepository import kr.co.vividnext.sodalive.member.MemberRole import kr.co.vividnext.sodalive.member.block.BlockMember import kr.co.vividnext.sodalive.member.block.BlockMemberRepository +import kr.co.vividnext.sodalive.member.following.CreatorFollowing import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -72,12 +73,38 @@ class LiveRecommendRepositoryTest @Autowired constructor( assertEquals(creator.id, result[0].creatorId) } + @Test + fun shouldReturnFollowingCreatorListWithNotifyFlag() { + val viewer = saveMember(nickname = "viewer-following", role = MemberRole.USER) + val creatorA = saveMember(nickname = "creator-following-a", role = MemberRole.CREATOR) + val creatorB = saveMember(nickname = "creator-following-b", role = MemberRole.CREATOR) + + saveFollowing(member = viewer, creator = creatorA, isNotify = true) + saveFollowing(member = viewer, creator = creatorB, isNotify = false) + + entityManager.flush() + entityManager.clear() + + val result = liveRecommendRepository.getCreatorFollowingAllList( + memberId = viewer.id!!, + offset = 0, + limit = 20, + isBlocked = { false } + ) + + assertEquals(2, result.size) + val isNotifyByCreatorId = result.associate { it.creatorId to it.isNotify } + assertEquals(true, isNotifyByCreatorId[creatorA.id]) + assertEquals(false, isNotifyByCreatorId[creatorB.id]) + } + private fun saveMember(nickname: String, role: MemberRole): Member { return memberRepository.saveAndFlush( Member( email = "$nickname@test.com", password = "password", nickname = nickname, + profileImage = "profile/default-profile.png", role = role ) ) @@ -101,4 +128,14 @@ class LiveRecommendRepositoryTest @Autowired constructor( block.blockedMember = blockedMember blockMemberRepository.saveAndFlush(block) } + + private fun saveFollowing(member: Member, creator: Member, isNotify: Boolean) { + val following = CreatorFollowing( + isNotify = isNotify, + isActive = true + ) + following.member = member + following.creator = creator + entityManager.persist(following) + } }