리덕스(Redux)는 React 애플리케이션에서 상태를 관리하기 위한 라이브러리입니다.
리덕스를 사용하면 컴포넌트의 상태 업데이트 관련 오직을 다른 파일로 분리시켜서 더욱 효율적으로 관리할 수 있습니다.
또한, 컴포넌트끼리 똑같은 상태를 공유해야 할 때도 여러 컴포넌트를 거치지 않고 손쉽게 상태 값을 전달하거나 업데이트 할 수 있습니다.
리덕스 라이브러리는 전역 상태를 관리할 때 굉장히 효과적인 입니다. 물론 이전에 배운 Context API를 통해서도 똑같은 작업을 할 수 있습니다.
단순히 전역 상태 관리만 한다면 Conext API를 사용하는 것만으로도 충분 합니다.
하지만 리덕스를 사용하면 상태를 더욱 체계적으로 관리할 수 있기 때문에 프로젝트의 규모가 클 경우에는 리덕스를 사용하는 편이 좋습니다.
MVC 패턴이란 Model에 데이터를 저장하고, Controller를 사용하여 Model의 데이터를 관리하는 소프트웨어 디자인 패턴의 하나입니다. 이러한 MVC 패턴에서는 사용자가 View를 통해 데이터를 입력하면 View에서도 Model를 업데이트 할 수 있기 때문에 데이터가 양방향으로 전달될 수 있습니다.
하지만 이렇게 구현된 프로젝트는 프로젝트의 규모가 커질수록 수많은 Model과 View가 생성되고, 이때 Model의 상태에 변화가 생길 경우 Model과 View 사이에 엄청난 양의 데이터가 양방향으로 전달되게 됩니다. 이로 인해 데이터의 흐름을 예측하기가 점점 힘들어지고, 수많은 버그를 발생시키는 원인이 됩니다.

이러한 문제를 해결하기 위해 2014년 페이스북에서는 Flux 패턴이라는 새로운 아키텍처를 제안합니다.
Flux 패턴은 사용자 입력을 기반으로 Action을 생성하고, 이를 Dispatcher에 전달하여 Store의 데이터를 변경한 뒤 View에 반영하는 단방향의 데이터 흐름을 가지는 소프트웨어 아키텍처입니다. Flux 패턴으로 구현된 프로젝트는 데이터가 단방향으로만 전달되기 때문에 데이터의 흐름을 파악하기가 용이하고, 그 결과를 쉽게 예측할 수 있다는 장점을 가집니다.

애플리케이션의 규모와 복잡도가 증가할수록 컴포넌트끼리 state를 공유해야 할 경우 수많은 컴포넌트를 복잡하게 거쳐야만 그 값을 전달할 수 있게 됩니다. 또한, 필요에 따라 state를 비동기적으로 변경해야 할 경우도 많아지게 되었습니다. 따라서 state를 보다 효과적으로 관리할 수 있는 방법의 중요성이 대두되었으며, 이렇게 등장한 여러 상태 관리 라이브러리 중 하나가 바로 Redux입니다.

Redux는 Store라는 전역 상태 저장소를 통해 state와 Reducer를 저장
Redux는 애플리케이션 하나 당 하나의 Store만을 생성하며, 유용한 몇 가지 내장 함수를 같이 제공
(각 컴포넌트들은 이러한 내장 함수들을 사용하여 Store의 데이터에 접근하고 변경을 요청)
Store를 변경하기 위한 로직을 저장하는 곳이 바로 Reducer
Reducer는 현재 state와 Action을 인수로 전달 받아 Store에 접근하고, 전달 받은 Action을 참고하여 새로운 state를 만들어 반환 (Reducer를 원하는 조건에 따라 호출하는 것이 바로 Action)
상태에 어떠한 변화가 필요하면 액션(action)이란 것이 발생합니다. 이는 하나의 객체로 표현되는데요. 액션 객체는 다음과 같은 형식으로 이루어져 있습니다.
{
type: "TOGGLE_VALUE"
}
액션 객체는 type 필드를 반드시 가지고 있어야 합니다. 이 값을 액션의 이름이라고 생각하면 됩니다.
그리고 그 외의 값들은 나중에 상태 업데이트를 할 때 참고해야 할 값이며, 작성자 마음대로 넣을 수 있습니다.
{
type: "ADD_TODO",
data: {
id: 1,
text: "리덕스 배우기"
}
}
{
type: "CHANGE_INPUT",
text: "안녕하세요"
}
액션 생성 함수는 액션 객체를 만들어 주는 함수 입니다.
function addTodo(data) {
return {
type: "ADD_TODO"
data
};
}
// 화살표 함수로 만들기
const changeInput = text => ({
type: "CHANGE_INPUT",
text
});
어떤 변화를 일으켜야 할 때마다 액션 객체를 만들어야 하는데 매번 객체를 직접 작성하기 번거로울 수 있고, 만드는 과정에서 실수로 정보를 놓칠 수 있습니다. 이런한 일을 방지하기 위해 이를 함수로 만들어서 관리 합니다.
리듀서(reducer)는 변화를 일으키는 함수입니다. 액션을 만들어서 발생시키면 리듀서가 현재 상태와 전달받은 액션 객체를 파라미터로 받아 옵니다. 그리고 두 값을 참고하여 새로운 상태를 만들어서 반환해 줍니다.
const initialState = {
counter: 1
};
function reducer(state = initialState, action) {
switch(action.type) {
case INCREMENT :
return {
counter: state.counter + 1;
}
default:
return state;
프로젝트에서 리덕스를 적용하기 위해 스토어(store)를 만듭니다. 한 개의 프로젝트는 단 하나의 스토어만 가질 수 있습니다. 스토어 안에는 현재 애플리케이션 상태와 리듀서가 들어가 있으며, 그 외에도 몇 가지 중요한 내장 함수를 지닙니다.
디스패치는 스토어의 내장 함수 중 하나입니다. 디스패치는 “액션을 발생시키는 것”이라고 이해하면 됩니다. 이 함수는 dispatch(action)과 같은 형태로 액션 객체를 파라미터로 넣어서 호출합니다.
이 함수가 호출되면 스토어 리듀서 함수를 실행시켜서 새로운 상태를 만들어 줍니다.
구독도 스토어의 내장 함수 중 하나입니다. subscribe 함수 안에 리스너 함수를 파라미터로 넣어서 호출해 주면, 이 리스너 함수다 액션이 디스패치되어 상태가 업데이트 됩니다.
const listener = () => {
conslole.log("상태가 업데이트됨");
}
const unsubscribe = store.subscribe(listener);
unsubscribe(); // 추후 구족을 비활성화할 때 함수를 호출