11 KiB
11 KiB
PRD: 현재 진행 중인 라이브 조회 API
1. Overview
메인 홈에서 현재 진행 중인 라이브 목록을 20개씩 페이징 조회하는 v2 API를 제공한다.
2. Problem
- 메인 홈 추천 탭 통합 API는 상단에 현재 진행 중인 라이브를 일부 내려주지만, 별도 목록 조회에 필요한 응답 필드가 부족하다.
- 기존
GET /api/v2/home/recommendations/lives는roomId,creatorNickname,creatorProfileImage만 내려주며 이번 요구사항의title,price,beginDateTimeUtc를 포함하지 않는다. - 기존 공개 API 스키마를 변경하면 클라이언트 회귀 영향이 생길 수 있으므로, 신규 API 계약을 별도로 명시해야 한다.
- 기존 v2 홈 추천/팔로잉 탭에는 현재 진행 중인 라이브 조회 조건과 API 조립 계층/도메인 조회 계층 분리 패턴이 있으므로 이를 우선 재활용해야 한다.
3. Goals
- 현재 진행 중인 라이브 목록 조회 API를
kr.co.vividnext.sodalive.v2하위에 제공한다. - 한 page당 20개씩 조회한다.
- 응답 item에는
roomId,creatorNickname,creatorProfileImage,title,price,beginDateTimeUtc를 포함한다. - 기존 패턴과 동일하게 클라이언트 공개 API 조립 계층과 도메인 조회 계층을 분리한다.
- 기존 메인 홈 추천 탭의 라이브 조회 조건을 최대한 재사용한다.
- 인증 회원만 조회할 수 있게 하고, 회원별 차단/성인 콘텐츠 노출 조건을 반영한다.
- 기존 공개 API 응답 스키마는 변경하지 않는다.
4. Non-Goals
- 기존
GET /api/v2/home/recommendations응답 스키마를 변경하지 않는다. - 기존
GET /api/v2/home/recommendations/lives응답 스키마를 변경하지 않는다. - 라이브 생성, 예약, 입장, 종료 API는 포함하지 않는다.
- 라이브 추천 산식, 스냅샷, 랭킹, 배너 정책은 변경하지 않는다.
- 앱 표시용 가격 단위, 다국어 문구, 날짜 포맷은 서버에서 처리하지 않는다.
- 20개 외 page size를 클라이언트가 지정하는 기능은 이번 범위에 포함하지 않는다.
5. Target Users
- 회원: 메인 홈에서 현재 진행 중인 라이브 목록을 더 탐색하는 사용자
- 앱 클라이언트: 현재 라이브 목록 화면 또는 추천 탭의 추가 로딩 화면을 구성하는 클라이언트
6. User Stories
- 사용자는 메인 홈에서 현재 진행 중인 라이브를 20개씩 추가로 보고 싶다.
- 사용자는 라이브 제목과 가격을 목록에서 바로 확인하고 싶다.
- 앱 클라이언트는 다음 page 존재 여부를 응답에서 확인해 무한 스크롤 또는 더보기 UI를 구성하고 싶다.
- 앱 클라이언트는 기존 추천 탭 상단 라이브와 동일한 노출 정책으로 별도 목록을 조회하고 싶다.
7. Core Features
Feature A. 현재 진행 중인 라이브 목록 API
Requirements
- 신규 API endpoint는
GET /api/v2/home/on-air-lives로 정의한다. - 응답 wrapper는 기존 패턴과 동일하게
ApiResponse.ok(...)를 사용한다. pagequery parameter를 받는다.page를 보내지 않으면 기본값0을 사용한다.page는 0부터 시작하는 page index로 처리한다.sizequery parameter는 받지 않고, page size는 항상 20으로 고정한다.- 다음 page 존재 여부는
size + 1개를 조회하거나 동등한 방식으로 판단한다. - 응답 목록에는 최대 20개만 내려준다.
- 인증 회원만 조회할 수 있다.
- 인증 회원 조회는 기존 v2 컨트롤러 패턴과 동일하게
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?를 사용한다. member == null이면 기존 인증 필요 API와 동일하게common.error.bad_credentials계열 오류를 반환한다.- 현재 진행 중인 라이브는 기존 홈 추천 라이브와 동일하게
live_room.is_active = true,channel_name is not null,channel_name <> ''조건을 기본으로 한다. - 방송자는
member.is_active = true인 대상만 노출한다. - 정렬은 기존 홈 추천 라이브와 동일하게
live_room.begin_date_time desc,live_room.id desc로 한다. - 양방향 차단 관계가 있는 크리에이터의 라이브는 제외한다.
- 성인 라이브 노출 여부는
MemberContentPreferenceService.canViewAdultContent(member)결과를 따른다. - 프로필 이미지는 기존 홈 추천/팔로잉 탭과 동일하게 CDN URL로 변환하고, 값이 없으면 기본 프로필 이미지 URL을 내려준다.
Edge Cases
- 조회 결과가 없으면
items = emptyList(),hasNext = false를 내려준다. - 비회원이 조회하면 목록을 내려주지 않고 인증 오류를 반환한다.
page가 0보다 작으면 기존 홈 추천 컨트롤러의normalizePage패턴과 동일하게 0으로 보정한다.- 매우 큰
page값은 기존 홈 추천 컨트롤러의MAX_PAGE = 10_000패턴과 동일하게 상한 보정한다. - 20개보다 적게 조회되면 가능한 개수만 내려주고 성공 처리한다.
- 라이브 제목이 빈 문자열이면 별도 fallback을 만들지 않고 저장된
LiveRoom.title값을 그대로 내려준다. - 라이브 가격은
LiveRoom.price값을 그대로 내려준다. - 라이브 시작 시간은
LiveRoom.beginDateTime을 기존 UTC ISO 문자열 변환 패턴으로 변환해beginDateTimeUtc로 내려준다.
Feature B. 계층 분리와 재사용 정책
Requirements
- 클라이언트 공개 API 조립 계층은
kr.co.vividnext.sodalive.v2.api.home.live하위에 둔다. - API 조립 계층 후보 파일은 다음과 같다.
src/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/live/adapter/in/web/HomeOnAirLiveController.ktsrc/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/live/application/HomeOnAirLiveFacade.ktsrc/main/kotlin/kr/co/vividnext/sodalive/v2/api/home/live/dto/HomeOnAirLiveResponse.kt
- 도메인 조회 계층은 기존
kr.co.vividnext.sodalive.v2.recommendation.application.HomeRecommendationQueryService와HomeRecommendationQueryPort.findLiveRecommendations(...)확장 재사용을 기본안으로 한다. - 기존
HomeLiveRecommendationRecord에title,price,beginDateTime을 추가해 신규 API DTO로 조립할 수 있게 한다. - 기존
HomeLiveItem은 기존 필드만 매핑해 기존 추천 탭 공개 응답 스키마를 유지한다. - 기존
DefaultHomeRecommendationQueryRepository.findLiveRecommendations(...)의 조회 조건과 정렬을 유지하되liveRoom.title,liveRoom.price,liveRoom.beginDateTimeselect를 추가한다. - API 조립 계층은 도메인 조회 결과를 공개 응답 DTO로 변환하고, CDN URL 변환/기본 프로필 이미지 정책은 기존 홈 추천 패턴을 따른다.
Edge Cases
HomeRecommendationQueryService확장으로 추천 도메인 결합이 과도하다고 판단되면 구현 계획 단계에서kr.co.vividnext.sodalive.v2.home.live하위 전용 query service/port/repository를 만들 수 있다. 이 경우에도 기존 조회 조건, 정렬, 테스트 케이스는 동일하게 유지한다.- 기존 record 확장 시 생성자 projection 순서와 모든 매핑 호출부를 함께 수정해야 한다.
Feature C. Response 스키마
Requirements
- 응답 최상위 DTO 이름은
HomeOnAirLivePageResponse를 기본안으로 한다. - 응답 item DTO 이름은
HomeOnAirLiveResponse를 기본안으로 한다. - 응답 item은 다음 값을 포함한다.
roomId: 라이브 방 idcreatorNickname: 방송자 닉네임creatorProfileImage: 방송자 프로필 이미지 CDN URLtitle: 라이브 제목price: 라이브 입장 가격beginDateTimeUtc: 라이브 시작 시간 UTC ISO 문자열
- page metadata는 기존
HomeRecommendationPageResponse와 동일한 의미로page,size,hasNext를 포함한다. size는 항상20으로 내려준다.
Edge Cases
creatorProfileImage원본 값이 없으면 기본 프로필 이미지 CDN URL을 내려준다.price가 무료이면0을 내려준다.beginDateTimeUtc는LiveRoom.beginDateTime을 UTC ISO 문자열로 변환한 값으로 내려준다.
8. API Endpoint
GET /api/v2/home/on-air-lives?page=0
Authorization: Bearer {accessToken}
page: 선택값, 기본값0, 0부터 시작하는 page indexsize: 받지 않음, 서버에서 20으로 고정SecurityConfig에GET /api/v2/home/on-air-livesauthenticated 설정을 추가한다.- 회원 token이 없거나 anonymous이면 기존 인증 필요 API와 동일하게 인증 오류를 반환한다.
- 인증 회원 기준으로 차단/성인 콘텐츠 노출 조건을 반영한다.
9. Response Data Class
data class HomeOnAirLivePageResponse(
val items: List<HomeOnAirLiveResponse>,
val page: Int,
val size: Int,
val hasNext: Boolean
)
data class HomeOnAirLiveResponse(
val roomId: Long,
val creatorNickname: String,
val creatorProfileImage: String,
val title: String,
val price: Int,
val beginDateTimeUtc: String
)
10. Technical Constraints
- Kotlin, Spring Boot 2.7.14, Java 17, Gradle Wrapper 구조를 유지한다.
- 신규 코드는 기존 v2 패키지 구조와 네이밍을 따른다.
- 공개 API 조립 계층은
kr.co.vividnext.sodalive.v2.api.*하위에 두고, 재사용 가능한 조회 책임은 API 패키지 밖 도메인 조회 계층에 둔다. - 기존
ApiResponse.ok(...)응답 wrapper를 사용한다. - QueryDSL 기반 조회 패턴을 유지한다.
- 공개 API 스키마 변경은 신규 endpoint에만 한정한다.
- 구현 계획 단계에서는 TDD 기준으로 controller/facade/query repository 테스트를 작성한 뒤 최소 구현한다.
11. Reuse Candidates
HomeRecommendationController: page 정규화,ApiResponse.ok(...),requireMember(...)인증 필수 패턴 참고HomeRecommendationFacade:size + 1조회 후hasNext를 판단하는 page 응답 조립 패턴 참고HomeRecommendationPageResponse: page metadata 의미 참고HomeRecommendationQueryService.findLiveRecommendations(...): 현재 진행 중인 라이브 도메인 조회 진입점으로 확장 재사용HomeRecommendationQueryPort.HomeLiveRecommendationRecord:title,price,beginDateTime을 추가해 신규 API 응답 조립에 재사용DefaultHomeRecommendationQueryRepository.findLiveRecommendations(...): 진행 중 라이브 조건, 정렬, 차단 필터, 성인 라이브 필터 재사용HomeFollowingLive/DefaultHomeFollowingQueryRepository.findOnAirLives(...):title포함 라이브 응답 모델링과 CDN URL 변환 패턴 참고LiveRoom:title,price,beginDateTime,channelName,isAdult,isActive필드 사용MemberContentPreferenceService.canViewAdultContent(member): 성인 라이브 노출 가능 여부 판단
12. Open Questions
- 없음. 현재 PRD는 인증 회원만 조회 가능, page size 20 고정, 기존 추천 라이브 조건 재사용을 기본 가정으로 작성한다.