Skip to content

[서버] 캐릭터 관계 레벨 시스템 PRD

Backlog grooming 단계의 산출물. 무엇을 만들지·왜 만들지·핵심 비즈니스 룰을 정의한다. 화면별 디테일(컴포넌트·상태·인터랙션)은 spec.md로.


Status: draft Created: 2026-05-13 Last updated: 2026-05-22 (DM/Soul 정책 반영: Episode Character 임시 적립·Soul 이관·개인화 선톡 source·노출 surface 정렬)

본 PRD의 성공 정의: "완성된 관계 경험" 아님. 추적 가능한 관계 이벤트 데이터 자산 + DM 캐릭터 상세/에피소드 상세 Episode Character 정보 섹션 최소 노출까지. 감정 가중치·관계 효과·정교한 톤 변화 같은 sharp한 경험은 후속 PRD가 이 데이터 위에 올린다. Linear Issue: DEE-71 [앱] 캐릭터 관계 레벨 시스템Author: agent (momo) 시스템/표면: 서버 foundation + 앱/웹 노출 surface(DM 캐릭터 상세, 에피소드 캐릭터 정보)


0. 요약

  • 유저가 에피소드에서 Episode Character가 등장하는 씬을 생성하거나, DM에서 Soul 응답/개인화 선톡을 받는 등 star가 차감되는 Soul 상호작용이 성공하면 Bond Exp가 쌓인다. 대전제는 delta_exp = consumed_star이며, 멀티 Episode Character scene은 등장 Episode Character 수로 균등 분배한다.
  • 이 Exp를 Soul과 연결된 관계에서만 관계 Lv.N + 진행바로 최소 노출한다. 노출 surface는 DM 캐릭터 프로필 상세에피소드 상세의 Episode Character 정보 섹션 두 곳이며, Exp 숫자 자체는 유저에게 직접 노출하지 않는다.
  • 본 PRD의 핵심은 예쁜 관계 경험을 완성하는 것이 아니라, 나중에 DM 선톡·톤 변화·잠금해제·관계 효과 같은 기능이 쓸 수 있는 raw 이벤트 데이터 자산을 만드는 것이다.
  • 그래서 (user, Soul) 총합 Exp만 저장하는 형태는 금지. source / delta / timestamp가 있는 이벤트 로그를 진실원천(source of truth) 으로 남기는 게 핵심. 감사·분석·운영 안정성을 위해 어떤 상호작용에서 어떤 Exp가 발생했는지 추적 가능해야 한다.

1. 목표 및 배경

1.1 문제

  • 사용자 정의 (segment): 캐릭터 중심 콘텐츠 소비를 하는 모든 플레이어 + DM/관계형 기능을 만들려는 제품팀.
  • 상황 (when, where): 플레이어가 한 캐릭터를 반복적으로 만나거나, DM에서 자주 대화함에도 그 누적이 어디에도 반영되지 않는 상황.
  • 불편 / 미충족 needs: 캐릭터-유저 유대 관계가 데이터로 존재하지 않아 (1) 플레이어가 "내가 이 캐릭터와 얼마나 가까운지" 시각적으로 확인할 수 없고, (2) DM 선톡·톤 변화·잠금해제 같은 후속 기능을 깔 데이터 기반이 없다.

1.2 근거

  • 이니셔티브 방향: "캐릭터 관계/메신저 경험 기반 구축". 본 PRD는 그 안의 사전작업 — 후속 관계형 기능들이 올라설 raw 데이터·최소 노출을 깐다.
  • 인접 grilling: 2026-05-13 모모 grilling에서 DM 메신저(DEE-72)와 에피소드 상세 캐릭터 섹션(DEE-66/79) ship 결정. 두 기능 모두 "이 캐릭터와 얼마나 가까운가"의 데이터 표현을 요구.
  • DM 검증 속도 우선: DM(DEE-72) 시장 검증을 빠르게 돌리는 것이 상위 우선순위. 유대 체계는 DM 발 끌지 않게 MVP 수준으로 단순·기능적으로 가져가되, 데이터는 후속 튜닝이 가능하게 남긴다.
  • 현재 우회: 디렉터들이 캐릭터 정보를 미리보기 이미지에 텍스트로 박는 식으로 우회 중 (DEE-66 Background) — 관계 표현 자리 자체가 없음.

1.3 아이디어 (해결 방향)

유저-Soul 누적 상호작용을 이벤트 단위 raw 기록(source, delta, timestamp 포함) 으로 적재하고, 그 합산으로 관계 Lv.N과 진행바를 산출해 노출한다. Episode Character 상호작용은 linked Soul로 귀속하며, Soul 미연결 상태에서는 Episode Character side에 임시 적립 후 연결/패치 시점에 1회 이관한다. Bond Exp 숫자 자체는 유저에게 노출하지 않는다.

  • 옵션 1 (채택): 이벤트 로그 + 파생 총합 Bond Exp + 관계 레벨 노출. 구현·이해 단순. 후속 기능은 raw 이벤트/Exp를 직접 참조할 수 있고, 감사·분석·운영 확인이 가능.
  • 옵션 2 (기각): 의미 가중치(긍정/부정/감정 톤)로 계산하는 복합 점수. MVP 가설·튜닝 비용 과다 + DM 시장검증 속도 저하.
  • 옵션 3 (기각): 총합 Exp 정수만 저장(이벤트 로그 X). 사후 정책 튜닝 시 재계산 불가 → foundation의 확장성 요구에 위배.
  • 옵션 4 (기각): 단계만 노출 (숫자 X). 노출 정책 자체는 옵션 1 안에서 결정 (본 PRD는 관계 Lv.N + 진행바만 노출, Exp 숫자는 비노출).

채택 근거: foundation 단계는 추적 가능한 관계 데이터 자산을 정확히 쌓는 게 1차 목표. raw 이벤트가 남아 있어야 운영 중 적재 누락·이상치·source mix를 감사/분석할 수 있고, 후속 기능도 같은 진실원천을 안정적으로 참조할 수 있다. 노출은 동기 부여 + 후속 기능 신뢰도 빌딩용으로 최소 표면만.

1.4 가설 (직접 검증은 후속 PRD)

본 PRD는 foundation 성격이라 가설 1·2는 후속 PRD(DM 선톡, DEE-66 ship 후 재진입 분석 등) 시점에 검증. 본 PRD는 데이터 자산이 정확히 쌓이는 것까지 책임진다.

  1. 플레이어는 누적된 유대가 시각적으로 보이면 같은 캐릭터의 다른 에피소드/DM으로 재진입할 동기를 갖는다 → DEE-66 ship 후 측정 가능.
  2. 유대 데이터가 존재하면 DM 선톡·톤 변화·잠금해제 같은 후속 기능이 ship 가능해진다 → 각 후속 PRD에서 enablement 확인.

1.5 성공 지표

지표현재목표측정 방법
Bond Exp 적재 손실률n/a허용 손실률 ≤ 정책 임계 (정책·임계 spec에서 확정)카운트 소스 이벤트 대비 Exp 증가 트랜잭션 비율
단계 분포 합리성n/a분포가 §3-1 곡선 의도와 ±X% 이내 일치 (헤비 cap-hit 유저 기준 Lv.100 ≈ 6.5개월, Lv.200 ≈ 2.2년)단계별 (user, Soul) 쌍 분포 모니터링
  • 메인 지표: Bond Exp 적재 손실률 (정책 임계 안에서 손실).
  • UI 노출 surface의 진입률·이탈률은 DEE-66/79(에피소드 상세 캐릭터 섹션) 지표로 본다. 본 PRD의 핵심 분석은 DB에 쌓인 Bond Exp/Level 기준.

2. 타깃 사용자

2.1 주요 사용자

  • 캐릭터를 중심으로 콘텐츠를 즐기는 플레이어 (특정 캐릭터가 등장하는 에피소드를 반복 플레이하거나 DM 대화를 즐기는 사용자).
  • 빈도: 에피소드 상세 진입 시마다 자연스럽게 노출. 별도 진입 경로 없음.

2.2 핵심 시나리오

  1. 플레이어가 Episode Character A가 등장하는 에피소드 3편을 클리어한 후, 같은 Soul에 연결된 Episode Character가 등장하는 다른 에피소드 상세에 들어가 관계 Lv.2 + 다음 단계까지의 진척바를 본다.
  2. 플레이어가 DM에서 Soul B와 충분히 대화한 후, 에피소드 상세에서 진척바가 다음 단계 가까이 가 있는 걸 본다.
  3. 후속 PRD(DM 선톡 등)에서 Bond Exp/Bond Level을 조건으로 기능을 분기시킨다 (본 PRD 범위 외, foundation 사용 예시).

3. 핵심 기능 요구사항

3-1. 클라이언트 (앱)

유대 표시 (DM 캐릭터 상세 + 에피소드 상세 캐릭터 정보 섹션)

  • 주요 동작: DM 캐릭터 프로필 상세(DEE-72)와 에피소드 상세의 Episode Character 정보 섹션(DEE-66/79)에서, 대상 Episode Character/Soul이 linked Soul 조건을 만족할 때 유대 상태를 노출한다.
  • 표시 요소:
    • 단계 라벨 (관계 Lv.N — 단계명 카피 동반 여부는 §7)
    • 진척바 (현 단계 시작 → 다음 단계 진입까지 비율)
    • Bond Exp 숫자는 직접 노출하지 않는다. (디버그/어드민용만)
  • 비즈니스 룰:
    • 유대는 (user, Soul) 쌍 단위, 글로벌. 같은 Soul에 여러 Episode Character가 연결될 수 있으며, Episode Character 출연 이벤트는 linked Soul에 귀속한다.
    • 노출 조건: 로그인 사용자 + linked Soul + Bond 기능/데이터 사용 가능 조건에서만 관계 Lv/progress를 노출한다. 에피소드 상세의 Episode Character 정보 섹션은 기존 DM Thread 존재를 요구하지 않는다. linked Soul이 없거나 비로그인 상태이면 관계 UI를 숨긴다.
    • Bond Level/진척바는 누적 Bond Exp에서 매번 파생 (저장하지 않음). 곡선이 바뀌면 표시값이 자동 재계산.
  • 노출 위치: (1) DM 캐릭터 프로필 상세, (2) 에피소드 상세 Episode Character 정보 섹션. 다른 표면(MY/홈/캐릭터 카드 등) 확장은 §7.

Ship 순서: 본 PRD는 데이터 적재 + 컴포넌트만 정의. UI가 실제 유저에게 노출되려면 DEE-66 (에피소드 상세 캐릭터 섹션)이 함께 ship 되어야 한다 (의존성 표 참조). 본 PRD 단독 ship 시에는 데이터만 쌓이고 노출은 없는 상태가 될 수 있음.

Bond Exp 누적 (count source)

Bond Exp가 증가하는 소스. episode_scene_appearance, dm_response_generated, personalized_proactive_message_receivedsource/event record로 분리 저장하고, 표시용 Bond Exp/Level은 (user, Soul) 기준으로 aggregate한다. Episode Character source는 linked Soul에 귀속하되, Soul 미연결 상태에서는 Episode Character side에 임시 적립 후 연결/패치 시점에 Soul로 1회 이관한다.

  • 공통 단가 공식 (확정): delta_exp = consumed_star (멀티 Episode Character scene은 등장 Episode Character 수로 균등 분배 후 적용). 즉 해당 상호작용에서 실제로 소비된 star 양 자체가 그대로 Exp가 된다. 소수 Exp 허용 — Exp는 유저에게 직접 노출하지 않으므로 별도 반올림/표시 정책 불필요. consumed_star = 0이면 delta_exp = 0.

  • free/paid·프로모/보너스 생성 구분 없음: 무료/보너스 생성이라도 실제로 star 소비가 기록되면 그 소비량 기준으로 Exp가 발생한다. star 소비 자체가 0이면 Exp도 0. 개인화 선톡도 유저 측 수신 성공 시 star가 차감되면 동일 원칙으로 Bond Exp 적립 대상이다.

  • 소스 A — 에피소드 씬 등장(Scene Appearance)

    • 정의: 생성된 에피소드의 한 scene에서 Episode Character가 등장하거나 발화함. 해당 source_ref(예: scene_id) 안에서 scene당 Episode Character당 1회로 카운트 — 같은 Episode Character가 한 scene 안에서 여러 번 발화해도 1회 entry.
    • Exp 단가: 고정값 아님. 그 scene 생성에서 실제 소비된 star를 등장 Episode Character 수로 균등 분배한 값.
    • 멀티 Episode Character scene 정책: 한 scene에 여러 Episode Character가 등장하면 scene_consumed_star / 등장 Episode Character 수를 각 Episode Character의 allocated consumed star로 보고, 각 Episode Character별 delta_exp = allocated_consumed_star를 적립한다. 같은 scene 내 동일 Episode Character의 중복 발화는 추가 적립하지 않는다.
  • 소스 B — DM 응답 생성(DM Response)

    • 정의: DM Thread에서 Soul 응답이 성공적으로 1회 생성될 때마다 1회로 카운트. 응답이 여러 말풍선으로 분할되더라도 1회.
    • Exp 단가: 고정값 아님. 그 응답 생성에서 실제 소비된 star 값 그대로.
  • 소스 C — 개인화 선톡 수신(Personalized Proactive Message)

    • 정의: 유저가 개인화 선톡을 유저 측 수신 성공 상태로 받은 경우. 전체 발송/무료 선톡처럼 star 차감이 없는 메시지는 consumed_star = 0이므로 Bond Exp도 0.
    • Exp 단가: 고정값 아님. 수신 성공 시 실제 차감된 star 값 그대로.

첫 출시 정책 (확정): 단가는 consumed_star 자체(멀티 Episode Character scene만 등장 Episode Character 수로 균등 분배). 첫 출시는 §3-1 일일 cap만 적용하고, 추가 diminishing·소스간 balancing은 포함하지 않는다. 이벤트 로그는 감사·분석·운영 안정성을 위해 raw delta·source·source_ref·timestamp를 보존한다.

  • 단계 곡선 (확정 — 공식 기반)

    • 공식: required_exp_for_level(N) = 300 × (N − 1)² (N ≥ 1, Lv.1 임계 = 0).

    • 레벨 산출: total_bond_exp >= required_exp_for_level(N)을 만족하는 가장 큰 N.

    • Max level (첫 출시): max_level = 200.

    • 진행바: 현재 레벨 임계 → 다음 레벨 임계 구간 비율. Lv.200 도달 후에도 Bond Exp는 계속 누적되지만, 유저 노출 레벨은 200으로 고정한다.

    • 설계 근거: Exp 적립 단위를 consumed_star 기준으로 확정하면서, 기존 성장 체감 속도를 유지하기 위해 곡선 계수와 일일 cap을 함께 스케일했다. 일일 cap 15,000 Exp를 매일 채우는 헤비 유저 기준 Lv.100 도달 ≈ 6.5개월, Lv.200 도달 ≈ 2.2년. 초기 레벨은 빠르게 오르고 후반은 의도적으로 여러 달~수년에 걸쳐서만 도달 가능.

    • 주요 레벨 도달 필요 누적 Exp / 소요일:

      Level필요한 누적 Bond ExpMax 기준(15,000 Exp/day)평균 기준
      Lv.100일0일
      Lv.23001일300 ÷ avg_daily_credited_exp
      Lv.31,2001일1,200 ÷ avg_daily_credited_exp
      Lv.1024,3002일24,300 ÷ avg_daily_credited_exp
      Lv.50720,30049일720,300 ÷ avg_daily_credited_exp
      Lv.1002,940,300197일2,940,300 ÷ avg_daily_credited_exp

      평균 기준 소요일은 출시/분석 기준 avg_daily_credited_exp 확정 후 산출한다. 현재 PRD 확정값으로 바로 계산 가능한 기준은 일일 cap max(15,000 Exp/day)다.

  • 일일 cap (확정): (user, Soul, day) 1일 최대 15,000 Bond Exp credited. 하루 기준은 KST 오전 6시 reset (06:00:00~익일 05:59:59). raw 이벤트 자체는 cap 초과분도 이벤트 로그에 그대로 남기되, credit 되는 delta_exp는 일일 누적이 15,000을 넘지 않도록 절단/부분 적립 (cap 경계의 이벤트는 부분 credit, 이후는 0 credit). 정확한 적재 형태(별도 flag / 부분 credit 컬럼 등)는 spec.

    • 설계 근거: consumed_star 기준 적립에서도 기존 성장 속도 의도를 유지하려면 15,000 Exp/일 cap이 필요하다. D0 scene 생성 q3 ≈ 52건/일 데이터 기준, 15,000 Exp/일 cap은 정상~상위 D0 활동을 막지 않고 극단 outlier만 통제하는 수준.
  • 데이터 모델 (확장성 요구):

    • 이벤트 로그 우선: (event_id, user_id, soul_id, source_type, source_ref, consumed_star, delta_exp, credited_delta_exp, occurred_at, server_received_at, linked_episode_character_id?) 단위로 적재. source_type = episode_scene_appearance / dm_response_generated / personalized_proactive_message_received / migration_backfill / (향후 추가). source_ref는 episode_id+scene_id 또는 dm_response_id 같은 원본 추적 키. raw delta_expconsumed_star 기준(멀티 Episode Character scene은 균등 분배값) 그대로 저장, credited_delta_exp는 일일 cap을 반영한 실제 가산분.
    • 총합 Exp는 파생/캐시: (user, Soul) 총합 Bond Exp(total_exp)는 조회 성능을 위해 캐시할 수 있으나 이벤트 로그가 진실원천. 정책(곡선·가중치·cap)이 바뀌면 이벤트 로그에서 재집계해 캐시 갱신.
    • 불투명 단일 총합만 저장하는 형태는 금지. 후속 정책 튜닝 시 재계산 불가 → foundation 목적 위배.
  • 누적 룰:

    • 트랜잭션: scene 생성 성공 후 / DM 응답 생성 성공 후 / 개인화 선톡 유저 측 수신 성공 후 동기 적재 (해당 트랜잭션의 consumed_star 확정 이후). 실패 시 retry. 최종 실패 시 손실로 집계되어 §1.5 메인 지표(허용 손실률)로 관측. 사용자에게 노출되는 동작은 없다.
    • 같은 (user, Soul, scene_id, linked_episode_character_id?) 또는 (user, Soul, dm_response_id) 또는 (user, Soul, proactive_message_delivery_id)는 중복 방지 키로 이중 적재 방지.
    • 일일 cap을 초과하는 credited delta는 0 또는 부분 credit으로 절단 (raw 이벤트는 보존).

3-2. 어드민

본 PRD 범위 어드민 화면 없음 (§3-5 Out of scope). 운영 incident 발생 시 DB 직접 조정.

3-3. 딥링크 / URL 구조

신규 path 없음. 노출 surface는 기존 /episode/:episodeId 안의 캐릭터 섹션.

3-4. Scope

포함 (In scope)

  • (user, Soul) Bond 이벤트 로그 + 파생 총합 Bond Exp 데이터 모델·적재 파이프라인 (source/ref/consumed_star/timestamp 포함, 사후 재계산 가능 형태).
  • 에피소드 scene 등장 → scene consumed star를 등장 Episode Character 수로 균등 분배한 allocated_consumed_star를 Bond Exp로 적재 (scene·Episode Character당 1 entry, 같은 scene 내 동일 Episode Character 중복 발화는 1회로 절단).
  • DM 응답 생성 → consumed_star를 Bond Exp로 적재 (응답당 1회, 말풍선 분할 무관).
  • 개인화 선톡 유저 측 수신 성공 → star가 차감된 경우 consumed_star를 Bond Exp로 적재.
  • 일일 cap 15,000 Bond Exp / (user, Soul, day) — credit 절단, raw 로그는 보존.
  • 단계 곡선 공식 300 × (N − 1)², max_level = 200.
  • DM 캐릭터 프로필 상세 + 에피소드 상세 Episode Character 정보 섹션 내 유대 표시 (관계 Lv.N + 진척바) — linked Soul 조건 충족 시에만.
  • 기존 유저 대상 과거 scene·DM 생성 이력 기반 migration/backfill (§ Migration 참조).
  • Soul 미연결 Episode Character side Exp의 Soul 연결 후 1회 이관 정책.

제외 (Out of scope)

  • DM 내 효과: 선톡, 톤 변화, 잠금해제 (각 후속 PRD).
  • 다른 surface 노출: MY 탭, 캐릭터 카드, 홈 등.
  • 어드민 수동 조정 화면.
  • 추가 가중치·Exp 감소·만료·diminishing 룰 (이벤트 로그 보존으로 사후 도입 가능).
  • 감정/톤 분석 기반 점수 산출 (sentiment weighting).
  • DM 메모리/컨텍스트가 유대에 미치는 효과 (DEE-115 범위).
  • 통계·랭킹·소셜 비교 (친구의 유대 노출 등).
  • 캐릭터 정보 섹션 자체의 UI/정보 구조 (= DEE-66/79의 PRD 범위).

4. 에러 처리 및 예외 상황

상황처리 방향
비로그인 상태에서 에피소드 상세 진입관계 UI 숨김
Bond Exp 적재 이벤트 실패 (네트워크/서버 오류)서버 트랜잭션 retry → 최종 실패는 손실로 집계, §1.5 메인 지표로 관측. 사용자 노출 없음
단계 곡선 공식 변경 (배포 후)누적 Bond Exp는 그대로, 표시 단계만 자동 재계산
Episode Character가 에피소드에서 제거되거나 비공개linked Soul의 누적 Bond Exp는 보존. 해당 Episode Character 노출 surface가 사라질 뿐
같은 Episode Character가 한 scene에서 여러 번 발화scene·Episode Character당 1회로 절단 (중복 방지 키)
DM 응답 1건이 여러 말풍선으로 분할응답 1건 = 1회로 절단
일일 cap(15,000) 초과credited delta를 0 또는 부분 credit으로 절단, raw 이벤트는 로그에 남김
한 scene에 여러 Episode Character 등장scene consumed star를 등장 Episode Character 수로 균등 분배한 뒤, 각 Episode Character별 allocated_consumed_star 적립
consumed_star = 0 (무료/보너스 생성에서 실제 star 차감 0)delta_exp = 0. 이벤트 entry는 남길 수도, 생략할 수도 — spec
Lv.200 도달 후 추가 ExpBond Exp는 계속 누적하되, 유저 노출 레벨은 200으로 고정
Episode Character ↔ Soul 연결 적용Studio draft/자동 저장 단계는 영향 없음. [적용] 성공 후 active connection으로 취급하되, Episode Character side Exp의 Soul 이관은 유저 컨텍스트 기반 데이터 패치/리드 시점에 1회 수행. 이관 후 Episode Character side exp reset, rollback 없음
user 또는 Soul 삭제Bond 레코드도 함께 정리 — 세부 cascade 정책은 spec

5. 데이터 분석

본 PRD는 DB에 적재된 이벤트 로그 + 파생 총합 Bond Exp를 진실원천으로 한다. 별도 클라이언트 로깅 이벤트는 본 PRD에서 추가하지 않는다 (필요 시 후속 PRD에서). 아래 모든 지표는 DB에서 직접 도출.

5.1 핵심 지표

  1. Bond Exp 적재 손실률 (§1.5 메인) — 카운트 소스(scene 생성 / DM 응답 생성) 이벤트 대비 Bond Exp 적재 트랜잭션 비율.
  2. Bond Level 분포 — 단계별 (user, Soul) 쌍 수. max_level = 200 기준 분포, 곡선 의도(대다수 저레벨)와의 fit.
  3. 레벨 도달 시간 — (user, Soul)별 Lv.N → Lv.N+1 진입까지 걸린 일수, 누적 Lv.100 / Lv.200 도달 시간 분포.
  4. 일별 획득 Bond Exp 분포 — (user, Soul) day별 credited delta 합 분포. 일일 cap(15,000) 도달 빈도.
  5. 소스 mix — Bond Exp 누적의 source_type 비율 (episode_scene_appearance vs dm_response_generated vs personalized_proactive_message_received vs migration_backfill).
  6. Cap-hit rate — 일일 cap 15,000에 도달한 (user, Soul, day) 비율.
  7. Stalled level — 일정 기간 같은 레벨에 머무는 (user, Soul) 비율 (곡선 후반부 의도 검증).
  8. Migration validation — backfill 후 총 Exp / 레벨 분포 합리성, 상위 유저·캐릭터 spot check, source_type별 카운트 매칭.
  9. Outlier monitoring — 비정상적으로 빠른 레벨 진입, 단일 (user, Soul, day) raw delta 폭주, abuse 패턴 알람.

5.2 로깅 이벤트

본 PRD에서는 별도 신규 클라이언트 로깅 이벤트를 추가하지 않는다. 모든 분석은 DB(이벤트 로그 테이블 + 캐시 테이블) 기준. 클라이언트 노출 측 funnel은 DEE-66 (에피소드 상세 캐릭터 섹션) PRD의 책임.


6. Ubiquitous Language

TermKoreanDefinitionDo Not Confuse WithPrimary Domain상태
Soul소울Studio의 Soul Management에서 디렉터가 만들고 운영하는 DM 가능한 지속 인격체. DM Thread, 선톡, Bond, DM 메모리/프롬프트의 기준 entity. 하나 이상의 Episode Character와 연결될 수 있다.에피소드 내 등장 인물 Episode CharacterDM / Studio신규
Episode Character에피소드 캐릭터에피소드 콘텐츠와 플레이에 등장하는 episode-local 인물. 씬 등장·에피소드 상세 섹션·출연 정보의 기준 entity. Soul과 연결되면 Bond 적립/노출이 (user, Soul)로 귀속된다. Soul 미연결 상태에서는 Episode Character side에 임시 Exp가 쌓일 수 있다.Soul(위), 유저 프로필Episode Content기존
Bond유대 / 관계(user, Soul) 쌍의 관계 상태를 표현하는 상위 도메인 entity. 이벤트 로그 기반으로 누적되는 Bond Exp를 원천값으로 가지며, 유저 노출용 Bond Level은 Bond Exp에서 파생된다. 유저에게는 "유대" / "관계 Lv.N"으로 노출.캐릭터 일반 평판·작품 인기도Bond (신규 도메인)신규
Bond Exp유대 ExpBond의 raw 누적 카운트. 소수 허용, 단조 증가. delta_exp = consumed_star(멀티 Episode Character scene은 균등 분배값). (user, Soul, day) 일일 credit cap 15,000. 유저에게는 숫자로 직접 노출하지 않는다.일반 경험치(없음), Credit/star 자체Bond신규
Bond Level유대 단계 (관계 Lv.N)Bond Exp에 공식 300 × (N − 1)²을 적용해 얻은 단계 라벨. 저장하지 않고 파생. max_level = 200. 유저 노출 표기는 관계 Lv.N.Bond Exp 자체Bond신규
Bond Source Event관계 적립 이벤트Bond Exp를 부여하는 카운트 가능한 이벤트. source: (A) 에피소드 scene 등장 — scene·Episode Character당 1 entry, 멀티 Episode Character scene은 scene consumed star를 등장 Episode Character 수로 균등 분배. (B) DM 응답 생성 — 응답당 1회. (C) 개인화 선톡 수신 성공 — star 차감이 발생한 경우. Exp 단가는 각 event의 consumed_star.일반적 "언급" / 단순 발화 횟수 / 고정 단가Play / DM신규

7. Open Questions

  • [ ] 유저 노출 한국어 네이밍 최종 확정 — "유대", "관계 Lv.N", 진척바 라벨 등 카피의 최종 표기. PRD 단계 작업 가정값은 관계 Lv.N + "유대". — PM + 카피.
  • [ ] 단계 라벨 카피 동반 여부관계 Lv.N만 쓸지, 의미 있는 단계명(예: 낯선 사이 → 친한 사이)을 함께 노출할지. 동반한다면 카피는 spec/카피 단계에서. — PM.
  • [ ] 다른 surface 노출 후속 결정 — MY 탭(내 유대 톱), 캐릭터 카드, 홈 추천 등. 본 PRD 범위 외지만 본 PRD ship 직전 후속 PRD 큐 점검. — PM + 디자이너.
  • [ ] 모니터링/운영 임계 — §1.5 메인 지표 허용 손실률 임계 + 가드레일 회귀 폭, cap-hit rate / stalled level / outlier 알람 임계. 베이스라인 수치는 출시 직전. — PM + 엔지니어.

부록: 메타 정보

Required artifacts

  • [x] BE implementation handoff (needs-be-handoff) — 본 PRD의 §3-1 정책을 기준으로 구현. 세부 hook 위치, 중복 방지 키, cap 집계 테이블/뷰, Episode Character side Exp 이관, backfill 실행 방식, DB cascade 정책은 백엔드 구현 설계에서 확정.
  • [x] Design (needs-design) — Figma: 관계 Lv.N 라벨 + 진척바 컴포넌트 + 빈/저레벨 상태. DEE-66 캐릭터 섹션에 통합.
  • [ ] QA scenarios (needs-qa-scenarios) — Sprint planning에서 작성.
  • [x] Migration plan (needs-migration) — 신규 이벤트 로그 테이블 + (user, Soul, total_exp, last_event_at) 캐시 테이블 + (user, Soul, day) 일일 cap 집계 테이블/뷰. 기존 유저 backfill 포함: 과거 episode scene 생성·DM 응답 생성 이력에서 (a) Episode Character ↔ Soul 매핑과 consumed_star가 복원 가능한 경우 원래 source_type/source_ref로 이벤트 로그 entry 생성, (b) source_ref까지는 복원 불가하지만 (user, Soul) 단위로 누적 star가 복원 가능한 경우 migration_backfill source_type의 집계 entry로 적재 (occurred_at = backfill 시점 또는 기간 대표값, backfill 메타데이터 포함). Episode Character id 재발행 정책: 새 id 발급 이후 신규 play/generation부터 새 id 기준으로 적립하며, 과거 play를 재트리거해도 새 id에 소급 적립하지 않는다. Soul 미연결 기간에 Episode Character side에 쌓인 Exp는 Soul 연결 후 유저 컨텍스트 기반 데이터 패치/리드 시점에 1회 Soul로 이관하고, 이관 후 Episode Character side exp는 reset한다. Backfill 후 §5 migration validation 지표로 총 Exp / 레벨 분포 및 상위 유저·캐릭터 spot check.
  • [ ] Tracking events (needs-tracking) — 본 PRD는 신규 클라이언트 로깅 이벤트 없음. 모든 분석은 DB 기준 (§5).

Size & Risks

  • Size: M
  • Confidence: medium
  • 추정 근거: 신규 테이블 1~2개 + 이벤트 3 소스 hook + 노출 surface 2곳 연동 + 기존 유저 backfill/이관 1회성 작업. 단계 곡선 공식·단가 공식·cap·멀티 Episode Character 균등 분배 정책이 확정되어 구현 자체는 단순.

주요 위험 요소

위험영향대응
scene·DM 응답 hook 누락 또는 중복 적재적재 손실 / 단계 분포 왜곡중복 방지 키 + retry. ship 후 1~2주 모니터링하며 곡선·cap 튜닝 (raw 이벤트 로그 보존으로 재집계 가능).
후속 기능이 Bond Level에 강결합곡선 튜닝 비용 ↑후속 기능은 raw Bond Exp 임계값 또는 이벤트 로그로 분기. Bond Level은 UI 노출 전용.
총합 Bond Exp만 저장된 채 ship → 사후 정책 튜닝 시 재계산 불가foundation 목적 실패 (데이터 리셋 필요)이벤트 로그를 진실원천으로 박는 §3-1 데이터 모델 룰을 spec/구현에서 어겨선 안 됨. spec 리뷰 게이트.

의존성

  • DEE-66 / DEE-79 (에피소드 상세 캐릭터 정보 섹션): 본 PRD의 UI 노출 surface 중 하나. linked Soul 조건에서 관계 Lv/progress 노출 룰을 함께 반영해야 함. design merge point 협의 필요.
  • DEE-72 (DM 메신저): 카운트 소스 B 및 DM 캐릭터 프로필 상세 노출 surface 제공자. DM ship 전에도 소스 A 단독으로 본 PRD ship 가능. DM ship 시 소스 B 및 개인화 선톡 source 연동.
  • DEE-115 (DM 메모리/컨텍스트): 유대 데이터를 컨텍스트로 참조할 가능성이 높은 후속 PRD. 본 PRD는 이벤트 로그·총합 Bond Exp를 read API로 제공할 수 있는 형태로 적재 (스키마는 spec/구현 단계 확정).

References

  • Frontia UL wiki: wiki/foundation/ubiquitous-language.md — Character, Episode, Scene, Play 정의
  • Linear:
    • DEE-66 / DEE-79 [앱/웹] 에피소드 상세 페이지 내 캐릭터 정보 섹션 — 노출 surface
    • DEE-72 [앱] DM 메신저 기능 — 카운트 소스 B
    • DEE-115 [앱] DM 메모리/컨텍스트 — 유대 데이터를 컨텍스트로 참조할 후속 PRD
prd-review 보기

Review log

2026-05-13 (auto-review, agent 단독 적용)

prd-writer 직후 prd-review 1회. momo 부재 상황이라 메인 agent가 low-risk·obvious 정리만 적용, 진짜 product decision은 §7 OQ로 남김.

채택 (PRD 본문 갱신)

  • Q: 메인 지표 "적재율 100%"가 가설 검증 지표가 아니다 + 100%는 단일 PRD 도달 불가
    • A: 메인 지표를 적재 손실률 ≤ 정책 임계로 정정. 가설 1·2는 foundation 성격상 후속 PRD에서 검증한다고 §1.4에 명시.
    • → §1.4 가설 헤더 변경, §1.5 표·메인 지표 문장 교체.
  • Q: 가설 1 검증은 노출 surface 의존(DEE-66) — ship 순서 불명
    • A: §3-1에 "본 PRD 단독 ship 시 데이터만 쌓이고 노출 안 됨" 문장 + 부록 의존성에 명시.
    • → §3-1, 부록 의존성.
  • Q: 백엔드/시스템 §3-3은 API/저장소 설계라 PRD 범위 아님
    • A: §3-3 삭제. "단계 라벨/진척바 파생" 같은 비즈니스 룰만 §3-1로 흡수.
    • → §3-3 제거, §3-1 비즈니스 룰에 흡수.
  • Q: Negative spec 다수 ("어드민 화면 없음", "외부 시스템 연동 없음", "다른 팀 없음" 등)
    • A: §3-5 Out of scope로 통폐합. §3-2는 한 줄로 축소. 부록 의존성의 "없음" 라인 제거.
    • → §3-1, §3-2, §3-5, 부록.
  • Q: §🔍 검토 필요 / 🚨 / ⚠️ / ❓ 4개 메타 섹션이 §7 OQ와 중복
    • A: 모두 §7 OQ로 통합 + owner 필드로 외부 agent 호출 흡수. §🔍 섹션 전체 삭제.
    • → §7로 통합, 섹션 삭제.
  • Q: 부록 "진행 패턴 Spec → Design"은 SKILL 정의 메타
    • A: 삭제.
    • → 부록 Required artifacts.
  • Q: §7 OQ 중 단계명 카피(디자인/카피), retention 법무, 어드민 운영 의례는 PRD 단계 OQ 아님
    • A: 단계명 카피는 "단계 라벨 카피 동반 여부"로 PRD 단계 의사결정 1줄만 남김(spec에서 카피 확정). retention·어드민 OQ 삭제.
    • → §7.
  • Q: §1.5 가드레일 임계·베이스라인 placeholder
    • A: §7에 "허용 손실률 임계 + 가드레일 회귀 폭" OQ로 추가, 책임자 명시. 본문은 임계만 결정·수치는 출시 직전 채움 정책 명시.
    • → §1.5, §7.
  • Q: §5.2 로깅 이벤트 그룹·재사용 판단을 spec으로 미룸
    • A: event-docs.frontia.dev는 Cloudflare Access로 sprint-prep 세션에서 fetch 불가. 노트에 그 사실 명시 + §7에 momo 세션 확인 OQ 추가. 멘션·메시지 이벤트 자체는 "기존 재사용 가정"으로 표에서 빠짐.
    • → §5.2 노트, §7.
  • Q: 메인 지표 단위가 engagement·후속 ship 가능성이라는 가설과 불일치
    • A: 가설은 foundation 특성상 본 PRD 직접 검증 X로 §1.4 헤더에 명시. 메인 지표는 데이터 품질(적재 손실률)에 한정하는 것이 일관됨.
    • → §1.4, §1.5.

Skip

  • (없음 — momo 부재라 product decision은 모두 §7 OQ로 보존)

진짜 product decision으로 §7에 보존된 항목

  • 단계 곡선 함수 (선형/지수/수동, 단계 수)
  • 멘션 카운트 단위 (frame/scene/turn/episode 클리어당 N)
  • DM 메시지 단가 1:1 적정성
  • 단계 라벨 카피 동반 여부
  • 다른 surface 노출 후속 결정
  • 적재 손실률 임계 + 가드레일 회귀 폭
  • 로깅 이벤트 재사용 매핑 (Cloudflare Access 세션 필요)

momo 인라인 피드백 (criteria 후보)

  • (없음 — agent 단독 세션. criteria.md 갱신 보류, momo walk-through 시 재논의 권장.)

2026-05-15 (PM direction pass, agent 적용)

momo의 PM direction 메모를 기준으로 PRD 정합성 재검토. 핵심: DM 검증 속도 우선 + 친밀도는 단순/MVP + 데이터는 확장 가능하게. "완성된 관계 경험"이 아니라 재튜닝 가능한 관계 데이터 자산 + 최소 노출이 본 PRD의 성공 정의임을 명시.

채택 (PRD 본문 갱신)

  • Q: PRD 성공 정의가 모호 — "데이터 자산 + 최소 노출" vs "완성된 관계 경험"
    • A: 상단 메타에 박스 추가: "완성된 관계 경험 아님. 재튜닝 가능한 관계 데이터 자산 + 에피소드 상세 1곳 최소 노출까지."
    • → 상단 status 블록 직후.
  • Q: 데이터 모델이 "raw XP 단일 숫자"로 기술되어, 후속 정책 튜닝 시 재계산 불가 위험 → foundation의 확장성 요구 위배
    • A: §1.3에 옵션 1 정의 재정의(이벤트 로그 + 파생 총합 XP), 옵션 3(총합만 저장) 신규 기각. §3-1에 데이터 모델 (확장성 요구) 블록 신규 — 이벤트 로그 진실원천, 총합은 캐시, 불투명 단일 총합 저장 금지. Migration plan 항목도 "이벤트 로그 + 캐시"로 정정. Risks에 "총합만 저장 시 foundation 실패" 항목 추가.
    • → §1.3, §3-1, 부록 Required artifacts/Risks.
  • Q: +1/+1 XP가 MVP로 acceptable 하지만 cap/diminishing/volume balancing이 블로킹처럼 보일 수 있음
    • A: §3-1에 "MVP 단가 정책" 노트 — 출시 차단 아닌 정책 결정 게이트. §7 DM 단가 OQ를 "단가 + cap/diminishing/balancing"으로 확장하며 "ship 후 재계산 가능" 명시.
    • → §3-1, §7.
  • Q: 비로그인/0 XP 표시가 단정적으로 박혀 있음 — recommendation/open decision으로 격하 권장
    • A: §3-1 비즈니스 룰 문장을 "권장값" + "디자인/스펙에서 재검토"로 완화. §4 표 행도 동일. §7에 "비로그인 영역 표시 정책" OQ 신규.
    • → §3-1, §4, §7.
  • Q: Out of scope에 sentiment weighting + DM 메모리(DEE-115) 효과가 명시 안 됨
    • A: §3-5 Out of scope에 "감정/톤 분석 기반 점수 산출", "DM 메모리/컨텍스트 효과(DEE-115)" 추가. 가중치 룰 항목에 "이벤트 로그 보존으로 사후 도입 가능" 보강.
    • → §3-5.
  • Q: 의존성에 DEE-115 누락, DEE-79도 함께 언급 필요
    • A: 부록 의존성·References에 DEE-115 추가, DEE-66을 DEE-66/79로 병기.
    • → 부록.

Skip

  • Q: 가설 검증 지표를 본 PRD에서 더 단단히 만들 것
    • 사유: foundation 특성상 가설 1·2 직접 검증은 후속 PRD에서 한다는 이전 결정 유지. PM direction도 "complete relationship experience 아님"이라 일관.
  • Q: §5.2 로깅 이벤트 재정의
    • 사유: PM direction에 직접 신호 없음. 기존 §7 OQ(Cloudflare Access 세션 확인)로 충분.

본 세션에서 추가/강화된 §7 OQ

  • DM 메시지 단가 OQ → "단가 + cap/diminishing/소스간 volume balancing" 정책 게이트로 확장 (출시 차단 아님 명시).
  • 비로그인/XP=0 영역 표시 정책 (0 XP 노출 vs 영역 숨김) — 디자이너 + PM.

momo 인라인 피드백 (criteria 후보)

  • foundation/사전작업 성격 PRD는 "성공 정의"를 본문 상단에 박을 것 — "완성된 경험"으로 오독될 수 있는 PRD는 상단 박스로 scope를 좁혀 선언. (criteria 후보로 momo walk-through에서 컨펌 필요.)
  • 데이터 모델이 사후 재계산 가능한가 — foundation PRD는 raw 이벤트 보존 형태인지 명시적으로 검사 — 단일 총합/스칼라만 저장하는 형태는 정책 튜닝 시 데이터 리셋 비용. (criteria 후보.)

남은 PM 결정 (walk-through 필요)

  1. 단계 곡선 함수 (선형/지수/수동) + 단계 수.
  2. 멘션 카운트 단위 (frame/scene/turn/episode 클리어당 N).
  3. DM 단가 + cap/diminishing/balancing — MVP는 +1/+1로 ship, 정책은 ship 후 도입?
  4. 비로그인/XP=0 친밀도 영역 표시 정책.
  5. 단계 라벨 카피 동반 여부.
  6. 다른 surface 노출 후속 결정 (MY/카드/홈).
  7. 적재 손실률 임계 + 가드레일 회귀 폭.
  8. 로깅 이벤트 재사용 매핑 (Cloudflare Access 세션).

2026-05-20 (PM decision update, momo 요청 반영)

채택 (PRD 본문 갱신)

  • Q: Bond Exp 적립 단위에서 consumed_star / 3을 제거하고 star 소비량을 그대로 Exp로 적립하려면 기존 성장 밸런스가 깨지지 않는가?
    • A: 적립 단위가 3배 커지므로, 기존 성장 체감 속도를 유지하기 위해 일일 cap과 Lv threshold를 모두 3배 스케일한다.
    • → Exp 적립: consumed_star 자체(멀티 캐릭터 scene은 등장 캐릭터 수로 균등 분배), 일일 cap: 15,000 Bond Exp, Lv 공식: 300 × (N − 1)², max_level=200 유지.

남은 결정

  • 없음. 본 변경은 기존 성장 속도 의도를 유지하는 단위 재정의로 확정.

2026-05-20 Soul/Character terminology update

  • 상위 도메인 term을 Character Bond에서 Bond로 정렬.
  • Bond Exp/Level은 episode_scene_appearance와 dm_response_generated를 source별 저장 후 (user, Soul) 기준 aggregate.
  • 관계 Lv/progress는 linked Soul + DM Thread 조건에서만 노출.
  • Episode Character ↔ Soul mapping 변경에 따른 aggregate 변동은 별도 유저 안내/보상/롤백 없이 처리.

2026-05-22 (DM spec feedback 반영 — Soul 연결/선톡/노출 surface 정렬)

채택 (PRD 본문 갱신)

  • 제목을 [앱]에서 [서버]로 변경. 본 PRD의 핵심은 서버 foundation/Bond 이벤트 로그·집계이며, 앱/웹은 노출 surface로 명시.
  • 관계 Lv/progress 노출 surface를 DM 캐릭터 프로필 상세 + 에피소드 상세 Episode Character 정보 섹션 두 곳으로 정렬. 에피소드 surface는 linked Soul 조건을 사용하며 기존 DM Thread 필수 조건을 제거.
  • Bond Exp 적립 대전제를 star consumed → Bond Exp로 명시하고, 개인화 선톡도 유저 측 수신 성공 시 star가 차감되면 적립 source에 포함.
  • DM source 명칭은 dm_response_generated로 유지하고, spec 쪽의 애매한 dm_message 표현은 dm_response_generated 기준으로 맞춘다.
  • Soul 미연결 Episode Character side Exp 임시 적립 → Soul 연결 후 유저 컨텍스트 기반 데이터 패치/리드 시점 1회 이관 → Episode Character side reset 정책 추가.
  • Episode Character id 재발행/중복 migration 정책 추가: 새 id 발급 이후 신규 play/generation부터 새 id 기준 적립, 과거 play 소급 적립 없음.
  • 공식 300 × (N − 1)² 기준 주요 레벨 도달 필요 누적 Exp와 max 기준 소요일 표 추가. 평균 기준은 avg_daily_credited_exp 확정 후 산출하도록 보존.