redux는 reduce에서 이름을 따온 것이다.
데이터 중앙 저장소가 있다고 쳐보자. 아래 그림에다가 name은 jay, age: 27, password는 babo가 들어있다고 하자.
중앙저장소를 만들면 이걸 각 컴포넌트에서 필요로 할 때 꺼내서 쓸 수 있다. 데이터를 조회하기만 하는 것이 아니라 데이터를 수정도 하고 데이터를 추가도 하고 삭제도 한다.
리덕스에서는 데이터를 바꾸려면 action이라는 것을 필수로 만들어 줘야한다.
가상의 action 하나가 있다고 치면 (아래와 같이)
중앙저장소가 있고 이 중앙저장소를 수정해야 되는 일이 있는데 그럴 때 액션을 또 하나 만들 수 있다. 그리고 이 액션을 dispatch하면 중앙저장소가 바뀐다. 즉 action을 dispatch 하는 순간 CHANGE_NICKNAME 부분이 boogicho로 바뀐다.
데이터가 boogicho로 바꼈으면 name을 가져다가 쓰고있는 컴포넌트들에서도 알아서 다 모든 name들이 jay에서 boogicho로 바뀐다.
reducer라는 개념이 있는데 reducer는 dispatch한다고 해서 알아서 name을 boogicho로 바꾸는 것이 아닌데, js는 CHANGE_NAME이 뭔지 이해를 못한다. 그래서 사용자가 직접 어떻게 바꿔야 하는지 일일이 다 reducer에서 적어줘야 한다. 아래 그림을 참고하자.( reducer의 중요성을 보여준다.)
처음부터 정리하면 앱에 대한 전체 상태를 하나의 객체로 표현을 해두고 그것을 바꾸고 싶을 때마다 action을 하나씩 만들어준다. CHANGE_NICKNAME도 있는데 나중에 바꾸고 싶은것이 있으면 action 하나 만들어 주면 된다. action 하나 만들어서 dispatch해주면 되는 것! 하지만 reducer에서 직접 구현은 해줘야 한다. 즉 최종적으로는 reducer에 적어준 방식에 따라서 state가 바뀌게 되는 것이다.
데이터를 하나씩 바꾸고 싶을 때마다 액션을 매번 만들어줘야 한다. 액션 매번 만들어주고 어떻게 처리할지 액션을 실제로 처리할 부분을 직접 적어줘야 하고 즉 코드량이 매우 많아진다....!
비밀번호를 바꾸고 싶다하면 CHANGE_PASSWORD도 만들어야 한다. AGE와 PASSWORD를 동시에 바꾸고 싶다 그러면 CHANGE AGE AND PASSWORD 만들어야 하고 3개를 바꾸고 싶으면 3개속성을 적어줘야한다. 이러면 action을 만들 때마다 reducer도 하나씩 만들어 줘야 하는 것이다.
왜 이렇게 할까 의아하긴 하다. 실제로 해보면 상당히 좋은게 액션 하나하나가 리덕스에 기록이 된다.
액션들만 쫙 놓고 보면 지금까지 데이터를 어떻게 바꿔왔는지 내역들을 다 추적이 된다. 즉 버그잡을 때 매우 편하다.
액션 같은 것들을 실수로 잘못 만들었거나 reducer를 잘못 만들었으면 내역이 쫙 있다가 중간에 데이터가 뭔가 잘못 변화하는 부분이 생기게 되면 포착이 될 것이다. 즉 리덕스를 쓰면 액션들이 쫙 출력이 되기 때문에 흐름타고 내려가다 보면 데이터가 잘못되서 에러가 나는 부분을 쉽게 찾을 수 있다.
그리고 히스토리 처럼 나열되어 있으면 거꾸로 거슬러 올라갈 수도 있다. 타임머신 역할을 하는건데 로그인을 했다 그러면 정보가 없다가 어떤 액션에 의해서 정보가 생기게 되는데 리덕스 데브툴로 뒤로가기를 하면 로그인이 풀려버린다.
원하면 다시 로그인을 시킬 수도 있고. 데이터를 뒤로 돌렸다가 다시 앞으로 감았다가를 할 수 있는 것이다.
즉 개발할 때 테스트하기가 유용하다. switch문이 매우 길어질 수도 있는것이 단점이다. switch문이나 state들을 쪼갤 수 있기는 한데 길어지는 것이 단점인 것이다.
그리고 위 그림과 같이 case 구문안에 return을 왜 저렇게 적어주냐.. 불변성 때문이다.(Immutability)
js에서 {} === {}는 false이다. 객체와 객체의 비교는 false인 것이다.
그리고
const a = {};
const b = a;
a === b // true인데 이러한 성질을 이용해서 객체를 새로 만든거는 false인데 객체를 참조한 참조관계가 있으면 true가 나온다.
위 그림은 return 안에 {} 객체를 새로 만들어 준것이므로 항상 false가 나오는데 계속해서 다른 객체를 return하는 것이다.
내가 바꾸고 싶은것만 바꾸고 객체 자체는 새로 만들어서 보내준다.(두번째 그림에서 type: 'CHANGE_NICKNAME'이므로 CHANGE_NICKNAME만 바꿔주게 되고) 객체를 새로 만드는 이유는 객체를 새로 만들어야 변경 내용들이 추적이 된다.
아래 코드를 보면 prev에는 이전 기록이 있고 next에는 다음 기록이 있는데 이전기록도 남아있고 다음 기록도 남아있다.
그래서 새롭게 객체를 만들어 주는 것이다. 그래야지 이전기록과 다음기록이 남아있기 때문이다.
const prev = { name: 'zerocho'}
const next = { name: 'boogicho'}
만약
const prev = { name: 'zerocho'}
const next = prev;
next.name = 'boogicho'라고 직접 바꿔버리면
prev.name; // boogicho로 나오게 된다. 참조관계이기 때문이다. 즉 히스토리가 없어지게 된다.
const prev = { name: 'zerocho'}
const next = prev;
next.name = 'boogicho'
prev.name; // boogicho
리덕스를 쓰는 주된 이유중 하나가 히스토리를 관리하는 것인데, 참조관계로 해버리면 제로초 했다는 기록이 다 사라져 버리기 때문에 prev name도 boogicho로 바뀌게 된다. 그래서 항상 새로운 객체를 만들어서 작성하는 것이다.
그리고 전체를 다 안적고 ...state를 하는 이유는 메모리를 아끼기 위해서이다.
{
...state,
name: action.data,
}
// vs
{
name: action.data,
age: 27,
password: 'babo'
}
모든 것이 기록으로 다 남아 있는데 액션 하나실행 할때마다 자꾸 객체가 생기니까 메모리를 많이 잡아먹게 된다.
안바뀌는 애들은 ...state를 통해서 참조관계를 유지하고 있기 때문에 메모리를 아낄 수 있다.
매번 action을 만들때마다 객체를 새로 만드는데 이것들이 영원히 있는 것은 아니고 개발모드 일때는 메모리 정리가 안되고 개발모드 일때는 히스토리를 계속 가지고 있다. 즉 서비스 켰을 때부터 액션 하나하나 히스토리를 다 갖고 있는데 이것을 배포모드로 바꾸면 히스토리를 중간중간에 계속 버리게 된다.
히스토리를 계속 갖고 있다는 것은 참조를 유지하는 것이고 메모리 같은데 저장되어 있다는 것인데, 액션 하나한 호출할 때마다 점점 메모리가 커지는데 배포모드일 때는 히스토리의 모든기능이 필요없기 때문에 걸러서 갖다 버리게 된다. 즉 메모리 정리를 계속 해줘서 배포모드일 때는 메모리 문제가 일어나지 않는다. 즉 위에서 posts 3개의 객체가 바뀐게 없으면 같은 객체여도 된다는 것이다.
그리고 비구조화할당을 ...state하여 새로 생성되었다고 생각될 수 있는데 새로 생성된 것이 아니다. 아래를 보자.
...을 하게되면 객체들은 참조를 유지하게 된다.
결론 참조를 적절하게 유지할 때는 nest된 것들은 유지하고 새로 만들어줘야 할 때는 새로 만들어주고 하는 것이다.
const nest = { b: 'c'};
const prev = { a: nest };
// undefined
const next = { ...prev }
// undefined
prev.a === next.a
// true
// 참조를 유지하게 된다.
prev자체와 next자체는 다르다. 왜냐 각각 새로운 객체를 만들어 준 것이기 때문에 다르다.
그 안에 들어있는 a는 같게된다.
a까지 새로 만드는 것이 아니라, a는 참조를 그대로 유지하기 때문에 메모리를 아낄 수 있다.
메모리를 아낄 수 있게 되는 것이다.
prev === next
// false
아래를 보면 쉽게 이해될 것이다. 서로 값이 다르다.
{a: 'b'} === {a: 'b'}
// false
{} === {}
// false
<출처 조현영: [리뉴얼] React로 NodeBird SNS 만들기>
[리뉴얼] React로 NodeBird SNS 만들기 - 인프런 | 강의
리액트 & 넥스트 & 리덕스 & 리덕스사가 & 익스프레스 스택으로 트위터와 유사한 SNS 서비스를 만들어봅니다. 끝으로 검색엔진 최적화 후 AWS에 배포합니다., 새로 만나는 제로초의 리액트 노드버
www.inflearn.com
'React > NodeBird(ZeroCho)' 카테고리의 다른 글
redux-thunk 이해하기 (0) | 2021.10.28 |
---|---|
정규표현식 맛보기 (0) | 2021.10.28 |
redux설치 (0) | 2021.10.26 |
회원가입 페이지 만들기(커스텀 훅) (0) | 2021.09.17 |
프로필 페이지 만들기 (0) | 2021.09.17 |