Files
voiceon-character-admin/docs/20260806_수정요청변경필드만전송/prd.md

18 KiB

수정 요청 변경 필드 전송 PRD

문서 정보

항목 내용
문서 상태 구현 기준 확정
작성일 2026-08-06
최종 수정일 2026-08-06
대상 제품 AI 캐릭터 관리자 웹 수정 요청 최적화
작성자·결정권자 작성자: Codex / 결정권자: 사용자
관련 API Contract api-contract.md
관련 구현 계획 plan-task.md
관련 review 없음 — 구현 완료 후 reviews/에 추가

요구사항 상태

상태 의미 구현 처리
확정 제품·기술 결정이 완료되어 구현 기준으로 사용 plan-task.md의 Task와 완료 증거로 추적
미결 제품·UX·운영 결정이 더 필요함 권고안과 결정 주체·시점을 기록하고 임의 구현 금지
외부 의존 프론트엔드 밖의 계약·권한·환경 제공이 필요함 담당 주체·영향·재개 조건을 기록하고 추정 구현 금지
권고 미결 항목에 대한 현재 추천안 확정 전 계약이나 수용 기준으로 사용하지 않음
제외 현재 범위에서 구현하지 않기로 결정 제외 이유와 후속 조건을 Decision Log에 기록

문서 우선순위와 갱신 순서

  1. 사용자·제품 결정은 이 PRD에 기록한다.
  2. request payload 규칙은 api-contract.md에 기록한다.
  3. 구현 범위·순서·완료 증거는 plan-task.md에 기록한다.
  4. 요구사항 변경 시 Decision Log → 요구사항·수용 기준 → API Contract → 구현 계획 순서로 갱신한다.
  5. 기존 결정과 검증 기록은 삭제하거나 덮어쓰지 않고 정정 기록을 누적한다.

1. Overview

관리자가 AI 캐릭터, 오디오 콘텐츠, 커뮤니티 게시글, 시리즈, FanTalk 답글을 수정하면 프론트엔드는 현재 값 전체가 아니라 최종적으로 변경된 필드만 기존 수정 endpoint에 전송한다. 기존 화면, HTTP method, multipart 구조, 인증·응답·오류 계약은 유지하고 request payload 생성과 무변경 저장 동작만 바꾼다.

2. Problem Statement

현재 관리자는 다음 문제를 겪는다.

  • 한 필드만 수정해도 화면이 보유한 다른 수정 가능 값이 함께 전송된다.
  • 사용자가 건드리지 않은 값까지 서버에 다시 기록될 수 있어 동시 변경을 덮어쓸 위험과 payload 확인 비용이 커진다.
  • 일부 화면은 이미 특정 필드만 생략하지만, 도메인마다 규칙이 달라 변경 필드 전송 여부를 일관되게 검증하기 어렵다.

문제를 해결했다는 판단은 각 수정 화면에서 한 필드만 바꿨을 때 request JSON에 그 필드만 존재하고, 변경이 없을 때 저장 버튼이 비활성화되며 mutation 요청이 0건인 것으로 한다.

3. Goals

3.1 제품 목표

  • 다섯 수정 기능이 실제 변경 필드와 새로 선택한 파일만 전송한다.
  • 값 삭제는 기존 nullable 계약에 맞는 null을 전송하고, 미변경은 key 생략으로 구분한다.
  • 변경 후 원래 값으로 되돌리면 변경 없음으로 판정해 불필요한 mutation을 만들지 않는다.

3.2 UX 목표

  • 변경 사항이 없으면 저장 버튼을 비활성화해 요청이 발생하지 않음을 사전에 알린다.
  • 유효한 변경이 있으면 기존 저장 중·성공·실패·중복 제출 방지 동작을 유지한다.
  • 기존 반응형 capability, keyboard 동작, label·오류 연결과 focus 정책을 회귀시키지 않는다.

4. Non-Goals

  • 기존 PUT endpoint를 PATCH로 바꾸지 않는다.
  • backend DTO, response, 오류 status/key 또는 저장 로직을 변경하지 않는다.
  • 생성, 비활성화, 게시글 고정 전환, 시리즈 순서 변경, FanTalk 원글 삭제 payload는 변경하지 않는다.
  • 수정 화면에 없는 필드를 새로 노출하지 않는다.
  • 새 dependency, 범용 form library 또는 전역 diff framework를 도입하지 않는다.

Non-Goal 변경 시 Decision Log와 plan-task.md 범위를 먼저 갱신한다.

5. Target Users and Permissions

5.1 사용자

사용자 목표 주요 작업 사용 환경
인증된 관리자 선택한 리소스의 의도한 값만 안전하게 수정 캐릭터·오디오 콘텐츠·커뮤니티 게시글·시리즈·FanTalk 답글 수정 기존 기능별 지원 viewport

5.2 권한

  • 인증 주체: 기존 관리자 bearer session
  • 허용 역할: 기존 각 수정 endpoint의 관리자 권한
  • 거부 조건: 기존 401·403 및 공통 인증 만료 정책 유지
  • 리소스 소유권: path의 characterId와 각 resource ID 기준 서버 검증 유지
  • read-only 조건: 비활성 캐릭터와 모바일 mutation 제한 등 기존 기능별 capability 유지

6. 핵심 사용자 흐름

  1. 관리자가 기존 상세·목록에서 수정 화면 또는 Sheet를 연다.
  2. 프론트엔드는 조회 응답을 수정 기준값으로 보존한다.
  3. 관리자가 하나 이상의 필드 또는 교체 파일을 변경한다.
  4. 프론트엔드는 기존 직렬화 규칙을 적용한 현재 값과 기준값을 필드별로 비교해 변경 필드만 request에 넣는다.
  5. 저장 성공·실패와 다음 화면 이동은 기존 기능 동작을 유지한다.

변경 필드가 없으면 저장 버튼은 비활성화되고 mutation 요청은 발생하지 않는다. 파일만 변경한 multipart 수정은 파일 파트와 빈 JSON object인 request: {}를 전송한다.

7. 정보 구조와 라우팅

/ai-characters/:characterId/edit
/ai-characters/:characterId/audio-contents/:contentId/edit
/ai-characters/:characterId/community-posts          # 목록 내 게시글 Sheet
/ai-characters/:characterId/series/:seriesId/edit
/ai-characters/:characterId/fan-talks                # 목록 내 답글 Sheet
  • route, path parameter, query parameter와 성공 후 이동 위치는 변경하지 않는다.
  • 커뮤니티 게시글과 FanTalk 답글은 별도 수정 route 없이 기존 Sheet에서 수정한다.
  • 직접 링크·새로고침·존재하지 않음·비활성 리소스 처리는 기존 정책을 유지한다.

8. 기능 요구사항

8.1 공통 변경 감지와 전송

ID 상태 요구사항 수용 기준 계약/Goal 연결
DIFF-001 확정 수정 request JSON은 최종 변경 필드만 포함한다. 한 필드 변경 시 해당 key만 존재하고 미변경 key는 0개다. API Contract §2, P1-T1~P1-T5
DIFF-002 확정 변경 여부는 각 기능의 기존 trim·빈값→null·list 직렬화 규칙을 현재 값과 기준값에 동일하게 적용한 뒤 판정한다. 공백 정리 후 원래 값과 같거나 변경 후 되돌린 필드는 생략된다. API Contract §1.2, P1-T1~P1-T5
DIFF-003 확정 필드 삭제는 계약상 삭제 의미인 null을 보내고 미변경은 key를 생략한다. nullable 값을 비우면 {field:null}, 건드리지 않으면 field key가 없다. API Contract §1.3, P1-T1, P1-T4
DIFF-004 확정 변경 필드와 교체 파일이 모두 없으면 저장 버튼을 비활성화하고 mutation을 호출하지 않는다. 최초 진입과 변경 후 원복 상태에서 저장 버튼 disabled, PUT 0건이다. API Contract §1.4, P1-T1~P1-T5
DIFF-005 확정 파일만 바뀐 multipart 수정은 교체 파일과 빈 request JSON object를 보낸다. 파일 파트 1개, request {}, 다른 JSON key 0개다. API Contract §1.5, P1-T1~P1-T4

8.2 기능별 수정 payload

ID 상태 요구사항 수용 기준 계약/Goal 연결
CHAR-001 확정 캐릭터 수정은 변경된 프로필·선택·반복 필드와 새 profile image만 전송한다. name만 변경하면 request는 {name}이고 region, isActive와 미변경 필드는 없다. API Contract §2.1, P1-T1
AUDIO-001 확정 오디오 콘텐츠 수정은 변경된 title, detail, tags, price와 새 cover image만 전송한다. detail만 변경하면 request는 {detail}이며 화면에 없는 boolean 필드는 없다. API Contract §2.2, P1-T2
COMM-001 확정 커뮤니티 게시글 수정 저장은 변경된 content, isCommentAvailable, isAdult와 새 post image만 전송한다. content만 변경하면 request는 {content}이고 isFixed는 없다. API Contract §2.3, P1-T3
SERIES-001 확정 시리즈 수정은 변경된 기본·enum·nullable 필드와 새 image만 전송한다. title만 변경하면 request는 {title}이고 이미 부분 적용된 state 포함 다른 미변경 필드는 없다. API Contract §2.4, P1-T4
FANTALK-001 확정 FanTalk 답글 수정은 기존 답글과 다른 content만 전송한다. 변경 시 {content} 1개, 미변경 시 수정 버튼 disabled와 PUT 0건이다. API Contract §2.5, P1-T5

8.3 공통 파일·데이터 정책

ID 상태 요구사항 수용 기준 계약/Goal 연결
FILE-001 확정 새 파일을 선택하지 않으면 기존 이미지·커버를 유지하고 파일 파트를 생략한다. 미선택 수정 request에서 관련 파일 part가 없다. API Contract §1.5, P1-T1~P1-T4
DATA-001 확정 숫자, boolean, enum, 배열과 객체 배열은 타입을 유지한 채 비교·전송한다. false, 0, 빈 값 삭제용 null이 누락되지 않고 배열 변경은 전체 해당 필드 값으로 전송된다. API Contract §1.3, P1-T1~P1-T4
DATA-002 확정 원작 미선택·선택 해제 시 originalWorkId key를 생략하는 기존 계약을 유지한다. 기존 serializeCharacterRequest 계약 test가 유지되고 원작 연결 해제 동작은 새로 만들지 않는다. API Contract §2.1, P1-T1

9. 반응형 기능 범위

기능 Desktop Tablet Mobile 비고
캐릭터·오디오 콘텐츠·시리즈 수정 허용 허용 기존 조회 전용 기존 직접 route 차단 유지
커뮤니티 게시글 수정 허용 허용 기존 capability 유지 기존 Sheet 정책 유지
FanTalk 답글 수정 허용 허용 허용 기존 Sheet 정책 유지
  • 이번 변경으로 viewport breakpoint나 action 노출 정책을 바꾸지 않는다.
  • 기존 최소 viewport, 200% zoom, touch target과 virtual keyboard 검증을 회귀 Gate로 사용한다.

10. UI/UX Expectations

10.1 디자인과 component 원칙

  • 기존 component와 design token을 그대로 사용한다.
  • 수정용 payload는 각 도메인의 기존 form serializer 또는 component에서 계산한다.
  • 새 dependency나 범용 diff abstraction을 만들지 않고 기능별 DTO 의미를 코드 가까이에 둔다.

10.2 화면 상태

  • 최초 진입과 모든 변경을 원복한 상태에서는 저장 버튼을 disabled로 표시한다.
  • 파일 준비·저장 pending·오류·성공 상태와 중복 제출 방지는 기존 동작을 유지한다.
  • payload 생성 결과와 저장 버튼 활성화 조건은 같은 hasChanges 판정을 사용한다.

10.3 접근성

  • disabled 상태는 native disabled 속성으로 노출한다.
  • 기존 visible label, 연결 오류, keyboard focus 순서와 성공·오류 live region을 유지한다.
  • 지원 viewport와 200% zoom에서 핵심 control이 가려지지 않고 axe critical·serious 위반 0건을 유지한다.

11. API 계약

11.1 공통 규칙

  • base URL·인증 header·locale·성공 envelope·오류 envelope는 기존 정식 OpenAPI를 유지한다.
  • HTTP method는 기존 PUT을 유지한다.
  • 캐릭터·오디오 콘텐츠·커뮤니티 게시글·시리즈는 multipart/form-datarequest JSON part를 유지한다.
  • FanTalk 답글은 application/json을 유지한다.
  • request field의 생략은 미변경, 명시적 null은 해당 DTO가 정의한 값 삭제를 의미한다.

11.2 Endpoint 추적

요구사항 Method Path 계약 상태 API Contract 소유 Goal
CHAR-001 PUT /api/v2/admin/ai-characters/{characterId} 제공됨 §2.1 P1-T1
AUDIO-001 PUT /api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId} 제공됨 §2.2 P1-T2
COMM-001 PUT /api/v2/admin/ai-characters/{characterId}/community-posts/{postId} 제공됨 §2.3 P1-T3
SERIES-001 PUT /api/v2/admin/ai-characters/{characterId}/series/{seriesId} 제공됨 §2.4 P1-T4
FANTALK-001 PUT /api/v2/admin/ai-characters/{characterId}/fan-talks/{fanTalkId}/replies/{replyId} 제공됨 §2.5 P1-T5

11.3 외부 제공 대기 계약

없음. 정식 OpenAPI에서 대상 update field가 모두 optional이고 현재 프론트엔드 schema도 부분 request를 허용한다.

12. 보안과 데이터 취급

  • 인증 저장·만료 lifecycle과 401·403 처리는 기존 공통 API client 정책을 유지한다.
  • token, 파일 본문, signed URL과 관리자 입력 전문을 새 log·분석 이벤트에 기록하지 않는다.
  • 파일 확장자·MIME·크기·crop 검증과 resource ownership 검증을 변경하지 않는다.
  • 부분 request를 이유로 client가 권한 또는 서버 validation을 대신하지 않는다.
  • 감사 로그 추가는 이번 범위에 포함하지 않는다.

13. 성능과 품질 요구사항

  • payload 크기는 같거나 작아야 하며 미변경 저장 network 요청은 0건이어야 한다.
  • 변경 판정은 현재 form field 수에 대한 동기 비교로 처리하고 새 network 조회나 dependency를 추가하지 않는다.
  • mutation single-flight, 파일 준비 취소·오류·재시도와 기존 browser 지원 범위를 유지한다.
  • test stack은 Vitest·Testing Library·Playwright mock E2E, TypeScript typecheck, ESLint, Vite production build를 사용한다.
  • backend 구현 전 mock fallback은 필요하지 않다. 기존 server/mock mode 경계를 유지하고 production 자동 mock fallback을 추가하지 않는다.

14. 성공 기준

14.1 기능 수용 기준

  • 다섯 수정 기능에서 한 필드 변경 request는 해당 key만 포함한다. (DIFF-001, P1-GATE)
  • nullable 필드 삭제와 미변경 생략이 구분된다. (DIFF-003, P1-T1, P1-T4)
  • 파일 미변경은 파일 part 생략, 파일만 변경은 파일 part와 request: {}를 전송한다. (DIFF-005, FILE-001)
  • 최초 진입과 변경 후 원복 상태에서 저장 버튼이 disabled이고 mutation 요청이 없다. (DIFF-004)
  • 기존 생성·비활성화·고정·순서·삭제 흐름이 회귀하지 않는다. (P1-GATE)

14.2 UI/UX 수용 기준

  • 기존 loading·error·success·pending 상태가 유지된다.
  • keyboard-only로 기존 수정 흐름을 완료할 수 있다.
  • 기존 지원 viewport와 200% zoom에서 핵심 control이 가려지지 않는다.
  • axe critical·serious 위반이 0건이다.

14.3 추적성 완료 기준

  • 모든 확정 요구사항이 API Contract와 하나 이상의 Task·Goal 완료 증거로 연결된다.
  • 각 구현 Task에 RED·GREEN·REFACTOR 결과가 Progress에 누적된다.
  • Phase Gate의 자동·수동 payload 검증 결과가 기록된다.
  • 미결·외부 의존·제외 상태의 새 항목이 생기면 담당·영향·재개 조건 또는 Decision Log가 추가된다.

15. Open Questions

열린 질문 없음.

인터뷰 결과:

  • 최종 모호성: 0.07
  • 명확성: Goal 1.00, Scope 0.85, Constraints 0.90, Success 0.90, Context 1.00
  • 확정 결정: 변경 필드만 전송하며, 변경이 없으면 저장 버튼 비활성화와 mutation 요청 0건

16. 요구사항 추적표

요구사항 범위 API Contract 계획 Phase Goal 자동 검증 수동 검증
DIFF-001~005, FILE-001, DATA-001 §1 1 P1-T1~P1-T5, P1-GATE 기능별 form·contract test DevTools Network payload·무요청 확인
CHAR-001, DATA-002 §2.1 1 P1-T1 Character edit/API test 캐릭터 단일 필드·파일 수정
AUDIO-001 §2.2 1 P1-T2 Audio form/API test 오디오 단일 필드·cover 수정
COMM-001 §2.3 1 P1-T3 Community Sheet/API test 게시글 단일 필드·image 수정
SERIES-001 §2.4 1 P1-T4 Series form/API test 시리즈 단일 필드·image 수정
FANTALK-001 §2.5 1 P1-T5 FanTalk reply/API test 답글 변경·무변경 수정

17. Decision Log

날짜 ID 상태 결정 근거 영향 요구사항·계약·Goal
2026-08-06 DEC-001 확정 수정 request는 HTTP method를 바꾸지 않고 최종 변경 필드만 포함한다. 사용자 요청과 정식 OpenAPI의 optional update field DIFF-001~003, API Contract §1, P1-T1~P1-T5
2026-08-06 DEC-002 확정 변경 필드와 교체 파일이 없으면 저장 버튼을 비활성화하고 요청하지 않는다. 사용자 인터뷰 A안 선택 DIFF-004, P1-T1~P1-T5
2026-08-06 DEC-003 확정 파일만 변경한 multipart update는 required request part를 빈 object로 전송한다. 기존 multipart 계약에서 request part가 required이고 update object에는 required field가 없음 DIFF-005, API Contract §1.5, P1-T1~P1-T4
2026-08-06 DEC-004 확정 생성·비활성화·고정·순서·삭제 전용 mutation은 범위에서 제외한다. 해당 action은 이미 전용 최소 payload 또는 별도 method를 사용함 Non-Goals, P1-GATE
2026-08-06 DEC-005 확정 새 공통 diff abstraction이나 dependency 없이 각 도메인의 기존 serializer와 원본 DTO 비교를 사용한다. DTO별 null, 배열, 파일과 수정 가능 필드 의미가 다름 §10.1, P1-T1~P1-T5

18. 변경 관리

  • Decision Log에 변경 이유와 날짜를 기록한다.
  • 관련 요구사항 상태·본문·수용 기준을 갱신한다.
  • API Contract의 request 규칙과 예시를 갱신한다.
  • plan-task.md의 범위·Files·Interfaces·체크박스·완료 증거를 코드 변경 전에 갱신한다.
  • 기존 Progress·review·검증 기록을 삭제하거나 덮어쓰지 않는다.