본문으로 건너뛰기

펜타 서비스 데이터베이스 스키마 (단순화 버전)

개요

콘텐츠 플랫폼의 핵심 기능에 집중한 단순화된 데이터베이스 스키마입니다. 확장성을 유지하면서 불필요한 복잡도를 제거했습니다.


1. 콘텐츠 도메인

books (도서)

컬럼명타입설명제약조건
book_idBIGINT도서 고유 식별자PK, AUTO_INCREMENT
titleVARCHAR(500)도서 제목NOT NULL
authorVARCHAR(200)작가NULL 가능
publisherVARCHAR(100)출판사NOT NULL
synopsisTEXT줄거리NULL 가능
age_rangeVARCHAR(20)연령대NULL 가능
published_dateDATE공개일NOT NULL
metadataJSON추가 메타데이터NULL 가능
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

book_languages (도서 언어)

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
language_codeVARCHAR(10)언어 코드PK
titleVARCHAR(500)번역 제목NOT NULL
cover_urlVARCHAR(500)표지 URLNOT NULL
content_urlVARCHAR(500)콘텐츠 URLNOT NULL

episodes (에피소드)

컬럼명타입설명제약조건
episode_idBIGINT에피소드 고유 식별자PK, AUTO_INCREMENT
book_idBIGINT도서 IDFK → books.book_id
episode_numberINT회차 번호NOT NULL
titleVARCHAR(500)에피소드 제목NOT NULL

categories (카테고리)

컬럼명타입설명제약조건
category_idBIGINT카테고리 고유 식별자PK, AUTO_INCREMENT
nameVARCHAR(100)카테고리명 (기본)NOT NULL
typeVARCHAR(50)카테고리 유형NOT NULL
parent_idBIGINT상위 카테고리FK → categories.category_id, NULL 가능
translationsJSON다국어 번역 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NULL 가능

book_categories (도서-카테고리 매핑)

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
category_idBIGINT카테고리 IDPK, FK → categories.category_id

book_series (시리즈)

홈 화면 필터 기능의 시리즈(프렌차이즈) 필터 구현을 위한 테이블입니다.

컬럼명타입설명제약조건
series_idBIGINT시리즈 고유 식별자PK, AUTO_INCREMENT
series_nameVARCHAR(200)시리즈명NOT NULL
series_typeENUM시리즈 유형 ('franchise', 'collection')NOT NULL
display_orderINT노출 순서DEFAULT 0
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

book_series_mapping (도서-시리즈 매핑)

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
series_idBIGINT시리즈 IDPK, FK → book_series.series_id
order_in_seriesINT시리즈 내 순서DEFAULT 0

book_tags (도서 태그)

테마별 큐레이션과 캐릭터 친구들 기능의 정확한 구현을 위한 태그 시스템입니다.

컬럼명타입설명제약조건
tag_idBIGINT태그 고유 식별자PK, AUTO_INCREMENT
tag_nameVARCHAR(100)태그명NOT NULL, UNIQUE
tag_typeENUM태그 유형 ('theme', 'character', 'feature')NOT NULL
tag_translationsJSON다국어 태그명 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NULL 가능

book_tag_mapping (도서-태그 매핑)

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
tag_idBIGINT태그 IDPK, FK → book_tags.tag_id

book_scores (도서 점수)

홈 화면의 PV 기반 정렬을 위한 테이블입니다.

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
pv_scoreINT페이지뷰 점수DEFAULT 0

characters (캐릭터)

작품에 등장하는 주요 캐릭터 정보를 관리합니다. 캐릭터 친구들 큐레이션에 활용됩니다.

컬럼명타입설명제약조건
character_idBIGINT캐릭터 고유 식별자PK, AUTO_INCREMENT
character_nameVARCHAR(200)캐릭터명NOT NULL
character_typeENUM캐릭터 유형 ('main', 'supporting', 'minor')DEFAULT 'main'
descriptionTEXT캐릭터 설명NULL 가능
image_urlVARCHAR(500)캐릭터 이미지 URLNULL 가능
name_translationsJSON다국어 캐릭터명 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NULL 가능
display_orderINT노출 순서DEFAULT 0
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

book_characters (도서-캐릭터 매핑)

컬럼명타입설명제약조건
book_idBIGINT도서 IDPK, FK → books.book_id
character_idBIGINT캐릭터 IDPK, FK → characters.character_id
role_in_bookVARCHAR(100)작품 내 역할NULL 가능

2. 리워드 도메인

stickers (스티커)

컬럼명타입설명제약조건
sticker_idBIGINT스티커 고유 식별자PK, AUTO_INCREMENT
episode_idBIGINT에피소드 IDFK → episodes.episode_id, UNIQUE
nameVARCHAR(200)스티커명 (기본)NOT NULL
name_translationsJSON다국어 스티커명 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NULL 가능
image_urlVARCHAR(500)이미지 URLNOT NULL

user_stickers (획득 스티커)

컬럼명타입설명제약조건
user_idBIGINT사용자 IDPK, FK → users.user_id
sticker_idBIGINT스티커 IDPK, FK → stickers.sticker_id
earned_atTIMESTAMP획득일시DEFAULT CURRENT_TIMESTAMP

3. 사용자 활동 도메인

reading_history (열람 기록)

컬럼명타입설명제약조건
history_idBIGINT기록 고유 식별자PK, AUTO_INCREMENT
user_idBIGINT사용자 IDFK → users.user_id, INDEX
book_idBIGINT도서 IDFK → books.book_id
episode_idBIGINT에피소드 IDFK → episodes.episode_id, NULL 가능
last_positionINT마지막 위치DEFAULT 0
is_completedBOOLEAN완독 여부DEFAULT FALSE
last_read_atTIMESTAMP마지막 열람일시DEFAULT CURRENT_TIMESTAMP

bookmarks (북마크)

컬럼명타입설명제약조건
user_idBIGINT사용자 IDPK, FK → users.user_id
book_idBIGINT도서 IDPK, FK → books.book_id
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

recordings (녹음)

컬럼명타입설명제약조건
recording_idBIGINT녹음 고유 식별자PK, AUTO_INCREMENT
user_idBIGINT사용자 IDFK → users.user_id
book_idBIGINT도서 IDFK → books.book_id
language_codeVARCHAR(10)언어 코드NOT NULL
file_urlVARCHAR(500)파일 URLNOT NULL
durationINT길이(초)NOT NULL
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

4. 콘텐츠 노출 도메인

content_lists (콘텐츠 리스트)

큐레이션, 랭킹, 스티커 구분 등 다양한 콘텐츠 리스트를 통합 관리합니다.

컬럼명타입설명제약조건
list_idBIGINT리스트 고유 식별자PK, AUTO_INCREMENT
list_typeVARCHAR(50)리스트 유형 (curation, ranking, popular_sticker, missing_sticker, upcoming_sticker)NOT NULL
nameVARCHAR(200)리스트명 (기본)NOT NULL
name_translationsJSON다국어 리스트명 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NULL 가능
criteriaJSON선정 기준 (예: {"period": "24h", "country": "KR"})NULL 가능
is_activeBOOLEAN활성화 여부DEFAULT TRUE
updated_atTIMESTAMP갱신일시DEFAULT CURRENT_TIMESTAMP

content_list_items (리스트 아이템)

컬럼명타입설명제약조건
list_idBIGINT리스트 IDPK, FK → content_lists.list_id
book_idBIGINT도서 IDPK, FK → books.book_id
positionINT순서NOT NULL
added_atTIMESTAMP추가일시DEFAULT CURRENT_TIMESTAMP

banners (배너)

컬럼명타입설명제약조건
banner_idBIGINT배너 고유 식별자PK, AUTO_INCREMENT
typeVARCHAR(50)배너 유형NOT NULL
image_urlVARCHAR(500)이미지 URLNOT NULL
target_typeVARCHAR(50)대상 유형NULL 가능
target_idBIGINT대상 IDNULL 가능
positionINT순서DEFAULT 0
is_activeBOOLEAN활성화 여부DEFAULT TRUE
start_dateDATETIME시작일시NOT NULL
end_dateDATETIME종료일시NULL 가능

5. 운영 도메인

notifications (알림)

컬럼명타입설명제약조건
notification_idBIGINT알림 고유 식별자PK, AUTO_INCREMENT
typeVARCHAR(50)알림 유형NOT NULL
titleJSON다국어 제목 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NOT NULL
messageJSON다국어 내용 {"ko": "...", "en": "...", "ja": "...", "es": "..."}NOT NULL
target_typeVARCHAR(50)대상 유형NULL 가능
target_idBIGINT대상 IDNULL 가능
created_atTIMESTAMP생성일시DEFAULT CURRENT_TIMESTAMP

user_notifications (사용자 알림)

컬럼명타입설명제약조건
user_idBIGINT사용자 IDPK, FK → users.user_id
notification_idBIGINT알림 IDPK, FK → notifications.notification_id
is_readBOOLEAN읽음 여부DEFAULT FALSE
received_atTIMESTAMP수신일시DEFAULT CURRENT_TIMESTAMP

events (이벤트)

컬럼명타입설명제약조건
event_idBIGINT이벤트 고유 식별자PK, AUTO_INCREMENT
typeVARCHAR(50)이벤트 유형NOT NULL
titleVARCHAR(500)제목NOT NULL
contentTEXT내용NOT NULL
image_urlVARCHAR(500)이미지 URLNULL 가능
start_dateDATETIME시작일시NOT NULL
end_dateDATETIME종료일시NULL 가능
is_activeBOOLEAN활성화 여부DEFAULT TRUE

6. 통계 도메인

daily_stats (일별 통계)

컬럼명타입설명제약조건
stat_dateDATE통계일PK
book_idBIGINT도서 IDPK, FK → books.book_id
viewsINT조회수DEFAULT 0
completionsINT완독수DEFAULT 0
bookmarksINT찜하기수DEFAULT 0
stickers_earnedINT스티커 획득수DEFAULT 0

search_history (검색 기록)

컬럼명타입설명제약조건
search_idBIGINT검색 고유 식별자PK, AUTO_INCREMENT
user_idBIGINT사용자 IDFK → users.user_id
queryVARCHAR(500)검색어NOT NULL
result_countINT결과수DEFAULT 0
searched_atTIMESTAMP검색일시DEFAULT CURRENT_TIMESTAMP

realtime_rankings (실시간 랭킹)

시간별 Top10 랭킹의 정확한 추적과 이력 관리를 위한 테이블입니다.

컬럼명타입설명제약조건
ranking_idBIGINT랭킹 고유 식별자PK, AUTO_INCREMENT
book_idBIGINT도서 IDFK → books.book_id
rankINT순위NOT NULL
scoreINT점수NOT NULL
country_codeVARCHAR(2)국가 코드NULL 가능
calculated_atTIMESTAMP집계일시DEFAULT CURRENT_TIMESTAMP
INDEX idx_country_time(country_code, calculated_at)국가별 시간별 조회용

7. 결제 도메인

payment_transactions (결제 거래)

컬럼명타입설명제약조건
transaction_idBIGINT거래 고유 식별자PK, AUTO_INCREMENT
user_idBIGINT사용자 IDFK → users.user_id
typeVARCHAR(50)거래 유형NOT NULL
amountDECIMAL(10,2)금액NOT NULL
currencyVARCHAR(3)통화NOT NULL
statusVARCHAR(50)상태NOT NULL
external_idVARCHAR(200)외부 거래 IDUNIQUE
processed_atTIMESTAMP처리일시DEFAULT CURRENT_TIMESTAMP

주요 인덱스

-- 자주 조회되는 패턴에 대한 인덱스
CREATE INDEX idx_reading_history_user ON reading_history(user_id, last_read_at DESC);
CREATE INDEX idx_daily_stats_date ON daily_stats(stat_date, views DESC);
CREATE INDEX idx_book_languages ON book_languages(language_code);
CREATE INDEX idx_content_list_items ON content_list_items(list_id, position);
CREATE INDEX idx_banners_active ON banners(is_active, start_date, end_date);

-- 홈 화면 기능을 위한 추가 인덱스
CREATE INDEX idx_book_series_type ON book_series(series_type, display_order);
CREATE INDEX idx_book_tags_type ON book_tags(tag_type, tag_name);
CREATE INDEX idx_book_scores_total ON book_scores(total_score DESC);
CREATE INDEX idx_realtime_rankings ON realtime_rankings(country_code, calculated_at DESC, rank);
CREATE INDEX idx_characters_order ON characters(display_order, character_name);
CREATE INDEX idx_book_characters ON book_characters(character_id, book_id);

확장 고려사항

1. 콘텐츠 포맷

  • books.metadata JSON 필드 활용
  • content_format, orientation 등 추가 가능

2. 사용자 세그먼트

  • user_segments 테이블 추가 가능
  • A/B 테스트, 타겟 마케팅 지원

3. 실시간 기능

  • 세션 관리, 실시간 동기화를 위한 테이블 추가 가능

4. 캐싱 레이어

  • Redis 등을 활용한 캐싱 전략
  • 자주 변경되지 않는 데이터는 캐시 활용

5. 스티커 구분 활용

  • content_lists의 list_type으로 스티커 3종 구분
  • popular_sticker: 인기 스티커 (24시간 기준)
  • missing_sticker: 나만 없는 스티커 (사용자별 필터링)
  • upcoming_sticker: 공개 예정 스티커
  • criteria JSON 필드로 유연한 조건 설정 가능

6. 홈 화면 정책 완전 구현

  • book_series: 시리즈(프렌차이즈) 필터 지원
  • book_tags: 테마별 큐레이션 지원
  • book_scores: PV 기반 점수 시스템
  • realtime_rankings: 시간별 Top10 랭킹 추적
  • characters: 캐릭터 친구들 큐레이션 완전 지원

마이그레이션 전략

단계별 접근

  1. 핵심 테이블부터 생성 (users, books, subscriptions)
  2. 기능별로 점진적 추가
  3. 데이터 마이그레이션은 배치 작업으로 처리

버전 관리

CREATE TABLE schema_versions (
version INT PRIMARY KEY,
description VARCHAR(200),
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

이 단순화된 스키마는 콘텐츠 플랫폼의 핵심 기능을 지원하면서도, 필요시 확장 가능한 구조를 유지합니다.


원본 스키마에서 제외된 주요 항목

1. 복잡한 점수 시스템

  • 제외된 것: 복잡한 점수 계산 시스템, 인기도 점수 가중치
  • 이유: 초기에는 단순 조회수와 완독수로 충분
  • 대안: daily_stats 테이블의 기본 지표 활용

2. 개인화 추천 시스템

  • 제외된 것: user_theme_preferences, user_sticker_recommendations
  • 이유: MVP에서는 전체 인기 콘텐츠로 충분
  • 대안: 추후 별도 추천 서비스로 확장 가능

3. 상세 행동 추적

  • 제외된 것: 스크롤 속도, 체류 시간, 50%/90% 진행률
  • 이유: 초기에는 완독 여부만으로도 충분
  • 대안: 필요시 reading_history 테이블 확장

4. 세분화된 스티커 관리

  • 제외된 것: 별도의 스티커 통계 테이블 (popular_stickers, upcoming_stickers 등)
  • 이유: content_lists로 통합 관리가 더 단순함
  • 대안: content_lists의 list_type을 활용한 3종 스티커 구분

5. 시간대별 집계

  • 제외된 것: 시간별 통계, UTC+9 시간대 관리
  • 이유: 일별 통계로 충분히 운영 가능
  • 대안: 필요시 통계 테이블에 시간 컬럼 추가

6. 세부 운영 기능

  • 제외된 것:
    • 프로모션 코드 관리 (promo_codes)
    • 관리자 권한 세분화 (admin_users)
    • 콘텐츠 공개 일정 관리 (content_schedule)
  • 이유: 초기에는 수동 운영으로 충분
  • 대안: 운영 규모 확대시 점진적 추가

7. 고급 검색 기능

  • 제외된 것:
    • 인기 검색어 집계 (popular_searches)
    • 검색 자동완성
    • 검색 결과 가중치
  • 이유: 기본 검색 기능으로 시작
  • 대안: 검색 엔진 도입시 확장

8. 멀티 디바이스 관리

  • 제외된 것:
    • 세션 관리
    • 디바이스별 로그인 추적
    • 1기기 제한 강제
  • 이유: 초기에는 단순 로그인으로 충분
  • 대안: 필요시 세션 테이블 추가

9. 부정 사용 방지

  • 제외된 것:
    • 스크롤 속도 감지
    • 비정상 패턴 탐지
    • 상세 로그 분석
  • 이유: 초기에는 기본 규칙으로 충분
  • 대안: 문제 발생시 로직 추가

10. 상세 메타데이터

  • 제외된 것:
    • 렉사일 지수 세부 정보
    • 작가별 관리
  • 이유: 핵심 정보만으로 시작
  • 대안: books.metadata JSON 필드 활용

이러한 단순화를 통해 개발 속도를 높이고, 핵심 기능에 집중하여 빠른 시장 검증이 가능합니다. 서비스 성장에 따라 필요한 기능을 점진적으로 추가할 수 있습니다.