Files
sodalive-android/docs/20260914_크리에이터의_리스너_DM_시작/prd.md
T

22 KiB

크리에이터의 리스너 DM 시작 PRD

문서 정보

항목 내용
문서 상태 구현 완료
작성일 2026-09-14
최종 수정일 2026-09-14
대상 제품 크리에이터의 리스너 DM 시작
작성자·결정권자 제품 담당자, Android 담당자
관련 API Contract 서버 CreateUserCreatorChatRoomRequest(recipientId?, creatorId?) 계약 제공됨
관련 구현 계획 docs/20260914_크리에이터의_리스너_DM_시작/plan-task.md
관련 review docs/20260914_크리에이터의_리스너_DM_시작/reviews/phase4-recipient-picker-review.md

요구사항 상태

상태 의미 구현 처리
확정 제품·기술 결정이 완료되어 구현 기준으로 사용 plan-task.md의 Task와 완료 증거로 추적
미결 제품·UX·운영 결정이 더 필요함 구현 전 확인하고 Decision Log에 누적
외부 의존 서버 계약·권한·배포 조건 확인이 필요함 담당 주체·영향·재개 조건 기록
제외 현재 릴리스에서 구현하지 않음 제외 이유와 후속 조건 기록

1. Overview

현재 리스너는 크리에이터 채널에서 크리에이터에게 바로 DM을 보낼 수 있지만, 크리에이터가 리스너에게 먼저 DM을 시작하는 진입점은 없다. 이 기능은 크리에이터가 메인 대화 탭에서 리스너를 찾고, 확인 팝업을 거쳐 기존 DM 방 생성 흐름으로 대화를 시작할 수 있게 한다.

현재 요구사항은 Phase 4까지 구현과 회귀 검증이 완료됐다. 이후 변경은 이 문서와 plan-task.md의 추가 Task로 추적한다.

2. Problem Statement

  • 크리에이터가 리스너에게 먼저 연락해야 하는 상황에서도 현재 앱에는 직접 DM 시작 경로가 없다.
  • 기존 DM 생성 API와 대화방 이동 흐름은 있으나, 메인 대화 탭에서 수신자를 선택하는 화면과 검색 흐름이 없다.
  • 검색 호출 조건과 빈 결과 문구, 확인 팝업 문구가 다국어 리소스로 정리되어야 한다.

문제를 해결했다는 판단은 크리에이터가 메인 대화 탭의 + 버튼에서 리스너를 선택하고, 보내기로 기존 DM 방 생성 API를 호출한 뒤 DM 방으로 이동하는 흐름이 검증되는 것으로 한다.

3. Goals

3.1 제품 목표

  • 크리에이터가 리스너에게 먼저 DM을 시작할 수 있다.
  • 기존 크리에이터 채널의 DM 생성 API와 방 이동 흐름을 재사용한다.
  • 검색 API 호출은 입력 2글자 이상과 debounce 조건을 만족할 때만 발생한다.

3.2 UX 목표

  • 메인 대화 탭 우측 하단에 홈 화면과 유사한 + 버튼을 제공한다.
  • 신규 수신자 선택 화면은 Figma 2372:23496의 검색바, 팔로우 섹션, 사용자 리스트 구조를 따른다.
  • 사용자 선택 시 Figma 2372:23521의 확인 팝업 구조를 따르고, v2 내부 공통 다이얼로그를 재사용한다.
  • 사용자에게 보이는 모든 신규 문구는 다국어 리소스로 관리한다.

4. Non-Goals

  • 신규 백엔드 endpoint를 추가하지 않는다.
  • DM 메시지 송수신 화면 자체의 UI, 소켓, 음성 메시지 전송 정책은 변경하지 않는다.
  • 팔로우/검색 결과의 프로필 상세, 차단, 팔로우 토글 정책은 이번 범위에서 새로 정의하지 않는다.
  • 레거시 파일 변경이 필요하면 구현 전에 별도 확인한다.

5. Target Users and Permissions

5.1 사용자

사용자 목표 주요 작업 사용 환경
크리에이터 리스너에게 먼저 DM을 시작 대화 탭 진입, 수신자 검색/선택, DM 방 생성 Android 앱
리스너 크리에이터로부터 시작된 DM을 수신 기존 DM 방에서 대화 Android 앱

5.2 권한

  • 인증 주체: 로그인한 사용자.
  • 허용 역할: 크리에이터 역할 사용자.
  • UI 노출 조건: 메인 대화 탭의 + 버튼과 신규 수신자 선택 화면은 크리에이터에게만 노출한다.
  • 서버 권한: 기존 DM 생성 API가 recipientId와 creatorId를 모두 수용하는 호환 계약으로 제공됐다.

6. 핵심 사용자 흐름

  1. 크리에이터가 메인 대화 탭에 진입한다.
  2. 우측 하단 + 버튼을 터치한다.
  3. 신규 수신자 선택 화면이 열리고, 최초 상태에서는 팔로우 리스트를 보여준다.
  4. 검색어를 입력하면 2글자 이상이며 debounce가 끝난 뒤 GET /member/search를 호출한다.
  5. 검색 결과가 없으면 화면 가운데에 사용자가 없어요.\n다른 이름으로 다시 검색해 주세요.를 표시한다.
  6. 사용자 리스트에서 사용자를 터치하면 확인 팝업을 표시한다.
  7. 취소를 터치하면 팝업만 닫고 API를 호출하지 않는다.
  8. 보내기를 터치하면 기존 크리에이터 채널 DM 생성과 같은 API를 호출하고 DM 방으로 이동한다.

7. 정보 구조와 라우팅

MainV2Activity
  ChatMainFragment
    + button (creator only)
    DmRecipientPickerActivity (v2 package)
      Follow list state
      Search result state
      Empty state
      Confirm dialog
    DmChatRoomActivity
  • 신규 화면은 kr.co.vividnext.sodalive.v2.main.chat.recipient.DmRecipientPickerActivity로 구현한다.
  • 신규 화면과 연결 하위 코드는 kr.co.vividnext.sodalive.v2 패키지 하위에 둔다.
  • 기존 채팅 방 이동은 DmChatRoomActivity의 기존 진입 방식을 재사용한다.

8. 기능 요구사항

8.1 진입점과 권한

ID 상태 요구사항 수용 기준 계약/Goal 연결
DM-001 확정 크리에이터는 메인 대화 탭에서 리스너에게 먼저 DM을 시작할 수 있다. 크리에이터 계정에서 신규 수신자 선택 화면에 진입할 수 있다. P2-T3
DM-002 확정 메인 대화 탭 우측 하단에 홈과 유사한 + 버튼을 추가한다. 버튼은 크리에이터 역할 사용자에게만 보이고, 비크리에이터에게는 보이지 않는다. P1-T1, P2-T3

8.2 수신자 선택 화면

ID 상태 요구사항 수용 기준 계약/Goal 연결
DM-003 확정 신규 화면은 Figma 2372:23496을 기준으로 검색바, 팔로우 섹션, 사용자 목록을 제공한다. 검색바 placeholder, 팔로우 섹션, 리스트 구조가 문서화되고 구현 전 기존 UI 패턴과 연결된다. P1-T1, P2-T3
DM-004 확정 화면 최초 진입 시 팔로우 리스트를 보여준다. 기존 팔로우 리스트 페이지와 동일한 API를 호출한다. P2-T2
DM-005 확정 검색어가 0~1자로 줄어든 경우 검색 모드를 해제하고 팔로우 리스트로 복귀한다. 0~1글자 입력에서는 /member/search 요청이 발생하지 않고 팔로우 리스트 상태가 표시된다. P2-T2

8.3 검색

ID 상태 요구사항 수용 기준 계약/Goal 연결
DM-006 확정 검색은 2글자 이상 입력했을 때 유저 검색 API를 호출한다. 0~1글자 입력에서는 /member/search 요청이 발생하지 않는다. P2-T2
DM-007 확정 검색 API는 GET /member/search를 사용하고 파라미터는 nickname이다. 요청 query가 nickname=입력값으로 전달된다. P2-T2
DM-008 확정 debounce를 적용해 글자를 치는 중에는 API를 호출하지 않는다. 연속 입력 중 요청 0회, 입력 중지 후 최종 검색어 요청 1회가 검증된다. P2-T2
DM-009 확정 debounce 대기 시간은 500ms로 한다. 입력 중지 후 500ms가 지난 최종 검색어로만 /member/search를 1회 호출한다. P2-T2

8.4 Empty와 다국어

ID 상태 요구사항 수용 기준 계약/Goal 연결
DM-010 확정 검색 결과가 없을 때 가운데 안내 문구를 표시한다. 사용자가 없어요.\n다른 이름으로 다시 검색해 주세요.가 중앙 empty state로 표시된다. P2-T2, P2-T3
DM-011 확정 모든 신규 문구는 다국어 리소스로 처리한다. 한국어, 일본어 등 기존 지원 언어 리소스에 신규 key가 추가된다. P2-T3
DM-012 확정 검색바 placeholder는 팬 이름을 입력하세요, 섹션 제목은 팔로워로 한다. Figma 기준 한국어 문구를 기존 지원 언어 리소스에 번역해 추가한다. P2-T3

8.5 확인 팝업과 DM 생성

ID 상태 요구사항 수용 기준 계약/Goal 연결
DM-013 확정 사용자 터치 시 Figma 2372:23521 기준 확인 팝업을 표시한다. 제목, 본문, 버튼이 지정 문구로 노출된다. P2-T3
DM-014 확정 팝업 다이얼로그는 v2 내부에서 사용하는 공통 다이얼로그를 재사용하고 문구만 변경한다. 신규 다이얼로그 구현 없이 기존 공통 다이얼로그 contract를 소비한다. P1-T1, P2-T3
DM-015 확정 팝업 제목은 메시지 보내기다. 신규 string resource로 관리된다. P2-T3
DM-016 확정 팝업 본문은 {{사용자이름}}에게 메시지를 보낼까요?다. 사용자 이름을 포맷 인자로 전달한다. P2-T3
DM-017 확정 팝업 버튼은 취소, 보내기다. 취소는 요청 없이 닫고, 보내기는 DM 생성 요청을 1회 호출한다. P2-T3
DM-018 확정 보내기는 크리에이터 채널에서 DM 보내기를 터치했을 때 호출되는 API와 동일한 API를 호출한다. 기존 DM 생성 endpoint와 방 이동 흐름을 재사용한다. P2-T1, P2-T3
DM-019 확정 DM 생성 요청 DTO는 recipientId와 creatorId를 모두 표현할 수 있어야 한다. 신규 크리에이터→리스너 DM은 recipientId만 보내고, 기존 크리에이터 채널 DM은 creatorId를 유지한다. P2-T1
DM-020 확정 DM 방에서 뒤로 돌아와 대화 탭이 다시 보이면 대화방 목록을 첫 페이지부터 갱신한다. 기존 표시 목록을 비운 뒤 현재 선택 filter로 첫 페이지를 다시 요청하고, 요청 cursor는 null이다. P3-T1
DM-021 확정 수신자 선택 화면은 Figma 2372:23496, 검색 결과 화면은 Figma 2372:23506과 동일한 상단 검색 toolbar, 섹션/검색결과 라벨, 리스트 행 구조를 사용한다. 별도 detail_toolbar를 쓰지 않고 뒤로가기와 검색 input이 같은 54dp 검색 toolbar 안에 배치되며, 검색 모드에서는 0건도 검색결과 0을 표시한다. P4-T1
DM-022 확정 수신자 선택 화면의 팔로워 목록이 0명이면 팔로워 섹션 문구를 표시하지 않는다. 팔로워 모드라도 표시할 수신자가 0명이면 팔로워 라벨이 숨겨진다. P5-T1
DM-023 확정 검색결과 0과 팔로워 문구 크기를 통일하고, 검색결과 숫자만 gray/500으로 한다. 두 라벨은 같은 typography style을 사용하고, 검색결과 라벨의 숫자 범위에만 @color/gray_500 span을 적용한다. P5-T1

9. UI/UX Expectations

9.1 Figma 근거

항목 Figma node 확인 내용
수신자 선택 화면 2372:23496 상단 status bar, 뒤로가기, 검색바, 팔로워 섹션, 사용자 리스트
수신자 검색 결과 화면 2372:23506 뒤로가기와 검색 input이 같은 검색 toolbar, 검색결과 N sort-bar, 검색 결과 리스트
확인 팝업 2372:23521 제목 메시지 보내기, 본문 {{사용자이름}}에게 메시지를 보낼까요?, 버튼 취소/보내기

9.2 화면 상태

  • 최초 로딩: 기존 팔로우 목록 API 로딩 정책을 따른다.
  • 팔로우 목록 empty: 기존 팔로우 목록 페이지 정책을 확인 후 재사용한다.
  • 팔로우 목록 count: 팔로워가 0명이면 팔로워 섹션 문구를 숨긴다.
  • 검색 결과 empty: DM-010 문구를 중앙에 표시한다.
  • 검색 결과 count: 검색 결과가 0건이어도 Figma 2372:23506 위치에 검색결과 0을 표시한다.
  • 검색 결과 count style: 팔로워 라벨과 같은 문구 크기를 사용하고 숫자만 gray/500 색상으로 표시한다.
  • 검색 오류: 기존 검색/목록 오류 toast 또는 empty 정책을 확인 후 최소 변경으로 맞춘다.
  • 보내기 진행 중: 중복 터치를 막고 기존 로딩/비활성화 패턴을 따른다.

10. API 계약

10.1 알려진 기존 코드 근거

목적 기존 근거 확인된 내용
채팅 탭 ChatMainFragment 메인 대화 탭, 필터, 채팅방 목록 진입점
DM 생성 API DmChatApi.createDmChatRoom POST /api/v2/user-creator-chat/rooms/create
DM 요청 생성 DmChatRepository.createOrGetRoom(token, creatorId) 현재 기존 크리에이터 채널 DM 경로에서 CreateDmChatRoomRequest(creatorId = creatorId) 생성
기존 크리에이터 DM 이동 ChatActionCommand.DmCreator, DmChatRoomActivity.newIntentByCreatorId 크리에이터 채널에서 기존 DM 방 진입에 사용
유저 검색 UserApi.searchUser, UserRepository.searchUser GET /member/search, query nickname
검색 참고 구현 SelectMessageRecipientViewModel.searchUser nickname.length > 1 조건은 있으나 debounce는 별도 확인 필요
팔로우 목록 FollowingCreatorRepository.getFollowedCreatorAllList 기존 팔로우 목록 API 재사용 후보

10.2 서버 제공 계약

ID 상태 제공 계약 담당 주체 구현 영향 구현 기준
EXT-001 해결 CreateUserCreatorChatRoomRequest(recipientId: Long? = null, creatorId: Long? = null) 제공. 서버는 둘 다 있으면 같은 값이어야 하며, recipientId ?: creatorId를 수신자 member ID로 사용한다. 서버/API 담당자 신규 리스너 DM은 recipientId, 기존 크리에이터 채널 DM은 creatorId를 사용할 수 있다. 클라이언트 DTO는 두 필드를 모두 nullable로 표현하고 호출 경로별로 하나만 채운다.

11. 보안과 데이터 취급

  • 인증 header는 기존 repository 정책을 재사용한다.
  • token, Authorization header, 내부 사용자 식별자는 log, Toast, 문서 fixture에 직접 노출하지 않는다.
  • 검색어와 사용자 이름은 화면 표시와 API 요청에만 사용하고 별도 저장하지 않는다.
  • /member/search API가 반환한 사용자는 앱에서 추가 필터 없이 모두 선택 가능하게 둔다.
  • DM 방 복귀 갱신은 기존 채팅 목록 첫 페이지 API를 재사용하고 token, 내부 식별자를 log·Toast에 노출하지 않는다.

12. 성능과 품질 요구사항

  • 검색 API는 2글자 이상과 500ms debounce 완료 조건을 모두 만족할 때만 호출한다.
  • 연속 입력 중 중간 검색어 요청을 보내지 않는다.
  • 검색어가 0~1자로 줄어들면 검색 모드를 해제하고 팔로우 리스트로 복귀한다.
  • 동일 화면 내 팔로우 목록과 검색 결과 상태 전환이 명확해야 한다.
  • DM 방 복귀 후 대화 탭 목록 갱신은 기존 pagination 상태를 첫 페이지 기준으로 초기화한다. 이 저장소의 v2 대화 목록은 cursor 기반이므로 page 0은 cursor = null 요청을 의미한다.
  • 수신자 선택 화면의 Figma 정합성은 Android XML 구조/source test와 resource compile로 검증하고, View 크기·constraint 속성 자체를 unit/UI test에서 직접 검증하지 않는다.
  • 신규 테스트는 app/src/test의 로직/local unit test만 계획한다.
  • app/src/androidTest, connectedDebugAndroidTest, 기기·에뮬레이터 UI 조작, 스크린샷·시각 QA는 사용자가 별도로 요청하기 전까지 범위에서 제외한다.

13. 성공 기준

13.1 기능 수용 기준

  • 크리에이터에게만 메인 대화 탭 + 버튼이 보인다. (DM-001, DM-002)
  • 신규 화면 최초 진입 시 기존 팔로우 리스트 API를 호출한다. (DM-004)
  • 검색은 2글자 이상과 debounce 완료 후에만 /member/search?nickname=을 호출한다. (DM-006~DM-009)
  • 검색 결과가 없으면 지정 empty 문구를 중앙에 표시한다. (DM-010)
  • 사용자 선택 후 팝업에서 보내기를 터치하면 recipientId로 기존 DM 생성 API를 호출하고, 기존 크리에이터 채널 DM은 creatorId로 유지된다. (DM-013~DM-019)
  • DM 방에서 뒤로 돌아오면 대화 탭의 기존 목록이 비워지고 현재 filter의 첫 페이지가 다시 표시된다. (DM-020)
  • 수신자 선택 화면 상단이 Figma 검색 toolbar 구조와 일치하고, 검색 결과가 0건이어도 검색결과 0이 표시된다. (DM-021)
  • 팔로워가 0명이면 수신자 선택 화면의 팔로워 라벨이 표시되지 않는다. (DM-022)
  • 검색결과 0과 팔로워 라벨의 문구 크기가 같고 검색결과 숫자만 gray/500 색상이다. (DM-023)

13.2 추적성 완료 기준

  • 모든 확정 요구사항이 plan-task.md의 Phase/Task에 연결된다.
  • 서버 제공 계약 EXT-001이 DM-019와 plan-task.md의 P2-T1 구현 기준에 반영돼 있다.

14. Resolved Questions

ID 상태 결정 사항 근거 결정 주체 결정일 영향 Goal
OQ-001 확정 debounce 대기 시간은 500ms로 한다. 사용자 인터뷰 답변 제품/Android 담당자 2026-09-14 P2-T2
OQ-002 확정 검색어가 0~1자로 줄어들면 팔로우 리스트로 복귀한다. 사용자 인터뷰 답변 제품 담당자 2026-09-14 P2-T2
OQ-003 확정 /member/search API 결과는 앱에서 추가 필터 없이 모두 선택 가능하게 둔다. 사용자 인터뷰 답변 제품/서버 담당자 2026-09-14 P2-T2, P2-T3
OQ-004 확정 Figma 한국어 문구 팬 이름을 입력하세요, 팔로워, 사용자가 없어요.\n다른 이름으로 다시 검색해 주세요.를 최종 문구로 한다. 사용자 인터뷰 답변 제품/번역 담당자 2026-09-14 P2-T3
OQ-005 확정 레거시 수정이 필요하면 기능에 필요한 최소 수정은 허용한다. 사용자 인터뷰 답변 사용자/Android 담당자 2026-09-14 전체

15. 요구사항 추적표

요구사항 범위 계획 Phase Goal 자동 검증 수동 검증
DM-001~002 2 P2-T3 역할별 진입 판단 local unit test 코드 구현 단계에서 앱 흐름 확인
DM-003~005 1, 2 P1-T1, P2-T2, P2-T3 상태 mapper/ViewModel test 코드 구현 단계에서 화면 확인
DM-006~009 2 P2-T2 검색 길이/debounce/request test 없음
DM-010~012 2 P2-T2, P2-T3 empty state/resource mapping test 코드 구현 단계에서 문구 확인
DM-013~019 2 P2-T1, P2-T3 request serialization, dialog action, navigation test 코드 구현 단계에서 팝업 확인
DM-020 3 P3-T1 Fragment source wiring test, ViewModel first-page reset regression test 사용자가 확인한 뒤로가기 흐름
DM-021 4 P4-T1 수신자 layout/source test, 검색 결과 count ViewModel test Figma screenshot 대조
DM-022 5 P5-T1 팔로워 라벨 표시 조건 source test 없음
DM-023 5 P5-T1 수신자 layout typography와 숫자 color span source test 없음

16. Decision Log

날짜 ID 상태 결정 근거 영향 요구사항·계약·Goal
2026-09-14 DEC-001 확정 이번 세션에서는 문서만 생성하고 코드 구현은 하지 않는다. 사용자 요청 전체
2026-09-14 DEC-002 확정 메인 대화 탭의 + 버튼과 신규 DM 시작 화면은 크리에이터에게만 노출한다. 사용자 인터뷰 답변 DM-001, DM-002, P2-T3
2026-09-14 DEC-003 확정 검색 API는 GET /member/search와 nickname 파라미터를 사용한다. 사용자 요청과 기존 UserApi.searchUser 확인 DM-006~DM-008, P2-T2
2026-09-14 DEC-004 정정 서버 계약 확인 전에는 CreateDmChatRoomRequest.creatorId를 recipientId로 변경하는 방향으로 계획했다. 사용자 요청 DM-019, EXT-001, P2-T1
2026-09-14 DEC-005 확정 검색 debounce 대기 시간은 500ms로 한다. 사용자 인터뷰 답변 DM-008, DM-009, P2-T2
2026-09-14 DEC-006 확정 검색어가 0~1자로 줄어들면 팔로우 리스트로 복귀한다. 사용자 인터뷰 답변 DM-005, P2-T2
2026-09-14 DEC-007 확정 /member/search API 결과는 앱에서 추가 필터 없이 모두 선택 가능하게 둔다. 사용자 인터뷰 답변 P2-T2, P2-T3
2026-09-14 DEC-008 확정 Figma 한국어 문구를 최종 문구로 확정하고 기존 지원 언어 리소스에 번역을 추가한다. 사용자 인터뷰 답변 DM-010~DM-012, P2-T3
2026-09-14 DEC-009 확정 레거시 수정이 필요하면 기능에 필요한 최소 수정은 허용한다. 사용자 인터뷰 답변 전체
2026-09-14 DEC-010 확정 서버가 recipientId와 기존 creatorId를 모두 수용하는 호환 계약을 제공했다. 신규 크리에이터→리스너 DM은 recipientId, 기존 크리에이터 채널 DM은 creatorId를 사용한다. 서버 변경 공유 DM-019, EXT-001, P2-T1
2026-09-14 DEC-011 확정 DM 방에서 뒤로 돌아와 대화 탭이 다시 보이면 현재 filter의 첫 페이지를 재조회한다. page 0은 cursor 기반 API의 cursor = null로 처리한다. 사용자 확인 및 추가 요청 DM-020, P3-T1
2026-09-14 DEC-012 확정 수신자 선택 화면은 Figma 2372:23496, 검색 결과 화면은 Figma 2372:23506과 동일한 검색 toolbar와 검색결과 N 라벨을 사용한다. 사용자 지적 및 Figma 재확인 DM-021, P4-T1

17. 변경 관리

  • 요구사항 변경 시 Decision Log에 변경 이유와 날짜를 기록한다.
  • 관련 요구사항 상태, 수용 기준, 계획 Task를 코드 변경 전에 갱신한다.
  • 기존 결정과 검증 기록은 삭제하거나 덮어쓰지 않는다.
  • 서버 계약이 다시 변경되면 구현 전에 EXT-001 상태를 갱신하고 사용자에게 확인한다.