Files

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인 행을 기준으로 계산한다.
  • 인증 회원 기준으로 조회되는 크리에이터 채널 홈/커뮤니티 탭에서는 로그인한 조회자의 좋아요 여부를 반영한다.
  • 비회원도 호출 가능한 홈 추천 전체 응답에서는 비회원의 isLikedfalse로 내려준다.
  • 기존 likeCount, commentCount, existOrdered, 유료 콘텐츠 마스킹, 성인 콘텐츠 필터, 차단 정책은 변경하지 않는다.

4. Non-Goals

  • 커뮤니티 게시글 좋아요 생성/취소 API 동작은 변경하지 않는다.
  • likeCount 집계 기준은 변경하지 않는다.
  • legacy 커뮤니티 API 응답 스키마는 변경하지 않는다.
  • 팔로잉 뉴스의 COMMUNITY_POST news 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
    • 데이터 흐름: HomeRecommendationFacadeHomePopularCommunityRecommendationRecord를 변환한다.
  • CreatorChannelCommunityPostResponse in 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
    • 데이터 흐름: CreatorChannelHomeQueryServiceCreatorChannelCommunityQueryService.findHomeCommunityPosts(...)를 호출하고, 공지/커뮤니티 섹션이 같은 domain post를 사용한다.
  • CreatorChannelCommunityPostResponse in 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 / FollowingNewsResponse
    • FollowingNewsType.COMMUNITY_POSTtargetId는 있지만 게시글 카드 DTO가 아니며 likeCount도 제공하지 않는다.

7. User Stories

  • 사용자는 홈 추천의 인기 커뮤니티 게시글을 볼 때 내가 이미 좋아요를 눌렀는지 바로 알고 싶다.
  • 사용자는 크리에이터 채널 홈의 공지/커뮤니티 게시글 카드에서 좋아요 버튼이 현재 상태대로 표시되기를 원한다.
  • 사용자는 크리에이터 채널 커뮤니티 탭 목록에서 각 게시글의 좋아요 상태가 정확하게 표시되기를 원한다.
  • 앱 클라이언트는 게시글 목록 응답만으로 좋아요 버튼의 selected 상태를 렌더링하고 싶다.

8. Core Features

Feature A. 홈 인기 커뮤니티 게시글 좋아요 상태

Requirements

  • HomePopularCommunityPostItemisLiked: 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

  • 크리에이터 채널 홈의 CreatorChannelCommunityPostResponseisLiked: Boolean을 추가한다.
  • CreatorChannelCommunityPost domain에 조회자 좋아요 여부를 추가한다.
  • CreatorChannelCommunityPostRecord에 조회자 좋아요 여부를 추가한다.
  • DefaultCreatorChannelCommunityQueryRepository.findHomeCommunityPosts(...)는 기존 id 목록 기반 부가 조회 패턴을 유지하고, 조회자 좋아요 게시글 id 목록을 bulk 조회한다.
  • 공지(notices)와 일반 커뮤니티(communities) 모두 같은 isLiked 의미를 사용한다.

Edge Cases

  • 조회자가 게시글 작성자여도 본인이 활성 좋아요를 누른 이력이 없으면 isLiked=false다.
  • 유료 미구매로 이미지/오디오/본문이 마스킹되어도 좋아요 상태는 실제 조회자의 활성 좋아요 기준으로 내려준다.

Feature C. 크리에이터 채널 커뮤니티 탭 게시글 좋아요 상태

Requirements

  • 커뮤니티 탭의 CreatorChannelCommunityPostResponseisLiked: Boolean을 추가한다.
  • DefaultCreatorChannelCommunityQueryRepository.findCommunityPosts(...)도 홈 조회와 동일한 조회자 좋아요 상태 계산을 적용한다.
  • page/size와 무관하게 응답에 포함된 각 게시글의 isLiked가 정확해야 한다.

Edge Cases

  • 현재 page에 포함되지 않은 게시글의 좋아요 상태를 조회하거나 응답에 포함하지 않는다.
  • 좋아요가 없는 게시글은 isLiked=false다.

9. Technical Constraints

  • 기존 v2 패키지 경계를 유지한다.
  • 공개 API 응답 필드 추가 외에 기존 필드명과 의미를 변경하지 않는다.
  • 커뮤니티 좋아요 상태는 CreatorCommunityLikecreatorCommunityLike.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/recommendationspopularCommunityPosts[*].isLiked가 인증 회원 기준 활성 좋아요 여부를 반환한다.
  • GET /api/v2/home/recommendations를 비회원으로 호출하면 popularCommunityPosts[*].isLiked=false를 반환한다.
  • GET /api/v2/creator-channels/{creatorId}/homenotices[*].isLiked, communities[*].isLiked가 인증 조회자 기준 활성 좋아요 여부를 반환한다.
  • GET /api/v2/creator-channels/{creatorId}/communitycommunityPosts[*].isLiked가 인증 조회자 기준 활성 좋아요 여부를 반환한다.
  • 비활성 좋아요, 다른 회원의 좋아요, 좋아요 수와 조회자 좋아요 여부가 다른 케이스를 테스트로 구분한다.
  • 기존 좋아요 수, 댓글 수, 구매 여부, 유료 콘텐츠 마스킹, 성인 콘텐츠 필터 테스트가 계속 통과한다.

11. Open Questions

  • 없음. 필드명은 요청 의미와 기존 Boolean 응답 패턴을 기준으로 isLiked로 확정한다.