Files

13 KiB

PRD: AI 캐릭터 크리에이터 기능 최소 연결

1. Overview

ChatCharacter가 기존 크리에이터 기능을 최소 변경으로 사용할 수 있도록, 모든 ChatCharacterMember(role = CREATOR)와 1:1로 연결하고 실제 사람 Member와 AI 캐릭터용 Member를 memberKind로 구분한다.


2. Problem

  • 현재 ChatCharacter는 AI 대화 주체로만 동작하고, 라이브/콘텐츠/커뮤니티/채널 후원/정산/알림 등 크리에이터 기능의 주체가 될 수 없다.
  • 기존 크리에이터 기능은 대부분 Member(role = CREATOR)member.id 기반 creatorId를 전제로 구현되어 있다.
  • ChatCharacter를 독립 소유자로 직접 도입하면 콘텐츠, 라이브, 후원, 정산, 랭킹, 알림, 차단, 팔로우 등 넓은 범위의 소유자 모델 변경이 필요하다.
  • 이번 변경은 기존 Member 기반 크리에이터 기능을 유지하면서, AI 캐릭터가 크리에이터 기능을 사용할 수 있는 최소 연결 구조가 필요하다.

3. Goals

  • MemberMemberKind를 추가해 실제 사람 Member와 AI 캐릭터용 Member를 구분한다.
  • 모든 기존 ChatCharacter에 대응되는 Member(role = CREATOR, memberKind = AI_CHARACTER)를 생성하고 1:1로 연결할 수 있는 마이그레이션 SQL을 준비한다.
  • 신규/기존 ChatCharacter는 크리에이터 기능 주체인 creatorMember를 가진다.
  • memberKind = AI_CHARACTER인 Member는 로그인할 수 없도록 차단한다.
  • memberKind = AI_CHARACTER인 Member는 유저-크리에이터 DM 생성 대상이 될 수 없도록 차단한다.
  • memberKind = AI_CHARACTER인 Member는 로그인과 DM을 제외하고 Member(role = CREATOR)가 사용할 수 있는 기존 크리에이터 기능을 사용할 수 있어야 한다.
  • AI 캐릭터용 Member의 표시 정보는 연결된 ChatCharacter의 이름, 프로필 이미지, 소개를 스냅샷으로 복사해 기존 Member 기반 화면과 쿼리를 재사용한다.
  • 기존 사람 크리에이터의 콘텐츠/라이브/커뮤니티/채널 후원/정산/알림 동작은 유지한다.

4. Non-Goals

  • 이번 범위에서 ChatCharacterMember와 동급의 별도 소유자 타입으로 만들지 않는다.
  • 이번 범위에서 creator_identity 같은 공통 크리에이터 소유자 테이블을 도입하지 않는다.
  • 이번 범위에서 공개 API의 기존 creatorId = member.id 의미를 변경하지 않는다.
  • 이번 범위에서 크리에이터 검색 결과 카테고리 개편은 구현하지 않는다.
  • 이번 범위에서 Member:ChatCharacter = 1:N 관계를 허용하지 않는다.
  • 이번 범위에서 AI 캐릭터용 Member의 직접 로그인, 직접 크리에이터 관리자 접속, 직접 DM 기능은 허용하지 않는다.
  • 이번 범위에서 AI 캐릭터용 콘텐츠/라이브/커뮤니티 대리 생성 API를 새로 설계하지 않는다.
  • 이번 범위에서 기존 정산 산식, 정산 비율, 랭킹 점수 산식은 변경하지 않는다.
  • 이번 범위에서 AI 캐릭터용 Member를 정산 관리자 화면에서 사람 크리에이터와 별도 목록 또는 별도 필터로 분리하지 않는다.

5. Target Users

  • 일반 사용자: AI 캐릭터와 AI 대화를 하고, AI 캐릭터 채널에 후원하거나 AI 캐릭터 콘텐츠를 소비하는 회원
  • 사람 크리에이터: 필요 시 자신의 Member에 연결된 ChatCharacter를 통해 AI 대화 기능을 제공하는 크리에이터
  • 운영/정산 담당자: AI 캐릭터용 Member를 기존 크리에이터 정산 흐름에서 식별하고 처리해야 하는 담당자

6. User Stories

  • 사용자는 모든 활성 ChatCharacter와 AI 대화를 시작하고 싶다.
  • 사용자는 AI 캐릭터 채널에도 기존 크리에이터 채널처럼 채널 후원을 하고 싶다.
  • 사용자는 AI 캐릭터가 업로드한 콘텐츠를 기존 콘텐츠와 같은 방식으로 보고 싶다.
  • 시스템은 AI 캐릭터용 Member가 실제 사람 계정처럼 로그인하거나 DM 대상이 되는 것을 막고 싶다.
  • 운영자는 사람 크리에이터와 AI 캐릭터용 크리에이터 Member를 데이터에서 명확히 구분하고 싶다.

7. Core Features

Feature A. MemberKind 도입

Requirements

  • MembermemberKind 필드를 추가한다.
  • MemberKind 값은 최소 다음 2개를 가진다.
    • HUMAN: 실제 사람 Member
    • AI_CHARACTER: AI 캐릭터 기능을 위해 생성된 내부 크리에이터 Member
  • memberKindNOT NULL이며 기본값은 HUMAN이다.
  • 기존 모든 Member 데이터는 DDL 기본값에 의해 memberKind = HUMAN이 된다.
  • 일반 회원가입, 관리자, 에이전트, 콘텐츠 관리자 등 실제 사람 계정은 memberKind = HUMAN을 사용한다.
  • memberKind = AI_CHARACTER인 Member도 role = CREATOR를 가진다.
  • 크리에이터 기능 가능 여부는 기존처럼 기본적으로 role = CREATOR를 기준으로 유지한다.
  • 사람 크리에이터 전용 기능 가능 여부는 role = CREATORmemberKind = HUMAN을 함께 기준으로 판단한다.
  • memberKind = AI_CHARACTER인 Member는 로그인과 DM을 제외한 팔로우, 채널 후원, 콘텐츠, 커뮤니티, 라이브, 정산, 알림 등 기존 CREATOR 기능의 대상이 될 수 있다.

Edge Cases

  • memberKind = HUMAN만으로 사람 크리에이터 여부를 판단하면 안 되며, 반드시 role = CREATOR 조건을 함께 확인해야 한다.
  • memberKind = AI_CHARACTER인 Member는 반드시 role = CREATOR여야 한다.

Feature B. ChatCharacterMember 1:1 연결

Requirements

  • ChatCharacter가 관계의 주인이며 creatorMember를 가진다.
  • 관계는 초기에는 1:1로 제한한다.
  • DB에는 chat_character.creator_member_id를 추가한다.
  • chat_character.creator_member_idmember.id를 참조한다.
  • chat_character.creator_member_id에는 unique 제약을 둔다.
  • ChatCharacter.creatorMember.role은 반드시 CREATOR여야 한다.
  • 기존 모든 ChatCharacter는 마이그레이션 후 creatorMember가 있어야 한다.
  • 기존 ChatCharacter 중 실제 사람 크리에이터와 연결해야 하는 데이터는 이번 마이그레이션 대상에 없다고 본다.
  • 기존 모든 ChatCharacter는 새 Member(role = CREATOR, memberKind = AI_CHARACTER)를 생성해 연결한다.

Edge Cases

  • 이미 연결된 ChatCharacter에 중복 creatorMember가 배정되면 안 된다.
  • 하나의 Member에 여러 ChatCharacter가 연결되면 안 된다.
  • 비활성 ChatCharacter도 기존 데이터 정합성을 위해 creatorMember 연결 대상에 포함한다.

Feature C. 기존 ChatCharacter용 Member 생성 마이그레이션

Requirements

  • 운영 DB 반영용 MySQL 기준 DDL과 backfill SQL을 작성한다.
  • 마이그레이션 SQL은 기존 ChatCharacter별로 AI 캐릭터용 Member를 생성할 수 있어야 한다.
  • 생성되는 AI 캐릭터용 Member는 다음 정책을 따른다.
    • role = CREATOR
    • memberKind = AI_CHARACTER
    • email = null
    • password = ""
    • nickname은 기본적으로 ChatCharacter.name 기준
    • profileImage는 기본적으로 ChatCharacter.imagePath 기준
    • introduce는 기본적으로 ChatCharacter.description 기준
  • AI 캐릭터용 Member의 nickname, profileImage, introduce는 기존 콘텐츠/라이브/커뮤니티/후원/정산/알림/팔로우/AGENT 소속 화면에서 별도 ChatCharacter JOIN 없이 표시하기 위한 스냅샷이다.
  • backfill 후 chat_character.creator_member_id가 없는 row가 0건인지 검증하는 SQL을 포함한다.
  • 검증 완료 후 chat_character.creator_member_idNOT NULL로 전환할 수 있어야 한다.

Edge Cases

  • ChatCharacter.name이 중복되더라도 Member 생성이 가능해야 한다.
  • AI 캐릭터용 Member의 로그인 차단은 email/password 값이 아니라 memberKind = AI_CHARACTER 정책으로 보장해야 한다.
  • 기존 ChatCharacter의 사람 크리에이터 수동 매핑은 이번 범위에서 제공하지 않는다.

Feature D. AI 캐릭터 표시 정보 동기화

Requirements

  • AI 캐릭터용 Member의 표시 정보는 연결된 ChatCharacter 값을 기준으로 유지한다.
  • ChatCharacter.nameMember.nickname에 동기화한다.
  • ChatCharacter.imagePathMember.profileImage에 동기화한다.
  • ChatCharacter.descriptionMember.introduce에 동기화한다.
  • ChatCharacter 생성 시 AI 캐릭터용 Member를 함께 생성하는 경우 같은 transaction 안에서 표시 정보를 복사한다.
  • ChatCharacter 수정 시 연결된 AI 캐릭터용 Member의 표시 정보도 같은 transaction 안에서 갱신한다.
  • memberKind = AI_CHARACTER인 Member의 표시 정보는 직접 수정 API가 아니라 ChatCharacter 생성/수정 흐름을 기준으로 관리한다.

Edge Cases

  • 동기화 대상 creatorMember가 없으면 저장을 실패시켜 데이터 불일치를 막아야 한다.
  • 연결된 creatorMember.memberKind != AI_CHARACTER인 경우, 사람 크리에이터의 프로필을 덮어쓰지 않도록 동기화 대상에서 제외하거나 별도 정책을 명확히 적용해야 한다.
  • 기존 Member 기반 화면은 AI 캐릭터 표시 정보를 조회할 때 별도 ChatCharacter JOIN을 추가하지 않는다.

Feature E. AI 캐릭터용 Member 로그인 차단

Requirements

  • memberKind = AI_CHARACTER인 Member는 모든 일반 로그인 흐름에서 인증 성공 상태가 되면 안 된다.
  • 크리에이터 관리자 로그인 흐름에서도 memberKind = AI_CHARACTER인 Member는 로그인할 수 없어야 한다.
  • 소셜 로그인 또는 토큰 재발급 흐름에서 AI 캐릭터용 Member가 세션/토큰을 얻을 수 있는 경로가 있으면 차단한다.
  • 차단 시 기존 인증 실패 응답 패턴을 우선 재사용한다.
  • AI 캐릭터용 Member는 로그인에 사용하지 않으므로 emailnull을 허용하고, password는 기존 소셜 회원 생성 패턴과 같이 빈 문자열을 사용할 수 있다.
  • 로그인 차단은 email/password 값이 아니라 memberKind = AI_CHARACTER 정책으로 보장한다.

Edge Cases

  • 기존 토큰을 이미 가진 AI 캐릭터용 Member가 있을 수 없도록 마이그레이션 시점과 배포 순서를 점검한다.
  • 후속 범위에서 관리자/콘텐츠 관리자가 AI 캐릭터용 콘텐츠를 등록하더라도, AI 캐릭터용 Member 자체가 로그인하는 것은 허용하지 않는다.

Feature F. AI 캐릭터용 Member DM 차단

Requirements

  • 유저-크리에이터 DM 생성 대상이 memberKind = AI_CHARACTER이면 DM 방을 생성하지 않는다.
  • 기존 사람 크리에이터는 ChatCharacter 연결 여부와 무관하게 DM이 가능해야 한다.
  • DM 차단 기준은 ChatCharacter 연결 여부가 아니라 Member.memberKind이다.

Edge Cases

  • memberKind = HUMAN인 사람 크리에이터가 ChatCharacter를 가진 경우에도 DM은 가능해야 한다.
  • memberKind = AI_CHARACTER인 Member가 role = CREATOR이더라도 DM은 불가능해야 한다.

8. Technical Constraints

  • Kotlin, Spring Boot 2.7.14, Java 17, Gradle Wrapper 구조를 유지한다.
  • 기존 공개 API의 creatorId 의미는 이번 범위에서 변경하지 않는다.
  • 기존 콘텐츠/라이브/커뮤니티/후원/정산 테이블의 소유자 컬럼은 Member 기준을 유지한다.
  • ChatCharacterMember 관계는 초기에는 ChatCharacter 단방향 OneToOne으로 구현한다.
  • 운영 DB 반영용 DDL은 MySQL 기준으로 작성한다.
  • DDL 컬럼에는 가능한 경우 COMMENT를 추가한다.
  • memberKind 기반 정책 판단은 중복 분기를 줄이기 위해 정책 함수 또는 명확한 서비스 검증으로 모은다.
  • 검색 결과 카테고리 개편은 이번 구현에서 제외하되, 향후 memberKind를 활용할 수 있도록 데이터 모델만 준비한다.

9. Data Migration Requirements

  • Phase 1 DDL
    • member.member_kindNOT NULL DEFAULT 'HUMAN'으로 추가
    • chat_character.creator_member_id nullable 추가
    • chat_character.creator_member_id FK 및 unique index 추가
  • Phase 2 backfill
    • 기존 모든 ChatCharacter별로 AI 캐릭터용 Member(role = CREATOR, memberKind = AI_CHARACTER)를 생성한다.
    • 생성된 Member를 chat_character.creator_member_id에 연결한다.
  • Phase 3 검증 및 제약 강화
    • member_kind = 'AI_CHARACTER' and role <> 'CREATOR' row가 0건인지 확인한다.
    • chat_character.creator_member_id is null row가 0건인지 확인한다.
    • chat_character.creator_member_idNOT NULL로 변경한다.

10. Metrics

  • 기존 ChatCharactercreator_member_id 누락 0건
  • memberKind = AI_CHARACTER이면서 role != CREATOR인 Member 0건
  • memberKind = AI_CHARACTER Member 로그인 성공 0건
  • memberKind = AI_CHARACTER Member 대상 DM 생성 성공 0건
  • 기존 사람 크리에이터의 DM, 콘텐츠 등록, 채널 후원 흐름 회귀 실패 0건

11. Open Questions

  • AI 캐릭터용 콘텐츠/라이브/커뮤니티 등록 운영 흐름은 이번 범위에서 구현하지 않으므로, 후속 범위에서 chatCharacterId 기반 대리 생성 API 정책을 별도로 정해야 한다.