Redux
Redux는 애플리케이션의 모든 상태를 하나의 중앙 저장소에 관리하는 예측 가능한 상태 관리 라이브러리입니다.
상태(state)의 변화 흐름이 한 방향(One-way flow)로 고성되어 있어 동작이 명확하고 디버깅이 쉽습니다.
1️⃣ 구조 이해
🔹 Store
- 애플리케이션의 상타가 저장되는 중앙 저장소
- Redux에서는 앱 전체가 하나의 store만 갖는 것이 원칙(싱글 스토어)
Store 내부에는 다음 두 가지가 존재합니다.
- state: 애플리케이션에서 관라할 실제 데이터
- reducer: state가 어떻게 변경될지를 결정하는 함수
Store는 외부에서 다음 API를 제공합니다.
| API | 설명 |
|---|---|
getState() | 현재 상태(state)를 반환 |
dispatch(action) | reducer를 호출하여 상태를 변경 |
subscribe(listener) | 상태 변경 시 실행할 함수를 등록(UI 업데이트 등) |
🔹 Action
- 상태를 어떻게 변경할지 설명하는 "객체"
- 단순한 정보일 뿐이며, 변경 로직은 없음
{ type: "INCREMENT" }
Action의 규칙
- 반드시
type속성이 있어야 함 - 추가 데이터는 payload로 전달 가능
🔹 Reducer
- Action을 기반으로 새로운 state를 반환하는 순수 함수(Pure Function)
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return state + 1;
default:
return state;
}
}
Reducer의 특징
- 기존 state를 직접 변경하지 않음 (불변성 유지)
- 항상 새로운 state를 리턴
- 같은 입력(state + action)이 들어오면 항상 같은 결과가 나오는 순수 함수
🔹 Dispatch
- 상태를 변경한느 유일한 방법
- dispatch는 action을 reducer에게 전달
store.dispatch({ type: "INCREMENT" });
🔹 Subscribe
- 상태가 바뀔 때 호출되는 함수를 등록
- 주로 UI 업데이트에 사용됨
store.subscribe(() => {
render(store.getState());
});
2️⃣ Redux의 상태 변화 흐름(One-way Data Flow)
Redux는 단방향 데이터 흐름(One-way Flow) 구조를 갖고 있어 예측 가능성을 높입니다.
상태 변경 흐름은 다음과 같이 단순화 합니다.
UI → dispatch(action)
↓
reducer(state, action)
↓
새로운 state 생성
↓
store.subscribe(listener)
↓
UI 다시 렌더링
- 상태가 언제, 왜, 어떻게 바뀌었는지 추적하기 용이
- 디버깅이 매우 간단해짐
3️⃣ Redux에서 불변성이 중요한 이유
Reducer에서는 반드시 기존 state를 직접 변경하면 안 됩니다.
🧐 예시
state.count = state.count + 1; // ❌ 직접 수정 (mutate)
return { ...state, count: state.count + 1 }; // ✅ 새로운 객체 생성
불변성을 지키는 이유
- 변경 감지를 단순화할 수 있음
- Redux DevToolsdㅔ서 time-travel debugging이 가능
- 상태 추적이 쉬움
4️⃣ 실제 예제로 보는 Redux 앱 구성 패턴
JavaScript에서 Redux를 사용할 때는 상태가 바뀔 때마다 UI를 다시 그리도록 직접 subscribe를 연결합니다.
(React에서는 이 역할을 컴포넌트가 자동으로 수행하므로 직접 DOM을 갱신할 필요가 없습니다.)
🔹 상태 기반 렌더링
UI는 항상 store.getState()의 값으로 부터 만들어집니다.
🧐 예시
function render() {
const state = store.getState();
if (state.mode === "welcome") {
showWelcomePage();
} else if (state.mode === "read") {
showArticle(state.selectedId);
} else if (state.mode === "create") {
showCreateForm();
}
}
🔹 UI 이벤트 → Action dispatch
버튼 클릭 같은 이벤트는 상태를 직접 바꾸지 않고 항상 action을 dispatch합니다.
button.onclick = () => {
store.dispatch({ type: "CHANGE_MODE", mode: "create" });
};
🔹 Subscribe로 UI 자동 업데이트
Redux는 상태 변경 시 등록된 함수들을 자동 호출합니다.
store.subscribe(render);
dispatch → 새로운 state → subscribe → UI 업데이트
이 자동으로 수행됨.
5️⃣ Reducer 내부 로직 패턴
Reducer는 항상 다음 패턴을 유지합니다.
- state가 undefined일 때 → 초기 상태 반환
- ㅁction.type에 따라 분기
- 기존 state를 변경하지 않고 새로운 state생성
- 새로운 객체를 return
🧐 예시
function reducer(state, action) {
if (state === undefined) {
return {
mode: "welcome",
selectedId: null,
contents: []
};
}
switch (action.type) {
case "SELECT":
return {
...state,
selectedId: action.id,
mode: "read",
};
case "CREATE":
return {
...state,
contents: [...state.contents, action.payload],
};
// ...
}
}