07. Redux의 핵심 - Action, Reducer, Store
06편에서 Redux의 철학을 봤다면, 이 편은 그 철학을 구현하는 세 가지 구성 요소를 직접 코드로 만들어봅니다. createStore로 순수 Redux 스토어를 처음부터 만들어보면, 이후 React-Redux나 Redux Toolkit이 내부에서 무엇을 하고 있는지 훨씬 명확하게 이해됩니다.
학습 목표
- Action, Reducer, Store 세 요소의 역할과 형태를 정확히 설명할 수 있다.
createStore로 스토어를 만들고dispatch/subscribe/getState를 사용할 수 있다.- 액션 생성자(Action Creator)로 Action 객체 생성을 함수로 캡슐화할 수 있다.
Action: 무슨 일이 일어났는지 설명하는 객체
Action은 상태를 어떻게 바꿀지가 아니라, **“무슨 일이 일어났는지”**를 설명하는 평범한 JavaScript 객체입니다. 반드시 type 필드를 가져야 하며, 관례상 payload에 추가 데이터를 담습니다.
| |
type은 문자열이면 무엇이든 되지만, 실무에서는 도메인/이벤트 형식(예: "cart/itemAdded")을 관례로 씁니다. 이 명명 규칙은 Redux Toolkit의 createSlice(17편)가 자동으로 생성해주는 형식이기도 합니다.
**액션 생성자(Action Creator)**는 Action 객체를 만드는 함수입니다. 매번 객체 리터럴을 손으로 쓰는 대신, 오타를 줄이고 재사용성을 높입니다.
| |
Reducer: 다음 상태를 계산하는 순수 함수
Reducer는 (state, action) => newState 형태의 순수 함수입니다. 현재 상태와 Action을 받아 다음 상태를 반환합니다.
| |
세 가지 규칙을 반드시 지켜야 합니다.
- 매개변수를 변경하지 않는다:
state.count += 1대신 새 객체{ count: state.count + 1 }을 반환한다(03·08편의 불변성 원칙). - 부수 효과를 일으키지 않는다: API 호출,
Date.now(),Math.random()등을 리듀서 안에서 쓰지 않는다. - 알 수 없는 액션에는 기존 상태를 그대로 반환한다:
default케이스가 없으면undefined를 반환해 상태가 사라져 버린다.
**초기값(= initialState)**은 Store가 처음 만들어질 때 Redux가 내부적으로 보내는 초기화 액션에 대응하기 위해 필요합니다. state가 undefined로 호출되면(스토어 최초 생성 시), 매개변수 기본값 문법 덕분에 initialState가 사용됩니다.
Store: 상태를 보관하고 변경을 조율한다
Store는 애플리케이션의 유일한 상태 보관소이며, Redux가 제공하는 createStore(또는 Redux Toolkit의 configureStore, 18편에서 다룸)로 만듭니다.
| |
Store는 세 가지 메서드를 제공합니다.
getState(): 현재 상태를 반환한다.dispatch(action): Action을 리듀서에 전달해 상태를 갱신한다.subscribe(listener): 상태가 바뀔 때마다 호출될 콜백을 등록한다.
| |
React-Redux(11편)의 useSelector는 내부적으로 이 subscribe를 사용해, 상태가 바뀔 때마다 컴포넌트를 리렌더링합니다.
세 요소가 함께 동작하는 흐름
sequenceDiagram
participant UI as UI 코드
participant Store as Store
participant Reducer as Reducer
UI->>Store: "dispatch(todoAdded('학습'))"
Store->>Reducer: "reducer(currentState, action)"
Reducer-->>Store: "새 state 반환"
Store->>Store: "내부 state 교체"
Store-->>UI: "구독자에게 알림(subscribe 콜백 실행)"
UI->>Store: "getState()로 최신 상태 조회"
리듀서가 여러 개라면 어떻게 하나의 Store로 합칠까요? Redux는 combineReducers를 제공해, 각 리듀서를 상태 트리의 한 “슬라이스(조각)“에 대응시킵니다.
| |
combineReducers가 만드는 상태 구조가 바로 03편에서 다룬 reduce()의 “여러 값을 하나로 누적한다"는 발상과 정확히 같습니다. 각 슬라이스 리듀서는 자신이 담당하는 부분(state.counter, state.todos)만 알면 되고, 서로의 존재를 몰라도 됩니다.
실무 체크리스트
- 모든 Action이
type필드를 가지고, 명명 규칙(도메인/이벤트)을 일관되게 따르는가? - 리듀서의
default케이스가 기존 상태를 그대로 반환하는가? - 여러 리듀서를
combineReducers로 합칠 때, 각 리듀서가 자신의 슬라이스만 책임지고 있는가?
연습 과제
기초(★☆☆)
counterReducer에counter/incrementedBy(payload로 증가량을 받는) 액션 타입을 추가해보세요.
중급(★★☆)
todos배열을 다루는todosReducer(추가·토글·삭제)를 직접 작성하고,combineReducers로counterReducer와 합쳐보세요.
고급(★★★)
store.subscribe()를 이용해, 상태가 바뀔 때마다 변경 이력을 배열에 기록하는 간단한 로거를 만들어보세요(21편 미들웨어의 원리를 미리 체험하는 실습입니다).
요약
- Action은 “무슨 일이 일어났는가"를 설명하는 객체이고, 액션 생성자는 그 객체를 만드는 함수다.
- Reducer는
(state, action) => newState형태의 순수 함수이며, 매개변수 변경·부수 효과·알 수 없는 액션에서의 상태 소실을 피해야 한다. - Store는
getState/dispatch/subscribe세 메서드로 상태를 보관하고 변경을 조율하며,combineReducers로 여러 리듀서를 하나의 상태 트리로 합친다.
참고 문헌 및 출처(추천)
- Redux 공식 문서, “Redux Fundamentals, Part 3: State, Actions, and Reducers”
- Redux 공식 문서, “createStore” API 레퍼런스
- Redux 공식 문서, “combineReducers” API 레퍼런스
![Featured image of post [Redux] 07. Redux의 핵심 - Action, Reducer, Store](/post/redux/redux-core-concepts/wordcloud_hu_f60cf9ab88cef682.webp)
![[Redux] 05. TypeScript 기초 - 타입 시스템 이해하기](/post/redux/typescript-basics/wordcloud_hu_a10feb7b41a22039.webp)
![[Redux] 06. Redux란 무엇인가 - Flux 아키텍처와 상태 관리](/post/redux/what-is-redux/wordcloud_hu_bc06cda637d98c61.webp)
![[Redux] 07. Redux의 핵심 - Action, Reducer, Store](/post/redux/redux-core-concepts/wordcloud_hu_c656c166a5f38d17.webp)
![[Redux] 08. 불변성의 중요성 - Immutability in Redux](/post/redux/immutability-in-redux/wordcloud_hu_3a5feb2a8eb157f4.webp)
![[Redux] 09. Redux 데이터 흐름 이해하기](/post/redux/redux-data-flow/wordcloud_hu_5d8af85599fe0b0c.webp)
![[Redux] 00. 커리큘럼 - 학습 로드맵](/post/redux/getting-started-redux/wordcloud_hu_2ed9b2e29c50fe99.webp)
![[Tutorial] Learn Prompting - 프롬프트 엔지니어링 무료 가이드 정리](/post/2022-12-30-learn-prompting/wordcloud_hu_6a9d105de4834753.webp)
![[Hardware] LattePanda Alpha에 Ubuntu 16.04 LTS 설치 가이드](/post/2018-12-06-install-ubuntu-16.04-on-lattepanda/wordcloud_hu_fc536f8de2cbd4bf.webp)
![[Redux] 11. React-Redux 시작하기 - Provider와 connect](/post/redux/react-redux-basics/wordcloud_hu_ff09d62dce5f2caf.webp)