현재 프로필 수정할때 기본적으로 두가지를 수정할 수 있다. 첫째는 닉네임이고 두번째는 프로필사진이다. 그리고 사용자가 수정 사항을 입력하면 그것을 formData에 담아서 jwt 서버쪽에 patch 요청을 보내고, 이후에 redux-state에 저장되어 있는 auth 관련 정보를 업데이트 하는 방식으로 코드가 이루어져 있다.
문제는 사용자가 닉네임만 변경하는 경우, 닉네임과 프로필 사진 둘다 변경하는 경우, 프로필 사진만 변경하는 경우의 세가지 경우의 수가 있다는 것이다. jwt 서버쪽에서는 formData만 만들어서 보내 주면 알아서 기존에 존재하던 필드를 덮어 쓰는 방식으로 업데이트가 이루어지니 상관이 없지만 redux state의 업데이트는 [...state,...payload]
같은 방식으로 이루어지기 때문에 문제가 된다.
payload 로 전달하는 수정사항이 담긴 객체의 key로
"nickname"만 있거나(닉네임만 변경한 경우)
"avatar"만 있거나 (프로필 사진만 변경한 경우)
"nickname","avatar" 둘다 있는(둘다 변경한 경우) 세가지 경우에 대응해야 하는 것이다.
만약 항상 "nickname","avatar"를 둘다 key로 전달하고 변경되지 않은 것의 value는 빈칸으로 두면 redux는 변경된적 없는 값까지 null이나 빈칸으로 덮어씌울 것이다.
오랜 검색 끝에
hasOwnProperty를 이용하여 문제를 해결했다.
hasOwnProperty는 어떤 객체내에 특정 값이 존재하는지를 확인하고 불린 값을 반환한다. 이걸 이용하면 '특정 값이 존재함' 을 조건으로 삼아 코드를 실행 할 수 있게 된다.
const changedProfile = {};
if (response.data) {
if (response.data.hasOwnProperty("nickname")) {
changedProfile.nickname = response.data.nickname;
}
if (response.data.hasOwnProperty("avatar")) {
changedProfile.avatar = response.data.avatar;
}
}
response.data
는 jwt 서버에서 보내온 응답을 의미한다. 이 응답에는 변경된 필드명이 명시되는데 이것을 이용하여 변경된 필드만을 객체에 담아 그것을 dispatch의 payload로 전달한다.
만약 nickname만 변경한 상황이라면 response.data 안에 nickname 필드는 존재하지만 avatar 필드는 존재하지 않는다.
따라서 response.data.hasOwnProperty("nickname")
는 true가 되어 changedProfile 객체에 nickname key 와 해당되는 value가 추가되며,
response.data.hasOwnProperty("avatar")
는 false 가 되어 changedProfile 객체에 ㅁavatar key-value는 추가되지 않는다.
회원 정보 수정을 한 이후에 해당 id로 작성한 모든 글에서 닉네임과 프로필 사진을 수정된 정보로 바뀌게 해야 한다. 현재는 프로필 수정 이후에 작성한 글에만 바뀐 닉네임과 프로필 사진이 반영되는 상황.
이미 json-server 이용할때 쿼리로 특정 userId 가 작성한 모든 글을 조회하는 방법을 알고 있었기 때문에 수정된 사항을 PATCH 메서드로 간단히 json-server 쪽에 반영시킬수 있을 것이라 생각했지만 그게 아니었다.
이런 식으로 test713 아이디로 작성된 모든 글을 한번에 읽어오는 것은 가능했지만 여기서 바로 patch로 "nickname" 필드와 "avatar"필드를 수정하려는 시도를 할경우 어김없이 404 not found
가 뜨는 것이다.
json-server 공식문서도 열심히 찾아보았지만 다수의 문서를 한번에 patch로 수정하는 api는 제공되고 있지 않은 듯했다.
이미 JWT 서버의 프로필 수정 업데이트는 문제없이 이루어지고 있는 상황이므로 프로필 수정 사항을 redux-state에 반영하는 코드에서 redux thunk 를 이용하여 중간에 json-server 에 저장된 데이터들을 업데이트 하는 로직을 넣어보기로 한다.
흐름은 다음과 같다
AS-IS
사용자 인증 서버쪽에 업데이트가 완료됨
➡️ 변경사항을 redux state에 반영함
TO-BE
사용자 인증 서버쪽에 업데이트가 완료됨
➡️ (추가) 수정된 userId로 작성된 글을 전부 조회함(GET)
➡️ (추가) 조회된 글들의 id를 수집하여 배열을 만듬
➡️ (추가) 만들어진 id 배열로 forEach를 이용하여 하나씩 수정 사항을 반영함(PATCH)
➡️ 변경사항을 redux state에 반영함
이것을 코드로 작성한 부분은 다음과 같다.
//src>redux>modules>authSlice.js
export const __editUser = createAsyncThunk(
"EDIT_USER_AND_UPDATE_JSON_SERVER",
async (payload, thunkAPI) => {
try {
//수정된 사용자가 작성한 글들의 id를 수집
const usersLetters = await jsonInstance.get(`?userId=${payload.userId}`);
const idArr = [];
usersLetters.data.forEach((letter) => idArr.push(letter.id));
console.log(idArr, payload.changedProfile);
//수집한 id를 기반으로 json-server쪽에 patch 요청
idArr.forEach(
async (id) =>
await jsonInstance.patch(`/${id}`, payload.changedProfile, {
headers: {
"Content-Type": "application/json",
},
})
);
//프로필 변경사항을 redux-state에도 저장
thunkAPI.dispatch(editUser(payload.changedProfile));
} catch (error) {
console.log(error);
}
}
);
아직 redux thunk의 사용이 능숙하지 않아 반신 반의하면서 시도해 보았지만 멋지게 의도대로 작동해서 닉네임이나 프로필 사진을 수정하면 해당 id로 작성된 모든 글에서도 똑같이 닉네임과 프로필 사진의 변경사항이 반영되도록 되었다.