SPA가 갖춰야 할 요건이 점점 더 복잡해지면서, 많은 상태(state)를 관리할 필요가 생겨났다.
이에 Redux 공식문서에서는 Redux의 개발 동기에 대해 이렇게 말하고 있다.
항상 변하는 상태를 관리하기란 어렵습니다. 모델이 다른 모델을 업데이트하고, 그리고 뷰가 모델을 업데이트 할 수 있고, 이 뷰가 다시 다른 모델을 업데이트하고, 이에 따라 또 다른 뷰가 업데이트 됩니다. 어느 시점에서는 프로그래머조차 애플리케이션에서 무슨 일이 일어나는지 알 수 없게 됩니다. 상태를 언제, 왜, 어떻게 업데이트할지 제어할 수 없는 지경에 이르고 맙니다.
...
Redux는 상태 변화가 일어나는 시점에 제약을 두어, 상태 변화를 예측 가능하게 만들고자 시도한다.
하나의 저장소(store)가 존재하며, 이 저장소(store)에는 애플리케이션의 모든 상태들이 객체 트리 구조로 저장되어 있다.
-> 서버로부터 가져온 상태는 직렬화(serialized)되거나, 수화되어(hydrated) 전달되며 클라이언트에서 추가적인 코딩 없이도 사용할 수 있다. 하나의 상태 트리만을 가지고 있기 때문에 디버깅에도 용이하다.
직렬화(serialize)란?
직렬화 예시, localstorage는 값으로 string을 가질 수 있지만 object는 가질 수 없다. 이때, json.stringify를 통해서 object를 string화한다. 이것이 직렬화다. 다시 꺼내쓸 때는 json.parse를 하여 다시 string을 object화 하는데, 이것이 역직렬화다. 이때, 직렬화 전 object와 역직렬화된 object는 같아야 한다.
-> redux에서 function,promise등과 같은 non-serializable type을 저장하면, redux-devtools에서 표시가 안되고, 또 콘솔에서 경고 메세지를 던진다. redux에서는 store의 일관성 유지, 복원 기능, 시간여행 디버깅 등이 방해받을 수 있기에 non-serializable type을 저장하는 걸 권하지 않는다고 한다.
상태(state)는 읽기 전용이다. 상태를 변화시키는 유일한 방법은 무신 일이 벌어지는 지를 묘사하는 액션 객체를 전달하는 방법뿐이다.
-> 이를 통해서 뷰(view)나 네트워크 콜백에서 상태를 직접 바꾸지 못한다는 것을 보장 할 수 있다. 모든 상태 변화는 중앙에서 관리되며 모든 액션은 엄격한 순서에 의해 하나하나 실행되기 때문에 신경써 관리해야할 경쟁 상태는 없다.
액션에 의해 상태 트리가 어떻게 변화하는 지를 지정하기 위해 프로그래머는 순수 리듀서를 작성해야 한다.
-> 리듀서는 그저 이전 상태와 액션을 받아 다음 상태를 반환하는 순수함수이다. 이전 상태를 변경하는 것이 아니라, 새로운 상태 객체를 생성해서 반환해야한다는 사실을 기억해야 한다.
순수 함수란?
동일한 인자가 주어졌을 때 항상 동일한 결과를 반환해야 하며, 외부의 상태를 변경하지 않는 함수
-> 즉, 함수 내 변수 외에 외부의 값을 참조, 의존하거나 변경하지 않는 함수