UI에 동적으로 표현될 데이터를 상태라고 한다. 즉 변하는 데이터라는 뜻이다. 상태를 다룰 때 Side Effect는 주요 고려대상이다. Side Effect는 함수의 입력 외에도 함수의 결과에 영향을 미치는 요인을 뜻하는데 대표적으로 네트워크 요청, API 호출이 그것이다.
React의 주요 개발 원칙 중 하나는 UI를 페이지 단위가 아닌 컴포넌트 단위로 보는 것이다. 그렇다면 어떤 컴포넌트를 만들 때, API 요청이 없이도 컴포넌트는 작동되어야 한다. 설령 데이터가 가짜 데이터라 할지라도 컴포넌트는 표현 그 자체에 집중해야하는 것이다. 하지만 어플리케이션을 만들다보면 side effect는 불가피하게 생기기 마련이다.
그렇다면 상태는 어느 곳에 위치해야할까? 프로그래밍 언어처럼 지역 변수, 전역 변수로 생각을 하고 접근을 한다면 전역 변수를 불필요하게 사용하는 것은 좋지 않다. 하지만 경우에 따라 전역 변수로 다루어야 할 상황이 있을 것이다. 상태의 경우에서도 마찬가지로 서로 다른 컴포넌트가 사용하는 상태의 종류가 다르다면 전역 상태일 필요가 없을 것이다. 하지만 동일한 상태를 다룬다면 이 상태의 출처는 한 곳이어야만 한다. 마치 전역 변수를 다루는 것처럼 말이다. 이로써 데이터의 무결성을 지킬 수 있다.
전역 상태를 위한 저장소 제공
props drilling 문제 해결
전역 상태 저장소가 있고 어디서든 그 저장소에 접근이 가능하게 함
A 컴포넌트의 자식 컴포넌트 B, C가 있고 C의 자식 컴포넌트로 D 컴포넌트가 있다고 하자. B 컴포넌트와 D 컴포넌트에서 같은 상태를 다룬다고 할 때, 상태를 공통으로 다루기 위해서는 A 컴포넌트에 상태가 위치해야 한다. 이런 상황에서 C 컴포넌트는 굳이 상태가 필요하지 않음에도 컴포넌트에 props를 만들어서 전달해주어야 하는 상황이 생긴다.
Redux는 자바스크립트 어플리케이션에서 예측 가능한 상태 관리를 해주는 컨테이너이다. React의 state는 컴포넌트 안에서 관리를 한다. 때문에 부모 컴포넌트를 통해 상태를 주고 받는다. 하지만 자식 컴포넌트가 많아진다면 상태 관리는 무척 복잡해질 것이다. 이런 복잡성을 줄이기 위해 Redux를 사용할 수 있다.
Redux의 세 가지 원칙
Redux에서 상태가 관리되는 오직 하나의 공간을 store라고 한다.
const store = createStore(rootReducer);
store에게 어플리케이션의 데이터를 운반해주는 역할. 어떤 액션을 취할 것인지 정의해 놓은 객체이다.
{
타입: "주문",
내용: {
메뉴: "무엇",
크기: "무엇"
}
}
Action을 전달하는 메소드.
현재 상태와 Action을 통해 다음 상태를 만드는 순수 함수. Action 객체는 Dispatch에게 전달되고, Dispatch는 Reducer를 호출해서 새로운 State를 생성
Reducer의 불변성
Redux의 state 업데이트는 immutable한 방식으로 변경해야 한다. 이것은 Redux의 장점 중 하나인 변경된 state를 로그로 남기기 위해 꼭 필요한 작업이다.
useSelector()
컴포넌트와 state를 연결하는 역할. 인자로 콜백 함수를 받고 콜백 함수의 인자로는 state값이 들어간다.
useDispatch()
Action 객체를 Reducer로 전달해주는 역할.