react의 상태를 관리하다보면 불변성을 지켜서 사용하라고들 한다. 굳이 데이터를 추가할때도
array.push(5);
위의 push방법이 아닌
newArray=[...array, newData];
이런식으로 spread 방법을 사용해서 데이터를 넣고 한다 이는 불변성을 지키려고 일부러 이런 방법으로 사용한다.
불변성
불변성부터 이야기해보자면 값이나 상태를 변할수 없는것이다 즉 새로운값이 생기면 상태를 변경해주는 것이아니라 새로 할당하는 것을 말한다.
대표적으로 원시타입이 이렇게 동작한다
let a = 3;
//원시타입
3이라는 변수를 할당했다
let a = 5;
5로 변경을 하면 메모리에서는 a라는 변수에 5를 다시 할당하게된다 이는 불변성을 지키고있는 것이다.
원시타입이 있으면 참조타입도 있다
let arr = [1,2,3,4,5,6]
//참조타입
배열은 heap에 배열을 할당하고 call stack에는 이 저장된 주소값을 저장한다.
여기서는 [1,2,3,4,5,6]이 heap에 할당이 되고 arr는 이 heap의 주소값을 가지고 있는것이다
arr[2]를 10으로 변경한다고 하자
let arr = [1,2,10,4,5,6]
이렇게 되면 메모리에서는 arr를 다시 할당하는 것이 아닌 안에있는 값만 바뀌는 것이다 이는 불변성이 지켜지지 않았다고 할수있다.
React
React로 다시 돌아와 보자 React의 state가 변경할때 비교하는것은 데이터 하나 하나가 아니라 새로 할당되었는지를 확인해서 새로 할당 되었으면 state가 변경되었다고 감지하고 리랜더링을 수행한다.
이는 Array나 Object의 값이 불변성을 지키지 않고 바꾼다면 React에서는 값이 변경되었다고 파악하지 못한다.
const [state, setState] = useState({ id: 13, age: 30 })
setState({...person, age: 20})
다음과 같이 spread를 이용해서 불변성을 지키면서 변경해야 한다
( 새로 배열을 반환해주는 filter,mapm, concat 등을 사용해주어야 한다)
redux를 사용했으면 debug 툴로 redux dev tools를 많이 사용해 봤을것이다.
우리가 보는 redux dev tools에서도 불변성을 지켜야 수정 전의 state와 후의 state가 서로 달라지면서 재 할당 되기 때문에 이를 감지하여 action시에 state 변화를 dev tools로 볼수 있는 것이다.
코드 상으로는 reducer를 사용했을때 직접 와닿을수 있었다 데이터를 가공할때 이 불변성을 지키려다보면 코드들이 매우 난해해 지고 하나만 잘못해도 전부 무너저 버리는 상황이 발생하였다
다음은 댓글을 작성하는 reducer를 작성한 것이다.
//before
case ADD_COMMIT_SUCCESS:{
const postIndex = state.mainPost.finIndex((y)=>y.id===action.data.postId);
// 불변성을 지키면서 mainPost에서 알맞는 index를 가져와야함
const post ={...state.mainPosts[postIndex]};
// 불변성을 지키면서 찾은 index를 통해서 mainPosts의 개시글을 불러옴
post.Comments = [...post.Comments,action.data)
// 불변성을 지키면서 post에 Comment를 추가한다
const mainPosts = [...state.mainPosts];
// mainPosts를 불러온다
mainPosts[postIndex] = post;
// mainPosts에 수정된 post를 넣어준다
return{
...state,
mainPosts,
}
}
action.data에 API 호출후 응답 받은 데이터가 여기 들어있다 위의 상황에는 이렇게 들어가 있다고 생각하고 읽어주시길 바란다.
action.data{
postId: Number
content: String
userId: Number
}
이런코드는 구조가 복잡해 보이고 직관적이지 않는다
그러면 이런 방법을 해결할 방법이 없을까?
Immer
사실 이 불변성을 지키지 않고 코드를 짜는것이 지키면서 짜는것보다 직관적이게 짤수 있다 이를 해결해 주는 것이 바로 Immer 라이브러리이다. 우리가 불변성을 지키지 않고 사용하면 Immer가 직접 불변성 관리를 대신 해주는 것이다.
//after
case ADD_COMMENT_SUCCESS: {
const post = draft.mainPosts.find((v) => v.id === action.data.postId);
// main포스트에서 알맞는 개시글 찾기
post.Comments.unshift(action.data);
// 찾은 post에 댓글을 추가한다
break;
}
불변성을 지키지 않고 사용하면 단 두줄로 끝난다.
우리가 직관적으로 생각해봐도 댓글을 추가하려면 1. 댓글달 개시글을 찾고 2. 댓글을 추가한다가 알맞는다.
Immer을 사용한다고 무조건 코드가 짧아지거 하지는 않는다 오히려 짧은 코드들은 더 길어질수도 있다 위의 상황처럼 데이터 가공을하거나 할때 적절하게 사용하면 코드의 직관성과 간결함을 줄 수 있다.
'구 게시글 > React' 카테고리의 다른 글
JS 프로젝트 TS로 마이그레이션하기 (0) | 2022.11.25 |
---|---|
CSR SSR SSG(NEXT JS) SPA MPA 정리 (0) | 2022.06.19 |
SVG 태그 (0) | 2022.05.22 |
props로 modal관리는 이제 그만 (0) | 2022.05.17 |