refactor(character): 캐릭터 등록/수정 시 변경된 필드만 전송하도록 최적화

This commit is contained in:
Yu Sung
2025-08-07 18:53:07 +09:00
parent d1f700842f
commit 6bd3a62134
2 changed files with 109 additions and 29 deletions

View File

@@ -57,36 +57,15 @@ async function createCharacter(characterData) {
}
// 캐릭터 수정
async function updateCharacter(characterData) {
async function updateCharacter(characterData, image = null) {
const formData = new FormData()
// 이미지만 FormData에 추가
if (characterData.image) formData.append('image', characterData.image)
// 이미지가 있는 경우에만 FormData에 추가
if (image) formData.append('image', image)
// 나머지 데이터 JSON 문자열로 변환하여 request 필드에 추가
const requestData = {
id: characterData.id,
name: characterData.name,
systemPrompt: characterData.systemPrompt,
description: characterData.description,
age: characterData.age,
gender: characterData.gender,
mbti: characterData.mbti,
speechPattern: characterData.speechPattern,
speechStyle: characterData.conversationStyle,
appearance: characterData.appearance,
tags: characterData.tags || [],
hobbies: characterData.hobbies || [],
values: characterData.values || [],
goals: characterData.goals || [],
relationships: characterData.relationships || [],
personalities: characterData.personalities || [],
backgrounds: characterData.backgrounds || [],
memories: characterData.memories || [],
isActive: characterData.isActive
}
formData.append('request', JSON.stringify(requestData))
// 변경된 데이터 JSON 문자열로 변환하여 request 필드에 추가
// characterData는 이미 변경된 필드만 포함하고 있음
formData.append('request', JSON.stringify(characterData))
return Vue.axios.put(`/admin/chat/character/update`, formData, {
headers: {

View File

@@ -914,6 +914,7 @@ export default {
goals: [],
personalities: [],
backgrounds: [],
originalCharacter: null, // 원본 캐릭터 데이터 저장용
character: {
id: null,
name: '',
@@ -1233,6 +1234,97 @@ export default {
this.backgrounds.splice(index, 1);
},
// 변경된 필드만 추출하는 함수
getChangedFields() {
if (!this.originalCharacter || !this.isEdit) {
// 신규 등록인 경우 또는 원본 데이터가 없는 경우 전체 데이터 반환
return {
name: this.character.name,
systemPrompt: this.character.systemPrompt,
description: this.character.description,
age: this.character.age,
gender: this.character.gender,
mbti: this.character.mbti,
speechPattern: this.character.speechPattern,
speechStyle: this.character.conversationStyle,
appearance: this.character.appearance,
tags: this.character.tags || [],
hobbies: this.character.hobbies || [],
values: this.character.values || [],
goals: this.character.goals || [],
relationships: this.character.relationships || [],
personalities: this.character.personalities || [],
backgrounds: this.character.backgrounds || [],
memories: this.character.memories || [],
isActive: this.character.isActive
};
}
// 변경된 필드만 포함하는 객체
const changedFields = {
id: this.character.id // ID는 항상 포함
};
// 기본 필드 비교
const simpleFields = [
'name', 'description', 'age', 'gender', 'mbti',
'speechPattern', 'isActive'
];
simpleFields.forEach(field => {
if (this.character[field] !== this.originalCharacter[field]) {
changedFields[field] = this.character[field];
}
});
// 특수 필드 매핑 처리 (conversationStyle은 API에서 speechStyle로 사용됨)
if (this.character.conversationStyle !== this.originalCharacter.conversationStyle) {
changedFields.speechStyle = this.character.conversationStyle;
}
if (this.character.systemPrompt !== this.originalCharacter.systemPrompt) {
changedFields.systemPrompt = this.character.systemPrompt;
}
if (this.character.appearance !== this.originalCharacter.appearance) {
changedFields.appearance = this.character.appearance;
}
// 배열 필드 비교 (깊은 비교)
const arrayFields = [
'tags', 'hobbies', 'values', 'goals', 'relationships'
];
arrayFields.forEach(field => {
const original = this.originalCharacter[field] || [];
const current = this.character[field] || [];
// 길이가 다르거나 내용이 다른 경우
if (original.length !== current.length ||
JSON.stringify(original) !== JSON.stringify(current)) {
changedFields[field] = current;
}
});
// 복잡한 객체 배열 비교
const objectArrayFields = [
'personalities', 'backgrounds', 'memories'
];
objectArrayFields.forEach(field => {
const original = this.originalCharacter[field] || [];
const current = this.character[field] || [];
// 길이가 다르거나 내용이 다른 경우
if (original.length !== current.length ||
JSON.stringify(original) !== JSON.stringify(current)) {
changedFields[field] = current;
}
});
return changedFields;
},
async loadCharacter(id) {
this.isLoading = true;
try {
@@ -1242,6 +1334,9 @@ export default {
if (response && response.data) {
const data = response.data;
// 원본 데이터 저장 (깊은 복사)
this.originalCharacter = JSON.parse(JSON.stringify(data));
// 기본 데이터 설정
this.character = {
...this.character, // 기본 구조 유지
@@ -1293,9 +1388,15 @@ export default {
let response;
if (this.isEdit) {
response = await updateCharacter(this.character);
// 수정 시 변경된 필드만 전송
const changedData = this.getChangedFields();
console.log('변경된 필드만 전송:', changedData);
response = await updateCharacter(changedData, this.character.image);
} else {
response = await createCharacter(this.character);
// 신규 등록 시 ID 필드를 제외한 데이터 전송
const characterWithoutId = { ...this.character };
delete characterWithoutId.id;
response = await createCharacter(characterWithoutId);
}
if (response && response.data) {