코딩할 때 계속 반복해서 쓰이는 정형화된 부분
JS의 원시타입은 불변하다?
=> JS에서 메모리상 데이터 값은 불변하다
let a = 1;
let b = a; //a에 할당된 값의 데이터 주소가 b에게도
a = 2;
console.log(a,b); // 2 1
JS의 참조타입은 가변적이다?
=> 참조타입 내 데이터 영역의 값들은 불변하지만 변수 영역의 값들은 가변적이다.
let obj1 = {a:1,b:2};
let obj2 = obj1; //obj1의 같은 주소 범위가 obj2에게도
b = 3;
console.log(obj1, obj2) // {a:1, b:3} {a:1, b:3}
=> 타입에 따라 불변, 가변인지는 달라지지만 데이터 영역의 값은 불변성이 유지된다.
데이터는 타입에 따라 필요한 영역의 크기가 다르다. 타입과 상관없이 데이터를 넣는다면 영역의 크기가 부족할 시 메모리상 기존 데이터 위치를 옮겨줘야하는 비효율적인 문제가 발생하기 때문
1 const obj2 = obj1 //한 변수 속성 바뀌면 다른 변수 속성도 바뀜
2 Object.assign({}, obj) // 얕은 복사(현재 깊이에 대해서만 불변성 보장)
3 JSON.parse(JSON.stringify(obj)) // 깊은 복사(새로운 메모리 영역에 할당하는 방식)
1 예측가능성에서의 이점
2 성능효율성에서의 이점
1) 메모리 영역 성능
=> 메모리 추가 할당은 비효율적
2) 상태 변경 추적 성능
1 const 선언
2 Object.freeze, Object.seal, Object.preventExtension
=> 얕은 동결방식
3 깊은 동결
=> 성능 저하 유발
4 라이브러리
immutable.js
객체 속성의 변경, 추가, 삭제, 복사같은 행위를 수행하면 원본 객체 속성은 유지되고 변경된 복사본이 생성,반환.
리액트에서 불변성을 지켜야하는 이유는 리액트의 상태 업데이트 원리 때문.
리액트는 상태값 업데이트를 할 때 얕은 비교를 수행하는데(객체 속성을 비교x) 이는 객체의 속성이나 값을 바꾸면 상태 변화를 감지하지 못하기 때문에 새 객체를 생성해서 상태를 업데이트 하는 방식으로 불변성을 지킨다.
그리고 다른 이유로는 Side Effect를 방지하기 위함. 외부에 원본데이터가 존재하여 함부로 변경되지 않도록 해야하는데 복사본을 만들어 사용하면 복사본이 변경되도 원본 데이터는 불변하기 때문에 Side Effect를 방지할 수 있다.
map, filter, slice, reduce 같은 메서드를 사용하는 이유도 새로운 객체를 반환하기 때문에 기존 객체의 불변성을 지킬 수 있으므로.
상태 관리를 위해 action type, action creator, reducer 이렇게 나뉘었던 Redux 코드에,
//action type
const increase = "INCREASE";
const decrease = "DECREASE";
//action creator
export const addNumber = () => {
return { type: increase };
};
export const minusNumber = () => {
return { type: decrease };
};
//initial state
const initialState = {
number: 0,
};
//reducer
export const numberReducer = (state = initialState, action) => {
switch (action.type) {
case increase:
return {
...state,
number: state.number + 1,
};
case decrease:
return (state = {
...state,
number: state.number - 1,
});
default:
return state;
}
};
툴킷을 적용하면 아래와 같이 단순한 로직으로 같은 기능을 구현할 수 있다.
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
};
reducers: {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
},
});
위의 코드를 보며 비교했을 때 기존 redux에서 복사할 때는 스프레드 연산자를 사용하여 기존 객체를 복사하고 상태 변경 부분을 적용했는데 RTK를 적용함으로써 간단한 할당식으로 불변성을 유지하면서도 상태 변경을 표현할 수 있게 되었다.
위의 내용을 바탕으로,
Redux의 이런 boilerplate와 불변성을 지키면서 state를 변경시키는 로직이 긴 것을 더욱 간단하게 하기 위해 RTK(Redux-toolkit)이 등장하게 되었다고 이해했다.
해야하는 것은 json-server 돌리고 리덕스 툴킷 적용해보고 styled-component 적용하는 건데 아직 프로젝트 시작을 안해서 그런가 할 마음이 안든다. 저번에 하다가 접었던 json-server 대신에 express로 구현한 node.js 서버돌리고 mongoDB 연동하는 거 마저 했는데 일단 mongoDB 연동과 todo 추가해서 db에 저장하고 삭제 누르면 db에서 삭제되는 것까지는 구현했다. 근데 update는 아직 잘 모르겠다. 그리고 사실은 db에서 읽어온 응답으로 화면에 뿌려줘야되는데 아직 그 부분도 안돼있다.
mongodb에서 읽어오는 find() 메서드를 사용하니 내가 추가한 object만 읽어오는 게 아니라 event라는 이름으로 뭔가 큰 덩어리를 읽어온다. 어떻게 필요한 object만 추려서 읽을 수 있는지 아직 잘 모르겠다.
일단 프로젝트 준비를 이제 슬슬해야하니 프로젝트에 필요한 부분을 마저 공부해야겠다.