본문으로 건너뛰기

홈 화면 정책 문서

(2026년 3월 11일 updated)

1. 문서 개요

  • 목적: 홈 화면의 콘텐츠 노출 방식 및 동작 원칙 정의
  • 적용 화면: 앱 내 첫 진입 시 메인 홈 화면
  • 대상: 기획, 운영, 개발, QA 등 관련 부서

2. 콘텐츠 노출 정책

  • 홈 화면은 운영 큐레이션 중심으로 구성되며, 운영자가 지정한 섹션/콘텐츠 순서에 따라 노출
  • 콘텐츠 수급 방식: 수동 등록(CMS)
  • 섹션 내 콘텐츠가 부족할 경우:
    • 5개 이하일 경우 해당 섹션 비노출 처리
    • 콘텐츠 없음 → 섹션 자체 미노출

2.1 종합 홈 API

홈 화면 진입 시 단일 API를 통해 배너, 필터, 랭킹, 큐레이션 등 전체 데이터를 한번에 조회할 수 있다.

항목내용
엔드포인트GET /api/home/
ComprehensiveHomeView
설명홈 화면에 필요한 모든 섹션 데이터를 종합적으로 반환
인증선택 (비로그인 시에도 기본 데이터 제공)

3. 필터 동작 정책

3.1 필터 모델 (HomeFilter)

홈 화면 필터는 HomeFilter 모델(TranslatableModel)을 기반으로 관리된다.

필드타입설명
filter_typeCharField필터 유형: tab, series, reading_level
nameTranslatedField다국어 필터 명칭
valueCharFieldAPI 쿼리에 사용되는 필터 값
codeCharField (unique)클라이언트 측 필터링용 고유 코드
display_orderIntegerField노출 순서
is_activeBooleanField활성화 여부

3.2 필터 유형 및 코드 체계

filter_type설명code 예시
tab브랜드 탭 (디즈니/픽사)TAB_DISNEY, TAB_PIXAR
series시리즈(프랜차이즈) 필터시리즈별 고유 코드
reading_level읽기 단계 필터 (연령대, 렉사일)AGE_0_3, AGE_4_7, AGE_8_10, AGE_FAMILY, LEX_BR_200, LEX_200_500

3.3 필터 API

항목내용
엔드포인트GET /api/home/filters/
설명활성화된 모든 홈 필터 목록 조회
정렬filter_typedisplay_orderid

3.4 필터 동작 방식

  • 필터 종류:

    • 탭: 디즈니 / 픽사
    • 풀스크린 셀렉터 1: 시리즈 (프랜차이즈)
    • 풀스크린 셀렉터 2: 읽기 단계 (연령, 렉사일 지수)
  • 동작 방식:

    • 모든 필터는 AND 연산 (모든 조건을 만족하는 콘텐츠만 노출)
    • 필터 조작 시 즉시 반영됨 (Apply 버튼 없음)
    • 조합 결과가 0개일 경우 → "검색 결과가 없습니다" 안내
  • 초기 진입 시 기본값: 전체 노출 (필터 선택 없음)

  • 기준 메타데이터:

    • 운영에서 제공 > 드라이브 내 스프레드 시트 참조
  • 섹션 적용 여부: 모든 큐레이션 섹션에 필터 조건 적용됨

  • 연령 범위:

    • 0-3세 / 4-7세 / 8-10세 / 온가족
  • 렉사일 범위:

    • BR-200L / 200L-500L / 470L-620L / 590L-790L / 695L-910L

4. 배너 정책

4.1 배너 모델 (Banner)

배너는 Banner 모델(TranslatableModel)을 통해 관리되며, 다국어를 지원한다.

필드타입설명
titleTranslatedField다국어 배너 제목
image_urlTranslatedField (URL)다국어 배너 이미지 URL (CDN 또는 업로드)
link_urlTranslatedField (URL)다국어 링크 URL
target_typeTranslatedField언어별 콘텐츠 타입 (book, collection)
content_idTranslatedField (BigInteger)언어별 Book ID
curation_idTranslatedField (BigInteger)언어별 Curation ID
link_typeCharField링크 유형: book / external / none / collection
content_typeCharField콘텐츠 유형: book / event / collection
sequenceIntegerField노출 순서
is_activeBooleanField활성화 여부
start_dateDateTimeField배너 노출 시작일
end_dateDateTimeField (nullable)배너 노출 종료일

4.2 배너 API

항목내용
엔드포인트GET /api/home/banners/
설명현재 활성화된 배너 목록 조회
정렬sequence
노출 조건is_active=True 이며, 현재 시각이 start_date ~ end_date 범위 내

4.3 배너 클릭 시 동작

link_type동작
bookcontent_id에 해당하는 도서 상세로 이동
collectioncuration_id에 해당하는 큐레이션 모아보기로 이동
externallink_url 외부 브라우저 또는 인앱 브라우저로 이동
none클릭 불가 (정보형 배너)

5. 테마 큐레이션 정책

5.1 큐레이션 모델 (Curation)

큐레이션은 Curation 모델(TranslatableModel)을 통해 관리된다.

필드타입설명
titleTranslatedField다국어 큐레이션 제목
descriptionTranslatedField다국어 큐레이션 설명
curation_typeCharField큐레이션 유형: theme (테마) / collection (모아보기)
booksM2M (through CurationItem)큐레이션에 포함된 도서 목록
display_orderIntegerField노출 순서
is_activeBooleanField활성화 여부

5.2 큐레이션 아이템 (CurationItem)

필드타입설명
curationForeignKey소속 큐레이션
bookForeignKey도서
display_orderIntegerField아이템 노출 순서 (기본값: 999)

5.3 큐레이션 API

항목내용
개별 조회GET /api/home/curations/<id>/
설명특정 큐레이션의 상세 정보 및 포함 도서 목록 조회

5.4 섹션 노출 방식

  • 노출 방식:

    • 가로 스크롤 카드 UI (무한 루프) / 갯수 제한 없음
    • 카드 수 5개 이하인 경우 메인 미노출 (단, 필터가 걸린 경우에는 카드수 1개도 노출. 0개일 때만 미노출)
  • 테마 예시:

    • 애니를 읽자!
    • 생활 속에서 배워요
    • 모험
    • 자연 놀이
    • 걸파워
    • 우정은 나의 힘
    • 신비한 마법 이야기
    • 따듯한 감동
    • 가족 이야기
    • 오늘 밤은 어떤 책?
    • 마음이 자라는 시간
    • 가을 이야기
  • 콘텐츠 선정 기준:

    • theme_tag 기반 또는 수동 선택 가능
    • 중복 도서 제거 여부는 운영에서 수동 설정
  • 정렬 기준: PV 점수 기반

    PV 기준

    • PV 1회 = 1점
    • 집계 기준: UTC+9 기준 매일 00시부터 1일 1회 집계
    • PV 점수 기준으로 정렬
    • 동일 점수일 경우: 최신 콘텐츠 우선
  • 운영 제어 항목:

    • 섹션명 수정 / 도서 순서 조정 / 특정 도서 제외
  • 카드 클릭 시: 해당 도서 상세(홈) 이동

  • 필터 조건은 필터 동작 정책에 따라 적용됩니다.


6. 캐릭터 친구들 정책

  • 진입 기준: character_tag 기반

  • 정렬: 기본 ABC 순, 운영 수동 설정 가능

  • 도서 수 부족 시: 1개 미만 → 캐릭터 미노출

  • 2단계 화면: 카드 그리드 뷰, 제한 없이 스크롤 가능

  • API: GET /api/home/characters/

  • 2단계 화면 정렬 기준: PV 점수 기반

    PV 기준

    • PV 1회 = 1점
    • 집계 기준: UTC+9 기준 매일 00시부터 1일 1회 집계
    • PV 점수 기준으로 정렬
    • 동일 점수일 경우: 최신 콘텐츠 우선

7. 실시간 Top10 랭킹 정책

(2026년 4월 20일 updated)

7.1 랭킹 모델 (RealtimeRanking)

실시간 랭킹은 RealtimeRanking 모델을 통해 앱 언어별 / 시간별로 관리된다.

필드타입설명
bookForeignKey랭킹 대상 도서
language_codeCharField(5)앱 언어 코드 (ko, en, jp, es)
rankIntegerField (1~50)순위
previous_rankIntegerField (1~50, nullable)이전 시간대 순위
scoreFloatField다중 시그널 합산 점수
ranking_dateDateField랭킹 날짜
ranking_hourIntegerField랭킹 시간대 (0~23)

유니크: (book, language_code, ranking_date, ranking_hour) 저장 깊이: TOP_N = 50 (API는 상위 10개만 노출하지만 데이터는 50까지 저장 — 향후 기능 확장 여지)

7.2 순위 변동 표시 (rank_change)

조건설명
newprevious_rank가 null신규 진입
up현재 순위 < 이전 순위순위 상승
down현재 순위 > 이전 순위순위 하락
same현재 순위 = 이전 순위순위 유지

자정 처리: ranking_hour=0 계산 시 같은 날짜에 더 이전 시간이 없으므로 어제 마지막 시간(23 또는 가장 최근)에서 previous_rank를 가져온다.

7.3 랭킹 API

항목내용
엔드포인트GET /api/home/rankings/
설명현재 시간대 기준 앱 언어별 Top10 랭킹 조회
fallback현재 시간대 슬롯이 비어 있으면 가장 최근 슬롯 사용

7.4 랭킹 점수 산정 방식

다중 시그널을 가중 합산.

score = (
log10(1 + Book.views) * 5.0 # 누적 인기 (log 압축)
+ Book.pv_score * 0.3 # 기존 페이지뷰 점수 활용
+ bookmarks_7d * 2.0 # 강한 의도 신호
+ sticker_collections_7d * 0.5 # 최근 활동
+ reading_completions_7d * 1.0 # 실제 완독
+ new_book_decay_bonus(published_date) # 신간 부스트 (선형 감쇠)
)

가중치 (BookScoreConfig):

시그널가중치비고
VIEWS_LOG_WEIGHT5.0views=10K → 20점, 100만 → 30점
PV_SCORE_WEIGHT0.3기존 모델 필드
BOOKMARK_WEIGHT_7D2.0가장 강한 의도 신호
COLLECTION_WEIGHT_7D0.57일 합산
COMPLETER_WEIGHT_7D1.0ReadingHistory.is_completed
NEW_BOOK_MAX_BONUS5.0day 0 → +5
NEW_BOOK_DECAY_DAYS14day 14 → 0

신간 감쇠 공식:

new_book_decay_bonus = max(0, 5.0 * (1 - days_since_publish / 14))
  • day 0 → +5
  • day 7 → +2.5
  • day 14 → 0
  • 출시일 기반 자동 산정 (별도 운영자 토글 불필요)

언어 필터링: bookmarks_7d/collections_7d/completers_7d는 모두 user.viewer_languages에 해당 언어가 포함된 사용자만 카운트.

7.5 정렬 (tie-breaker)

ORDER BY score DESC, pv_score DESC, views DESC, id ASC

결정적 정렬 — 같은 입력 → 같은 순서. 동점 시 pv_scoreviewsid 순으로 결정.

7.6 갱신 / 운영

  • 집계 대상: 앱 언어 기준, 7일 윈도우
  • 갱신 주기: 1시간 단위 (cron calculate_realtime_rankings, 매 정시 +10분)
  • 동시 실행 방지: Redis 락 (home:realtime_ranking_calc_lock, TTL 600s)
  • 데이터 보관: 7일 이상 지난 슬롯은 매 cron 실행마다 자동 삭제
  • 운영 개입: Admin에서 row 편집 가능 (rank 1~50)

8. 섹션 구성 정책

  • 섹션 구성 및 개수: 배너 1섹션, 실시간 Top10 1섹션, 캐릭터 친구들 1섹션, 테마 큐레이션 다수 (제한 없음)

  • 노출 순서: 운영에서 수동 조정 가능

  • 섹션 내 카드 수:

    • 실시간 Top10: 고정 10개
    • 테마, 캐릭터친구들: 개수 제한 없이 가능한 것 전체 노출
    • 단, 카드 수 5개 이하인 경우 섹션 미노출 (단, 필터가 걸린 경우에는 카드 수 1개여도 노출함. 0개일 때만 미노출)
  • 슬라이드 동작:

    • 가로 스크롤, 루프 안함.

9. 카드=표지

  • 카드 구성 요소:

    • 표지 이미지 (제목 포함 / 도서 1권당 서비스 언어 수만큼 제작됨)
    • 배지 (BGM / OST 등 태그 기반 자동 노출, 확장 가능, 필수 아님)
  • 클릭 시: 작품 상세(홈) 이동

  • 배지 기준:

    • tag = BGM → "BGM"
    • tag = OST → "OST"

10. 예외 및 공백 처리

  • 카드 이미지 로딩 실패: 기본 표지 이미지로 대체

11. 하단 GNB 정책

  • 탭 구성: 홈 / 인기 / 이벤트 / 내 계정
  • 탭 이동 시: 홈 → 타 탭 → 홈 복귀 시 스크롤 초기화
  • depth 이동 시: 홈 → 뎁스 이동 → 홈 복귀 시 스크롤 위치 복원
  • GNB 고정 여부:
    • 1st depth(홈 화면): 상시 고정
    • 2nd depth(캐릭터 상세 등): 비노출

12. 로그 및 통계 정책

  • 기록 대상:

    • 필터 선택 이벤트
    • 카드 클릭 이벤트
    • 캐릭터 진입/복귀 이벤트
    • 배너 클릭 이벤트
  • 통계 활용:

    • 실시간 인기 Top10 집계
    • 사용자 행동 기반 추천 개선 및 A/B 테스트 활용
  • 제니 코멘트:

    • 시간 내 개발 가능하다면(불가시 우선순위로 최대한 빠른 시간내 개발 부탁합니다) GNB부터 클릭이 가능한 상위 3rd-4th depth 메뉴들까지 모두 로그 트래킹 가능하면 좋겠습니다. user habit이 서비스 진입부터 작품/결제 랜딩까지 어느 플로우로 가는지 보일 수 있도록요. 어느 루트로 작품뷰어까지 진입, 어떤 루트(작품)에서 결제 전환 등.

13. API 요약

API메서드설명
/api/home/GET종합 홈 데이터 (ComprehensiveHomeView)
/api/home/filters/GET홈 필터 목록
/api/home/banners/GET배너 목록
/api/home/rankings/GET실시간 Top10 랭킹
/api/home/curations/<id>/GET큐레이션 상세
/api/home/characters/GET캐릭터 친구들 목록