10 KiB
10 KiB
PRD: 커뮤니티 게시글 좋아요 상태 응답 추가
1. Overview
v2 API에서 커뮤니티 게시글 item을 내려줄 때 인증 조회자가 해당 게시글에 좋아요를 누른 상태를 함께 제공한다.
2. Problem
- v2 커뮤니티 게시글 응답은
likeCount는 제공하지만, 조회자 본인의 좋아요 여부는 제공하지 않는다. - 앱 클라이언트는 게시글 카드의 좋아요 버튼 초기 상태를 알기 위해 별도 조회를 하거나 화면 진입 후 상태를 추정해야 한다.
- 같은 커뮤니티 게시글이 홈 추천, 크리에이터 채널 홈, 크리에이터 채널 커뮤니티 탭에서 각각 다른 DTO로 노출되므로 누락 없이 동일한 의미의 필드를 추가해야 한다.
3. Goals
- v2에서 커뮤니티 게시글 카드로 노출되는 모든 응답 item에 조회자의 좋아요 상태를 추가한다.
- 신규 응답 필드 이름은
isLiked로 한다. - Kotlin Boolean 직렬화가
liked로 바뀌지 않도록 응답 DTO에는@JsonProperty("isLiked")를 사용한다. - 좋아요 상태는
CreatorCommunityLike.isActive == true인 행을 기준으로 계산한다. - 인증 회원 기준으로 조회되는 크리에이터 채널 홈/커뮤니티 탭에서는 로그인한 조회자의 좋아요 여부를 반영한다.
- 비회원도 호출 가능한 홈 추천 전체 응답에서는 비회원의
isLiked를false로 내려준다. - 기존
likeCount,commentCount,existOrdered, 유료 콘텐츠 마스킹, 성인 콘텐츠 필터, 차단 정책은 변경하지 않는다.
4. Non-Goals
- 커뮤니티 게시글 좋아요 생성/취소 API 동작은 변경하지 않는다.
likeCount집계 기준은 변경하지 않는다.- legacy 커뮤니티 API 응답 스키마는 변경하지 않는다.
- 팔로잉 뉴스의
COMMUNITY_POSTnews item에는 게시글 카드 필드가 없으므로 이번 범위에서 제외한다. - DB schema, 운영 DDL, 마이그레이션은 포함하지 않는다.
- 추천 스냅샷 산정 로직과 인기 커뮤니티 정렬 정책은 변경하지 않는다.
5. Target Users
- 회원: 커뮤니티 게시글 카드에서 본인이 누른 좋아요 상태를 즉시 확인하려는 사용자
- 앱 클라이언트: 게시글 카드 렌더링 시 좋아요 버튼의 초기 active 상태가 필요한 클라이언트
- 서버 개발자: v2 커뮤니티 게시글 응답 간 좋아요 상태 필드 의미를 일관되게 유지해야 하는 개발자
6. 조사 결과
대상 응답 item
-
HomePopularCommunityPostItem- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/dto/recommendation/HomeRecommendationResponse.kt - 노출 API:
GET /api/v2/home/recommendations - 현재 필드:
postId,creatorId,creatorNickname,creatorProfileImage,imageUrl,audioUrl,content,price,createdAt,likeCount,commentCount,existOrdered - 데이터 흐름:
HomeRecommendationFacade가HomePopularCommunityRecommendationRecord를 변환한다.
- 파일:
-
CreatorChannelCommunityPostResponsein creator channel home- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/home/dto/CreatorChannelHomeResponse.kt - 노출 API:
GET /api/v2/creator-channels/{creatorId}/home - 현재 필드:
postId,creatorId,creatorNickname,creatorProfileUrl,imageUrl,audioUrl,content,price,dateUtc,existOrdered,likeCount,commentCount - 데이터 흐름:
CreatorChannelHomeQueryService가CreatorChannelCommunityQueryService.findHomeCommunityPosts(...)를 호출하고, 공지/커뮤니티 섹션이 같은 domain post를 사용한다.
- 파일:
-
CreatorChannelCommunityPostResponsein creator channel community tab- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/api/creator/channel/community/dto/CreatorChannelCommunityTabResponse.kt - 노출 API:
GET /api/v2/creator-channels/{creatorId}/community - 현재 필드:
postId,creatorId,creatorNickname,creatorProfileUrl,createdAtUtc,content,imageUrl,audioUrl,price,isCommentAvailable,existOrdered,likeCount,commentCount,isPinned - 데이터 흐름:
CreatorChannelCommunityQueryService.getCommunityTab(...)가CreatorChannelCommunityPost를 만들고 DTO가 이를 변환한다.
- 파일:
대상 하위 모델
-
CreatorChannelCommunityPost- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/community/domain/CreatorChannelCommunityTab.kt - 채널 홈과 커뮤니티 탭이 함께 사용하는 domain post다.
- 파일:
-
CreatorChannelCommunityPostRecord- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/community/port/out/CreatorChannelCommunityQueryPort.kt - repository에서 조회한 게시글 row와 부가 상태를 service로 전달한다.
- 파일:
-
HomePopularCommunityRecommendationRecord- 파일:
src/main/kotlin/kr/co/vividnext/sodalive/v2/recommendation/port/out/HomeRecommendationQueryPort.kt - 홈 인기 커뮤니티 상세 조회 결과를 facade로 전달한다.
- 파일:
제외 대상
HomeFollowingNews/FollowingNewsResponseFollowingNewsType.COMMUNITY_POST와targetId는 있지만 게시글 카드 DTO가 아니며likeCount도 제공하지 않는다.
7. User Stories
- 사용자는 홈 추천의 인기 커뮤니티 게시글을 볼 때 내가 이미 좋아요를 눌렀는지 바로 알고 싶다.
- 사용자는 크리에이터 채널 홈의 공지/커뮤니티 게시글 카드에서 좋아요 버튼이 현재 상태대로 표시되기를 원한다.
- 사용자는 크리에이터 채널 커뮤니티 탭 목록에서 각 게시글의 좋아요 상태가 정확하게 표시되기를 원한다.
- 앱 클라이언트는 게시글 목록 응답만으로 좋아요 버튼의 selected 상태를 렌더링하고 싶다.
8. Core Features
Feature A. 홈 인기 커뮤니티 게시글 좋아요 상태
Requirements
HomePopularCommunityPostItem에isLiked: Boolean을 추가한다.HomePopularCommunityRecommendationRecord에 조회자 좋아요 여부를 전달할 수 있는 Boolean 필드를 추가한다.DefaultHomeRecommendationQueryRepository.findPopularCommunityRecommendationDetails(...)는memberId가 null이면isLiked=false를 반환한다.memberId가 있으면 해당 회원의 활성 좋아요가 있는 게시글만isLiked=true로 반환한다.- 홈 추천 전체 응답은 비회원 호출을 허용하므로 비회원
isLiked=false를 명시적으로 보장한다.
Edge Cases
- 비활성 좋아요는
isLiked=false다. - 다른 회원이 좋아요한 게시글은 현재 조회자의
isLiked=true가 되면 안 된다. - 좋아요 수가 1 이상이어도 현재 조회자가 좋아요하지 않았으면
isLiked=false다.
Feature B. 크리에이터 채널 홈 게시글 좋아요 상태
Requirements
- 크리에이터 채널 홈의
CreatorChannelCommunityPostResponse에isLiked: Boolean을 추가한다. CreatorChannelCommunityPostdomain에 조회자 좋아요 여부를 추가한다.CreatorChannelCommunityPostRecord에 조회자 좋아요 여부를 추가한다.DefaultCreatorChannelCommunityQueryRepository.findHomeCommunityPosts(...)는 기존 id 목록 기반 부가 조회 패턴을 유지하고, 조회자 좋아요 게시글 id 목록을 bulk 조회한다.- 공지(
notices)와 일반 커뮤니티(communities) 모두 같은isLiked의미를 사용한다.
Edge Cases
- 조회자가 게시글 작성자여도 본인이 활성 좋아요를 누른 이력이 없으면
isLiked=false다. - 유료 미구매로 이미지/오디오/본문이 마스킹되어도 좋아요 상태는 실제 조회자의 활성 좋아요 기준으로 내려준다.
Feature C. 크리에이터 채널 커뮤니티 탭 게시글 좋아요 상태
Requirements
- 커뮤니티 탭의
CreatorChannelCommunityPostResponse에isLiked: Boolean을 추가한다. DefaultCreatorChannelCommunityQueryRepository.findCommunityPosts(...)도 홈 조회와 동일한 조회자 좋아요 상태 계산을 적용한다.- page/size와 무관하게 응답에 포함된 각 게시글의
isLiked가 정확해야 한다.
Edge Cases
- 현재 page에 포함되지 않은 게시글의 좋아요 상태를 조회하거나 응답에 포함하지 않는다.
- 좋아요가 없는 게시글은
isLiked=false다.
9. Technical Constraints
- 기존 v2 패키지 경계를 유지한다.
- 공개 API 응답 필드 추가 외에 기존 필드명과 의미를 변경하지 않는다.
- 커뮤니티 좋아요 상태는
CreatorCommunityLike와creatorCommunityLike.isActive.isTrue를 기준으로 한다. - 채널 홈/커뮤니티 탭은 이미
postIds기반으로likeCount,commentCount,existOrdered를 bulk 조회하므로 같은 패턴의likedCommunityPostIds(viewerId, postIds)helper를 추가하는 방향을 우선 검토한다. - 홈 인기 커뮤니티는 QueryDSL projection으로 record를 생성하므로
isLiked계산식 또는 별도 subquery를 projection에 추가하는 방향을 우선 검토한다. - Boolean 응답 필드는 Jackson 직렬화 이름 보존을 위해
@JsonProperty("isLiked")를 명시한다. - 신규 필드 추가에 따른 테스트 fixture와 controller JSON assertion을 갱신한다.
10. Success Criteria
GET /api/v2/home/recommendations의popularCommunityPosts[*].isLiked가 인증 회원 기준 활성 좋아요 여부를 반환한다.GET /api/v2/home/recommendations를 비회원으로 호출하면popularCommunityPosts[*].isLiked=false를 반환한다.GET /api/v2/creator-channels/{creatorId}/home의notices[*].isLiked,communities[*].isLiked가 인증 조회자 기준 활성 좋아요 여부를 반환한다.GET /api/v2/creator-channels/{creatorId}/community의communityPosts[*].isLiked가 인증 조회자 기준 활성 좋아요 여부를 반환한다.- 비활성 좋아요, 다른 회원의 좋아요, 좋아요 수와 조회자 좋아요 여부가 다른 케이스를 테스트로 구분한다.
- 기존 좋아요 수, 댓글 수, 구매 여부, 유료 콘텐츠 마스킹, 성인 콘텐츠 필터 테스트가 계속 통과한다.
11. Open Questions
- 없음. 필드명은 요청 의미와 기존 Boolean 응답 패턴을 기준으로
isLiked로 확정한다.