리덕스는 가장 많이 사용하는 리액트 상태 관리 라이브러리입니다.
리덕스를 사용하면 컴포넌트의 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 더욱 효율적으로 관리 할 수 있습니다. 또한, 컴포넌트끼리 똑같은 상태를 공유해야 할 때도 여러 컴포넌트를 거치지 않고 손쉬게 상태 값을 전달하거나 업데이트 할 수 있습니다.
리덕스 라이브러리는 전역 상태를 관리할 때 굉장히 효과적입니다.이전에 배운 Context API를 통해서도 똑같은 작업이 가능하지만, 리덕스를 사용하면 상태를 더욱 체계적으로 관리할 수 있고 코드의 유지 보수성도 높여주며 작업 효율을 극대화해줍니다.
| 항목 | 리덕스(Redux) | 리액트 Context API |
|---|---|---|
| 설계 철학 | 중앙 집중식 상태 관리로 예측 가능성 및 추적 용이 | 간단한 상태 공유를 위한 설계, 소규모 애플리케이션에 적합 |
| 상태 관리 | 중앙 스토어에서 상태 관리, 어디서든 쉽게 접근 및 업데이트 가능 | 트리 구조 깊은 곳에서도 상태 공유 가능, 여러 컨텍스트 사용 시 복잡성 증가 |
| 미들웨어 | 미들웨어를 통해 액션 처리 전후에 추가 작업 가능, 비동기 작업 처리 수월 | 미들웨어 개념이 없어 비동기 작업 처리 시 번거로움 |
| 성능 | 상태 변경 시 필요한 컴포넌트만 리렌더링하여 성능 최적화 가능 | 상태 변경 시 모든 하위 소비자 리렌더링 가능성, 대규모 애플리케이션에서 성능 문제 발생 가능 |
| 확장성 | 대규모 애플리케이션에서도 상태 관리 효율적 | 소규모 애플리케이션에 적합, 규모가 커질수록 복잡성 및 성능 문제 발생 가능 |
| 예측 가능성 | 상태 변화 예측 가능, 디버깅 및 테스트 용이 | 간단한 상태 공유에는 적합하지만, 복잡한 상태 관리에는 불리 |
| 구현 용이성 | 설정과 초기 학습 곡선이 있지만, 체계적인 상태 관리 가능 | 별도의 라이브러리 설치 없이 리액트에서 바로 사용 가능, 간단한 상태 공유 구현에 적합 |
| 사용 사례 | 대규모 애플리케이션, 복잡한 상태 관리, 비동기 작업 처리 필요 시 | 소규모 애플리케이션, 간단한 상태 공유 시 |
상태에 어떠한 변화가 필요하면 액션(action)이란 것이 발생합니다 이는 하나의 객체로 표현되는데, 다음과 같은 형식입니다.
type 속성을 필수로 가지고 있습니다.{ type: 'INCREMENT' }{
type: 'TOGGLE_VALUE'
}
액션 객체는 type 필드를 반드시 가지고 있어야 합니다.
이 값을 액션의 이름이라고 생각하면 됩니다.
그리고 그 외의 값들은 나중에 상태 업데이트를 할 때 참고해야 할 값이며, 작성자 마음데로 넣을 수 있습니다.
액션 생성 함수(action creator)는 액션 객체를 만들어 주는 함수입니다.
function addTodo(data) {
return {
type: 'ADD_TODO',
data
};
}
어떤 변화를 일으켜야 할 때마다 액션 객체를 만들어야 하는데 매번 액션 객체를 직접 작성하기 번거로울 수 있고, 만드는 과정에서 실수로 정보를 놓칠 수도 있습니다. 이러한 일을 방지하기 위해 이를 함수로 만들어서 관리합니다.
리듀서(reducer)는 변화를 일으키는 함수입니다.
액션을 만들어서 발생시키면 리듀서가 현재 상태와 전달받은 액션 객체를 파라미터로 받아 옵니다. 그리고 두 값을 참고하여 새로운 상태를 만들어서 반환해 줍니다.
const initialState = {
counter: 1
};
function reducer(state = initialState, action){
switch(action.type) {
case INCREMENT:
return {
counter: state.counter + 1
};
default:
return state;
}
}
프로젝트에 리덕스를 적용하기 위해 스토어(store)를 만듭니다.
한 개의 프로젝트는 단 하나의 스토어만 가질 수 있습니다.
스토어 안에는 현재 애플리케이션 상태와 리듀서가 들어가 있으며, 그 외에도 몇 가지 중요한 내장 함수를 지닙니다.
createStore 함수로 생성됩니다.import { createStore } from 'redux';
const store = createStore(counterReducer);
디스패치(dispatch)는 스토어의 내장 함수 중 하나입니다.
디스패치는 액션을 발생시키는 것 이라고 이해하면 됩니다.
이 함수는 dispatch(action)과 같은 형태로 액션 객체를 파라미터로 넣어서 호출합니다. 이 함수가 호출되면 스토어는 리듀서 함수를 실행시켜서 새로운 상태를 만들어 줍니다.
store.dispatch(action) 형태로 사용됩니다.store.dispatch({ type: 'INCREMENT' });
구독(subscribe)도 스토어의 내장 함수 중 하나입니다. subscribe 함수 안에 리스너 함수를 파라미터로 넣어서 호출해 주면, 이 리스너 함수가 액션이 디스패치되어 상태가 업데이트 될 때마다 호출됩니다.
store.subscribe(listener) 형태로 사용됩니다.store.subscribe(() => console.log(store.getState()));
단일 스토어
읽기 전용 상태
리듀서는 순수한 함수
리덕스의 세 가지 핵심 원칙은 다음과 같습니다: