복잡한 상태 관리의 구원자: useReducer
useState만으로는 여러 개의 상태가 얽혀있거나 복잡한 로직을 처리하기가 어렵습니다. 이럴 때 useReducer 를 사용하면, 상태 업데이트 로직을 컴포넌트 외부의 Reducer 함수로 분리하여 코드를 훨씬 깔끔하고 예측 가능하게 만들 수 있습니다.
⚡ useReducer의 3가지 핵심 요소
용어
설명
비유
Action
어떤 상태 업데이트를 해야 할지 설명하는 객체 { type: 'DEPOSIT', payload: 1000 }
은행 창구에 제출하는 "입금 신청서"
Dispatch
Action 객체를 Reducer로 전달(발송)하는 함수
신청서를 창구 직원에게 "전달"하는 행위
Reducer
현재 State와 Action을 받아서 새로운 State 를 반환하는 함수
신청서를 보고 실제로 계좌 잔액을 업데이트하는 "은행원"
🔄 useReducer 동작 흐름도
버튼 클릭
onClick
dispatch()
Action
{ type: 'INC' }
Reducer 함수
Switch (type)
State
⚠️ 주의: Reducer 함수는 순수 함수(Pure Function)여야 합니다
Reducer 내부에서 직접 외부 상태를 변경하거나(Side Effect), 비동기 통신(API 호출)을 하면 안 됩니다. 반드시 매개변수로 받은 State와 Action만으로 예측 가능한 새로운 State 객체를 반환해야 합니다.
💻 실제 React 컴포넌트 적용 예제
위의 순수 자바스크립트 개념을 실제 React 컴포넌트(JSX) 로 적용하면 다음과 같습니다. useReducer 훅을 호출하여 [상태, 디스패치] 배열을 반환받아 사용합니다.
import React, { useReducer, useState } from 'react';
// 1. Reducer 함수 (상태 변화 로직을 컴포넌트 외부로 완벽히 분리!)
function accountReducer(state, action) {
switch (action.type) {
case 'DEPOSIT':
return { balance: state.balance + action.payload };
case 'WITHDRAW':
if (state.balance < action.payload) return state; // 잔액 부족 처리
return { balance: state.balance - action.payload };
default:
return state;
}
}
export default function BankApp() {
// 2. useReducer 초기화: [현재상태, 디스패치함수] 반환
const [state, dispatch] = useReducer(accountReducer, { balance: 0 });
const [amount, setAmount] = useState(10000);
return (
<div className="app-container">
<h3>은행 계좌 시스템 (React)</h3>
<div className="balance">
잔액: <span>{state.balance.toLocaleString()}</span>원
</div>
<input
type="number"
value={amount}
onChange={(e) => setAmount(Number(e.target.value))}
/>
<div className="buttons">
<button onClick={() => dispatch({ type: 'DEPOSIT', payload: amount })}>
입금하기
</button>
<button onClick={() => dispatch({ type: 'WITHDRAW', payload: amount })}>
출금하기
</button>
</div>
</div>
);
}
직접 실습해보기: 바닐라 JS로 Reducer 원리 파헤치기
위에서 살펴본 React의 useReducer가 내부적으로 어떻게 상태를 관리하고 화면을 업데이트(리렌더링)하는지 궁금하신가요?
바로 아래에 준비된 대화형 코드 에디터는 순수 자바스크립트(Vanilla JS)만으로 Reducer 패턴을 직접 구현해 본 예제입니다.
JS 탭의 코드를 살펴보면서 dispatch 함수가 어떻게 상태를 변경하고 콘솔(Console)에 로그를 찍는지 직접 확인해 보세요!