6.9 KiB
6.9 KiB
오디오 콘텐츠 배너 예약 기간 PRD
문서 정보
| 항목 | 내용 |
|---|---|
| 문서 상태 | 구현 완료 |
| 작성일 | 2026-10-27 |
| 최종 수정일 | 2026-10-27 |
| 대상 제품 | 관리자 오디오 콘텐츠 배너 예약 노출 |
| 작성자·결정권자 | 제품 승인 요구사항 |
| 관련 API Contract | 관리자 예약 필드 추가, 기존 공개 response 유지, 본 문서 §7 |
| 관련 구현 계획 | docs/20261027_콘텐츠배너예약기간/plan-task.md |
| 관련 review | reviews/admin-reservation-review.md, reviews/banner-reservation-final-review.md |
1. Overview
관리자는 오디오 콘텐츠 배너에 선택적인 노출 시작·종료 시각을 설정한다. 공개 배너 조회는 현재 시각이 해당 기간에 포함될 때만 배너를 반환하고, 기존 배너는 NULL 기간으로 계속 노출한다.
2. Problem Statement
현재 배너는 노출 시작과 종료 시점을 관리할 수 없어서 기간성 콘텐츠를 수동으로 활성화·비활성화해야 한다. 기간이 지나도 공개 조회에서 배너가 선택될 수 있다.
3. Goals
- 관리자가 예약 기간을 생성·조회·수정·해제할 수 있다.
- 공개 오디오 배너 조회 네 경로가 동일한 기간 조건을 적용하고 기존 필터·정렬·limit 동작을 보존한다.
- 기존 레코드의 동작과 공개 응답 스키마를 유지한다.
4. Non-Goals
- 오디오 이외 배너 유형, 예약 실행 scheduler, 활성 상태 자동 변경은 범위 밖이다.
- 공개 API 응답 필드, 권한·인증, 공통 시간대 설정 및 dependency 변경은 하지 않는다.
- 운영 DB에 DDL을 자동 실행하지 않는다.
5. 사용자 및 권한
- 사용자는 기존 관리자 배너 API의 기존 권한으로 생성·조회·수정한다. 권한 범위는 변경하지 않는다.
- 공개 조회 권한과 성인·언어·탭·비활성·차단 대상 필터는 기존 계약을 유지한다.
6. 핵심 흐름
- 관리자가 생성 요청에 선택적 예약 시각을 입력한다.
- 관리자가 목록에서 저장된 두 시각을 확인한다. 예약 여부로 관리자 목록 행을 숨기지 않는다.
- 관리자가 수정을 생략하면 기존 값을 유지하고, 해당 필드를 JSON
null로 보내면 그 경계만 해제한다. - 공개 조회는 예약 기간 안에 있는 활성 배너만 기존 조건에 따라 반환한다.
7. 확정 기능 요구사항 및 계약
| ID | 상태 | 요구사항 및 수용 기준 | 계약/Goal |
|---|---|---|---|
| SCH-001 | 확정 | startDate, endDate는 nullable 시각이다. 둘 다 NULL이면 항상 노출, 시작만 있으면 startDate <= now, 종료만 있으면 now <= endDate, 둘 다 있으면 startDate <= now <= endDate이다. |
P1-T1, P1-T2 |
| SCH-002 | 확정 | 관리자 생성 입력의 두 필드는 optional이다. 관리자 목록은 두 값을 반환하되 기간으로 행을 필터링하지 않으며 기존 isActive 및 tab 조건을 유지한다. |
P1-T1 |
| SCH-003 | 확정 | 관리자 수정은 생략한 경계를 유지하고, 명시적 JSON null은 해당 값을 해제한다. effective start가 end보다 늦으면 common.error.invalid_request로 거부한다. 형식 오류도 같은 공통 오류를 사용하며, 검증은 이미지 업로드 전에 끝난다. |
P1-T1 |
| SCH-004 | 확정 | 관리자 입력 형식은 기존 이벤트 입력 관례인 KST 문자열 yyyy-MM-dd HH:mm, 저장은 UTC다. 끝 시각은 입력 분의 :59까지 포함한다. 응답 시각은 KST 동일 형식이다. 이는 기존 관리자 이벤트 관례를 적용한 구현 결정이며 사용자 지정 초 형식은 아니다. |
P1-T1 |
| SCH-005 | 확정 | DB는 두 컬럼을 MySQL TIMESTAMP NULL DEFAULT NULL 초 정밀도로 추가하고 모든 컬럼에 설명 COMMENT를 둔다. 기존 데이터는 NULL 유지, backfill 없음. DDL은 문서로 제공하며 적용이 앱 rollout보다 먼저다. 운영 DB 자동 실행 금지. |
P1-T1, Gate |
| SCH-006 | 확정 | 공개 경로 네 곳 모두 기간 필터를 DB 조회에 적용해 limit 전에 제외한다. 기존 조건과 정렬을 보존한다. | P1-T2 |
| SCH-007 | 확정 | 공개 응답 schema·권한·security는 그대로 유지한다. | 전체 |
관리자 수정에서 JSON 필드 생략과 명시적 null을 구분하기 위해 raw JSON의 presence만 감지한다. 신규 dependency는 추가하지 않는다.
공개 조회 경로는 AudioContentQueryRepositoryImpl.getAudioContentMainBannerList(isAdult), AudioContentBannerQueryRepositoryImpl.getAudioContentMainBannerList(tabId, isAdult, lang), DefaultHomeRecommendationQueryRepository.findHomeBanners(limit, memberId, includeAdultBanners, lang), DefaultAudioRecommendationQueryRepository.findBanners(limit, memberId, canViewAdultContent, lang)이다. 각 경로에 이미 적용된 활성·탭·언어·성인·대상 소유자/차단 조건과 기존 정렬을 보존한다.
8. 데이터·오류·시각
- 입력 필드명은 사용자 요청대로
startDate,endDate; 값은yyyy-MM-dd HH:mm문자열 또는 null이다. 응답은 nullable 문자열이다. - 형식 오류 및 기간 역전은 기존
common.error.invalid_request로 응답한다. - DDL 소수초 미지정
TIMESTAMP의 초 정밀도에 맞춰 초 단위 단일 값으로 저장·응답한다. 공개 조회의 현재 UTC 시각도 초 단위로 비교해 종료 분의 마지막 초 전체를 포함한다. 테스트는 고정 UTC 현재 시각 seam을 사용하고 실제 DB 저장 후flush/clear/재조회로 왕복을 확인한다. H2 검증 컬럼은TIMESTAMP(0)로 운영 DDL의 정밀도를 재현한다.
9. 성공 기준과 추적
- 관리자 create/update/list에서 선택적 기간, 생략 유지와 명시적 null 해제를 검증한다. (
SCH-002~005,P1-T1) - 잘못된 입력과 역전 기간이 업로드 전 공통 오류로 거부된다. (
SCH-003,P1-T1,P1-T1-R1) - 네 공개 경로가 경계 시각 포함 여부를 판정하고 예약 외 레코드를 limit 전에 제외한다. (
SCH-001,SCH-006,P1-T2) - 기존 공개 필터·정렬, 관리자 isActive/tab 필터, 공개 응답 schema가 보존된다. (
SCH-002,SCH-006~007, Gate) - DDL과 앱 배포 순서를 문서화하고 자동 운영 DB 적용이 없다. (
SCH-005, Gate)
10. 제외 항목 및 결정 기록
- 제외: 다른 banner type, scheduler, 공개 response 변경, 자동 isActive 전환, 신규 dependency, global time 설정, live DB 실행.
- 2026-10-27, DEC-001, 확정: 이벤트 관리자의 기존 KST 분 단위 입력/응답 관례를 적용하고 종료 분을
:59까지 포함한다. 요구사항은 timestamp 예약을 지정했으며 seconds format을 지정하지 않았으므로 기존 관리자 관례를 따른다. - 2026-10-27, DEC-002, 확정: 기간 필터는 공개 네 조회에만 적용한다. 관리자 목록은 예약과 무관하게 기존 활성/tab 정책을 유지한다.