docs(creator-channel): 커뮤니티 탭 Phase 1 기록을 갱신한다
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
- 커뮤니티 게시글 조회 로직은 홈 화면과 커뮤니티 탭에서 모두 쓰일 수 있으므로, 하나의 커뮤니티 조회 도메인으로 분리되어야 한다.
|
||||
- 조회자의 성인 콘텐츠 노출 정책이 false이면 19금 커뮤니티 게시글은 전체 개수와 목록에서 모두 제외되어야 한다.
|
||||
- legacy `/creator-community` 목록 조회는 구매 내역 조건과 성인 필터 조건이 섞일 수 있으므로, `isAdult=false` 조회에서 구매한 19금 게시글이 개수나 목록에 포함되지 않도록 새 v2 조회 정책에서 명확히 보장해야 한다.
|
||||
- legacy 커뮤니티 목록은 유료 게시글을 구매하지 않은 조회자에게도 게시글 이미지를 노출했지만, 커뮤니티 탭 API는 유료 미구매 게시글의 이미지도 오디오와 동일하게 `null`로 내려줘야 한다.
|
||||
|
||||
---
|
||||
|
||||
@@ -18,12 +19,12 @@
|
||||
- 크리에이터 채널 커뮤니티 탭 조회 API를 제공한다.
|
||||
- API endpoint는 `GET /api/v2/creator-channels/{creatorId}/community`로 한다.
|
||||
- 클라이언트에서 호출하는 공개 API controller/facade/response DTO는 `kr.co.vividnext.sodalive.v2.api.creator.channel.community` 하위 조립 계층에 둔다.
|
||||
- 커뮤니티 게시글 목록, 전체 개수, 구매 여부, 좋아요 수, 댓글 수, 성인 콘텐츠 노출, 유료 오디오 접근 정책은 API 패키지 밖 커뮤니티 도메인 패키지에 둔다.
|
||||
- 커뮤니티 게시글 목록, 전체 개수, 구매 여부, 좋아요 수, 댓글 수, 성인 콘텐츠 노출, 유료 이미지/오디오 접근 정책은 API 패키지 밖 커뮤니티 도메인 패키지에 둔다.
|
||||
- 크리에이터 채널 홈 API와 커뮤니티 탭 API는 동일한 커뮤니티 조회 도메인을 사용한다.
|
||||
- 응답에는 조회 가능한 커뮤니티 게시글 전체 개수, 게시글 목록, page, size, hasNext를 포함한다.
|
||||
- 게시글 목록 item에는 게시글 id, 크리에이터 id, 크리에이터 닉네임, 작성 시간 UTC, 게시글 본문, 이미지 URL, 오디오 URL, 가격, 댓글 쓰기 가능 여부, 좋아요 개수, 댓글 개수, pin 여부를 포함한다.
|
||||
- 유료 게시글의 오디오 콘텐츠는 조회자가 구매했거나 게시글 작성자인 경우에만 signed URL로 내려준다.
|
||||
- 유료 게시글을 구매하지 않은 조회자에게는 오디오 콘텐츠 URL을 `null`로 내려준다.
|
||||
- 게시글 목록 item에는 게시글 id, 크리에이터 id, 크리에이터 닉네임, 크리에이터 프로필 이미지 URL, 작성 시간 UTC, 게시글 본문, 이미지 URL, 오디오 URL, 가격, 댓글 쓰기 가능 여부, 구매 여부, 좋아요 개수, 댓글 개수, pin 여부를 포함한다.
|
||||
- 유료 게시글의 이미지와 오디오 콘텐츠는 조회자가 구매했거나 게시글 작성자인 경우에만 내려준다.
|
||||
- 유료 게시글을 구매하지 않은 조회자에게는 이미지 URL과 오디오 콘텐츠 URL을 `null`로 내려준다.
|
||||
- 이미지가 없는 게시글은 `imageUrl`을 `null`로 내려준다.
|
||||
- 조회자의 성인 콘텐츠 노출 정책이 false이면 19금 게시글은 전체 개수와 목록에서 제외한다.
|
||||
- 페이징 요청값은 기존 오디오/시리즈 탭 API와 같은 보정 규칙을 따른다.
|
||||
@@ -56,8 +57,8 @@
|
||||
- 성인 콘텐츠 노출이 꺼진 사용자는 19금 게시글이 개수와 목록에 포함되지 않기를 원한다.
|
||||
- 사용자는 이미지가 없는 게시글도 정상적으로 목록에서 확인하고 싶다.
|
||||
- 사용자는 구매한 유료 게시글의 오디오 콘텐츠를 재생할 수 있어야 한다.
|
||||
- 구매하지 않은 사용자는 유료 게시글의 오디오 콘텐츠 URL을 받지 않아야 한다.
|
||||
- 앱 클라이언트는 댓글 작성 가능 여부, 좋아요 개수, 댓글 개수, pin 여부를 게시글 item에서 바로 확인하고 싶다.
|
||||
- 구매하지 않은 사용자는 유료 게시글의 이미지 URL과 오디오 콘텐츠 URL을 받지 않아야 한다.
|
||||
- 앱 클라이언트는 크리에이터 프로필 이미지, 댓글 작성 가능 여부, 구매 여부, 좋아요 개수, 댓글 개수, pin 여부를 게시글 item에서 바로 확인하고 싶다.
|
||||
- 서버 개발자는 홈 API와 커뮤니티 탭 API가 동일한 커뮤니티 조회 도메인을 사용한다는 것을 패키지 의존 방향으로 확인하고 싶다.
|
||||
|
||||
---
|
||||
@@ -121,6 +122,7 @@ data class CreatorChannelCommunityPostResponse(
|
||||
val postId: Long,
|
||||
val creatorId: Long,
|
||||
val creatorNickname: String,
|
||||
val creatorProfileUrl: String,
|
||||
val createdAtUtc: String,
|
||||
val content: String,
|
||||
val imageUrl: String?,
|
||||
@@ -128,6 +130,7 @@ data class CreatorChannelCommunityPostResponse(
|
||||
val price: Int,
|
||||
@JsonProperty("isCommentAvailable")
|
||||
val isCommentAvailable: Boolean,
|
||||
val existOrdered: Boolean,
|
||||
val likeCount: Int,
|
||||
val commentCount: Int,
|
||||
@JsonProperty("isPinned")
|
||||
@@ -138,6 +141,7 @@ data class CreatorChannelCommunityPostResponse(
|
||||
#### Edge Cases
|
||||
- 조회 가능한 커뮤니티 게시글이 없으면 `communityPostCount`는 `0`, `communityPosts`는 빈 배열, `hasNext`는 `false`로 내려준다.
|
||||
- 이미지가 없는 게시글은 `imageUrl`을 `null`로 내려준다.
|
||||
- 유료 게시글을 구매하지 않았고 게시글 작성자도 아닌 조회자에게는 이미지가 있는 게시글이어도 `imageUrl`을 `null`로 내려준다.
|
||||
- 오디오가 없는 게시글은 `audioUrl`을 `null`로 내려준다.
|
||||
- `isCommentAvailable == false`인 게시글의 `commentCount`는 기존 커뮤니티 목록 정책과 동일하게 `0`으로 내려준다.
|
||||
- Boolean 응답 필드는 Jackson 직렬화 시 `commentAvailable`, `pinned`로 바뀌지 않고 `isCommentAvailable`, `isPinned`로 내려가야 한다.
|
||||
@@ -157,7 +161,9 @@ data class CreatorChannelCommunityPostResponse(
|
||||
- 목록은 `page`, `size` 기준으로 페이징 조회한다.
|
||||
- 다음 page 존재 여부는 `size + 1`개를 조회하거나 동등한 방식으로 판단하되, 응답 목록에는 최대 `size`개만 내려준다.
|
||||
- `createdAtUtc`는 게시글 생성 시간을 UTC 기준 ISO-8601 문자열로 내려준다.
|
||||
- `imageUrl`은 커뮤니티 게시글 이미지 path가 있으면 기존 CDN URL 조합 정책으로 내려준다.
|
||||
- `creatorProfileUrl`은 크리에이터 프로필 이미지 path가 있으면 기존 CDN URL 조합 정책으로 내려주고, 없으면 기본 프로필 이미지 URL을 내려준다.
|
||||
- `existOrdered`는 조회자가 게시글 작성자이면 `true`, 조회자가 유효 구매 내역을 가지고 있으면 `true`, 그 외에는 `false`로 내려준다.
|
||||
- `imageUrl`은 커뮤니티 게시글 이미지 path가 있고 조회자가 해당 게시글의 유료 미디어에 접근할 수 있을 때만 기존 CDN URL 조합 정책으로 내려준다.
|
||||
- `likeCount`는 활성 좋아요 수를 기준으로 계산한다.
|
||||
- `commentCount`는 조회자가 볼 수 있는 활성 최상위 댓글 수를 기준으로 계산한다.
|
||||
- 댓글 수 계산에는 기존 커뮤니티 댓글의 차단 관계와 비밀 댓글 노출 정책을 적용한다.
|
||||
@@ -168,24 +174,32 @@ data class CreatorChannelCommunityPostResponse(
|
||||
- 게시글 작성자가 조회자인 경우에도 성인 콘텐츠 노출 정책이 false이면 19금 게시글은 제외한다.
|
||||
- 좋아요나 댓글이 없는 게시글은 `likeCount`, `commentCount`를 `0`으로 내려준다.
|
||||
|
||||
### Feature D. 유료 오디오 콘텐츠 접근 정책
|
||||
### Feature D. 유료 이미지와 오디오 콘텐츠 접근 정책
|
||||
|
||||
#### Requirements
|
||||
- 커뮤니티 게시글에 이미지 path가 없으면 `imageUrl`은 `null`이다.
|
||||
- 커뮤니티 게시글에 오디오 path가 없으면 `audioUrl`은 `null`이다.
|
||||
- 무료 게시글에 이미지 path가 있으면 CDN URL을 내려준다.
|
||||
- 무료 게시글에 오디오 path가 있으면 signed URL을 내려준다.
|
||||
- 유료 게시글에 이미지 path가 있고 조회자가 해당 게시글을 구매했으면 CDN URL을 내려준다.
|
||||
- 유료 게시글에 오디오 path가 있고 조회자가 해당 게시글을 구매했으면 signed URL을 내려준다.
|
||||
- 유료 게시글에 이미지 path가 있고 조회자가 게시글 작성자이면 CDN URL을 내려준다.
|
||||
- 유료 게시글에 오디오 path가 있고 조회자가 게시글 작성자이면 signed URL을 내려준다.
|
||||
- 유료 게시글에 이미지 path가 있지만 조회자가 구매하지 않았고 게시글 작성자도 아니면 `imageUrl`은 `null`이다.
|
||||
- 유료 게시글에 오디오 path가 있지만 조회자가 구매하지 않았고 게시글 작성자도 아니면 `audioUrl`은 `null`이다.
|
||||
- signed URL 생성은 기존 `AudioContentCloudFront.generateSignedURL` 방식을 재사용한다.
|
||||
- signed URL 만료 시간은 legacy 커뮤니티 목록 정책과 동일하게 30분을 기본으로 한다.
|
||||
- 이 이미지 제한 정책은 legacy `/creator-community` 목록의 기존 이미지 노출 동작과 다르며, 커뮤니티 탭 API에서는 오디오 접근 정책과 동일하게 적용한다.
|
||||
- 이미지 URL은 signed URL로 만들지 않고 기존 CDN URL 조합 정책만 사용한다.
|
||||
- 오디오 signed URL 생성은 기존 `AudioContentCloudFront.generateSignedURL` 방식을 재사용한다.
|
||||
- 오디오 signed URL 만료 시간은 legacy 커뮤니티 목록 정책과 동일하게 30분을 기본으로 한다.
|
||||
- 유료 게시글 본문은 기존 크리에이터 채널 홈 API의 유료 커뮤니티 본문 마스킹 정책을 따른다.
|
||||
- 유료 게시글 오디오 접근 여부는 `CanUsage.PAID_COMMUNITY_POST`의 유효 구매 내역을 기준으로 판단한다.
|
||||
- 유료 게시글 이미지/오디오 접근 여부는 `CanUsage.PAID_COMMUNITY_POST`의 유효 구매 내역을 기준으로 판단한다.
|
||||
- 환불된 구매 내역은 접근 가능 구매로 보지 않는다.
|
||||
|
||||
#### Edge Cases
|
||||
- 조회자가 구매했더라도 성인 콘텐츠 노출 정책이 false인 19금 게시글은 목록에 포함되지 않으므로 signed URL도 내려주지 않는다.
|
||||
- 조회자가 구매했더라도 성인 콘텐츠 노출 정책이 false인 19금 게시글은 목록에 포함되지 않으므로 이미지 URL과 오디오 signed URL도 내려주지 않는다.
|
||||
- 구매 내역이 중복으로 있어도 응답 item은 게시글 1개로 중복 없이 내려준다.
|
||||
- signed URL 생성 대상 path가 blank이면 `audioUrl`은 `null`로 내려준다.
|
||||
- 이미지 path가 blank이면 `imageUrl`은 `null`로 내려준다.
|
||||
- 오디오 signed URL 생성 대상 path가 blank이면 `audioUrl`은 `null`로 내려준다.
|
||||
|
||||
### Feature E. 커뮤니티 조회 도메인 분리
|
||||
|
||||
@@ -220,6 +234,7 @@ data class CreatorChannelCommunityPostResponse(
|
||||
- 페이징 응답은 기존 오디오/시리즈 탭 API와 같은 `page`, `size`, `hasNext` 패턴을 따른다.
|
||||
- 이미지 URL은 기존 `String?.toCdnUrl(cloudFrontHost)` 방식과 같은 CDN URL 조합 정책을 따른다.
|
||||
- 오디오 URL은 콘텐츠 CloudFront signed URL 생성 정책을 따른다.
|
||||
- `createdAtUtc` 변환은 기존에 재사용 가능한 `toUtcIso` 확장함수가 있으면 신규 private 확장함수를 만들지 않고 기존 확장함수를 사용한다.
|
||||
- 날짜 응답은 UTC 기준 ISO-8601 문자열로 내려준다.
|
||||
|
||||
---
|
||||
@@ -229,7 +244,7 @@ data class CreatorChannelCommunityPostResponse(
|
||||
- 커뮤니티 탭 API 응답 시간
|
||||
- 커뮤니티 탭 추가 로딩 요청 건수
|
||||
- 성인 콘텐츠 노출 정책이 false인 조회에서 19금 게시글이 개수와 목록에 포함되지 않는 테스트 통과 여부
|
||||
- 유료 오디오 콘텐츠 signed URL/null 처리 테스트 통과 여부
|
||||
- 유료 게시글 이미지 CDN URL/null 처리와 오디오 signed URL/null 처리 테스트 통과 여부
|
||||
- 홈 API 커뮤니티 요약 조회 회귀 테스트 통과 여부
|
||||
- `v2.creator.channel.community` 도메인 패키지의 `v2.api.*` import 검색 결과 0건 여부
|
||||
|
||||
|
||||
Reference in New Issue
Block a user