7.0 KiB
수정 요청 변경 필드 전송 API Contract
1. 공통 계약
이 문서는 기존 AI 캐릭터 관리자 OpenAPI의 endpoint·DTO를 바꾸지 않고, 프론트엔드가 수정 request를 구성하는 규칙을 구체화한다. 이 문서와 정식 OpenAPI가 충돌하면 정식 OpenAPI의 field type·nullable·response·error 계약을 우선하고 이 문서는 payload 선택 규칙만 소유한다.
1.1 유지되는 항목
- 기존
PUTmethod와 path를 유지한다. - 기존 bearer 인증,
Accept-Language, 성공 envelope, 오류 status·key를 유지한다. - 캐릭터·오디오 콘텐츠·커뮤니티 게시글·시리즈는
multipart/form-data를 유지한다. - multipart JSON part 이름은
request, MIME은application/json이다. - FanTalk 답글은
application/jsonbody를 유지한다.
1.2 변경 판정
- 상세·목록 응답으로 form을 초기화할 때 수정 기준값을 보존한다.
- 현재 form 값과 기준값에 같은 기존 직렬화 규칙을 적용한다.
- 문자열 trim, 빈 optional 값의
null변환, 배열·객체 배열 변환 후 필드별 값을 비교한다. - 값이 다른 field만 request object에 포함한다.
- 사용자가 값을 바꾼 뒤 기준값으로 되돌리면 해당 field를 생략한다.
비교 대상은 각 기능의 update DTO field다. route ID, 조회 전용 field, 서버 계산값과 수정 화면에 없는 field를 request에 복사하지 않는다.
1.3 생략, null, falsy 값
| 표현 | 의미 | 예시 |
|---|---|---|
| key 생략 | 미변경 | { "title": "새 제목" }에는 detail 변경 없음 |
null |
해당 DTO가 허용하는 기존 값 삭제 | { "writer": null } |
false |
boolean 값을 false로 변경 | { "isAdult": false } |
0 |
숫자 값을 0으로 변경 | { "price": 0 } |
| 배열·객체 배열 | 해당 필드 전체의 새 값 | { "publishedDaysOfWeek": ["RANDOM"] } |
false, 0, 빈값 삭제용 null은 falsy 값이라는 이유로 생략하지 않는다.
1.4 변경 없음
- 변경 field와 교체 file이 모두 0개면 저장 control은 native
disabled상태다. - disabled 상태에서는 API helper를 호출하지 않는다.
- 빈 JSON 또는 빈 multipart mutation을 전송하지 않는다.
1.5 파일 part
| 상태 | 파일 part | request JSON |
|---|---|---|
| 텍스트 field만 변경 | 생략 | 변경 field만 포함 |
| 파일과 field 변경 | 새 파일 1개 | 변경 field만 포함 |
| 파일만 변경 | 새 파일 1개 | {} |
| 변경 없음 | 요청 자체 없음 | 요청 자체 없음 |
기존 파일을 선택하지 않으면 서버의 현재 파일을 유지한다. 파일 삭제 기능은 이 계약에 추가하지 않는다.
2. 기능별 계약
2.1 AI 캐릭터
PUT /api/v2/admin/ai-characters/{characterId}
- Content-Type:
multipart/form-data - optional file part:
image - JSON part:
request - 비교 가능 field:
name,systemPrompt,description,age,gender,mbti,speechPattern,speechStyle,appearance,originalTitle,originalLink,originalWorkId,characterType,tags,hobbies,values,goals,relationships,personalities,backgrounds,memories - 금지 field:
region, 일반 수정의isActive - 기존 예외: 원작 미선택·선택 해제의
originalWorkId는 현재 serializer 계약대로 key를 생략하며, 원작 연결 해제 기능은 추가하지 않는다.
이름만 변경:
{
"name": "루나 수정"
}
태그를 모두 삭제:
{
"tags": null
}
2.2 오디오 콘텐츠
PUT /api/v2/admin/ai-characters/{characterId}/audio-contents/{contentId}
- Content-Type:
multipart/form-data - optional file part:
coverImage - JSON part:
request - 수정 화면 비교 field:
title,detail,tags,price - 일반 수정 금지 field:
isActive - 화면에 없는
isAdult,isPointAvailable,isCommentAvailable은 상세 응답에서 복사하지 않는다.
상세 설명만 변경:
{
"detail": "수정한 상세 설명"
}
가격만 무료로 변경:
{
"price": 0
}
2.3 커뮤니티 게시글
PUT /api/v2/admin/ai-characters/{characterId}/community-posts/{postId}
- Content-Type:
multipart/form-data - optional file part:
postImage - JSON part:
request - 수정 저장 비교 field:
content,isCommentAvailable,isAdult - 수정 저장 금지 field:
isFixed,isActive isFixed전환과 soft delete는 기존 전용 action payload를 유지한다.
내용만 변경:
{
"content": "수정한 게시글 내용"
}
댓글 허용만 끄기:
{
"isCommentAvailable": false
}
2.4 시리즈
PUT /api/v2/admin/ai-characters/{characterId}/series/{seriesId}
- Content-Type:
multipart/form-data - optional file part:
image - JSON part:
request - 비교 field:
title,introduction,publishedDaysOfWeek,genreId,isAdult,state,writer,studio - 일반 수정 금지 field:
isActive, create-onlykeyword
제목만 변경:
{
"title": "달빛 상담 시리즈 수정"
}
작가를 삭제:
{
"writer": null
}
2.5 FanTalk 답글
PUT /api/v2/admin/ai-characters/{characterId}/fan-talks/{fanTalkId}/replies/{replyId}
- Content-Type:
application/json - 비교 field:
content - 일반 답글 수정 금지 field:
isActive
답글 변경:
{
"content": "수정한 답글입니다."
}
content가 기존 답글과 같으면 수정 button은 disabled이고 request를 보내지 않는다.
3. 응답과 오류
응답과 오류 계약은 변경하지 않는다.
| 기능 | 성공 data |
|---|---|
| 캐릭터·오디오 콘텐츠·커뮤니티 게시글·시리즈 | 기존 null success data |
| FanTalk 답글 | 기존 FanTalkListItem update response |
- validation, 401, 403, 404, 406, 415, 500 처리는 정식 OpenAPI와 기존 공통 API client를 따른다.
- 부분 request 도입을 이유로 새로운 status,
errorProperty또는 자동 retry를 만들지 않는다.
4. Contract 검증 예시
| 시나리오 | 필수 assertion |
|---|---|
| title만 변경 | request key가 title 하나다. |
| detail만 변경 | request key가 detail 하나다. |
| boolean을 false로 변경 | 해당 key와 false가 존재한다. |
| nullable field 삭제 | 해당 key와 null이 존재한다. |
| 변경 후 원복 | 저장 disabled, mutation 0건이다. |
| 파일만 변경 | 파일 part 1개, request {}다. |
| 파일 미변경 | 파일 part가 없다. |
5. 범위 밖 mutation 회귀 계약
다음 기존 요청은 payload 최적화 대상이 아니며 현재 contract를 유지한다.
- 캐릭터·오디오 콘텐츠·시리즈 비활성화:
{ "isActive": false } - 커뮤니티 게시글 고정 전환:
{ "isFixed": boolean } - 커뮤니티 게시글 soft delete: 기존
{ "isActive": false, "isFixed": false } - 시리즈 순서 변경:
{ "ids": number[] } - FanTalk 원글 삭제: body 없는
DELETE