Reduecer
1. useState, useReducer 개념 정리
useState는?
- 단순한 상태 하나를 다루기 쉬운 Hook
- 값 변경 시 setState로 바로 수정
- 예: 숫자 1개, 문자열 1개 상태 관리에 적합
useReducer는?
- 상태(state)를 관리하는 로직을 reducer 함수로 분리해서 처리
- 액션(action)을 보내면, reducer가 판단해서 상태를 변경
- 상태가 여러 개이거나 변경 로직이 복잡할 때 적합
2. 실습 예제로 비교
예제 시나리오: 숫자 카운터 (+, , 초기화)
A. useState로 만들었을 경우
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>현재 카운트: {count}</p>
<button onClick={() => setCount(count + 1)}>증가</button>
<button onClick={() => setCount(count - 1)}>감소</button>
<button onClick={() => setCount(0)}>초기화</button>
</div>
);
}
특징
- 상태는 1개 (count)
- 버튼마다 로직이 직접 들어감
- 간단하지만 로직이 컴포넌트 안에 계속 쌓이면 복잡해짐
B. useReducer로 만든 버전
import React, { useReducer } from 'react';
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count - 1 };
case 'RESET':
return { count: 0 };
default:
return state;
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>현재 카운트: {state.count}</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>증가</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>감소</button>
<button onClick={() => dispatch({ type: 'RESET' })}>초기화</button>
</div>
);
}
특징
- 상태 변화 로직은 컴포넌트 바깥(reducer)에서 관리
- 컴포넌트는 dispatch로 요청만 보냄
- 상태 변경 로직이 한 곳에 정리되어 있어서 추적, 유지보수, 테스트에 좋음
3. 비교 정리
항목 useState 방식 useReducer 방식
| 상태 수 | 1~2개면 편함 | 여러 개일수록 효과적 |
| 상태 변경 위치 | 컴포넌트 내부에 직접 작성 | reducer 함수로 분리 가능 |
| 가독성 | 단순한 경우 좋음 | 복잡한 경우에 더 깔끔함 |
| 확장성 | 상태가 많아지면 복잡해짐 | 액션 기반으로 로직 통합 가능 |
| 유지보수 | 상태 변경 흐름 파악 어려움 | 액션과 리듀서로 추적 가능 |
| 테스트 | 어려움 | reducer는 순수함수라 테스트 용이 |
4. 언제 사용해야 할까?
useState를 쓰는 게 더 나은 상황
- 상태가 1~2개이고 간단한 경우
- 복잡한 로직이 없는 경우
useReducer를 쓰는 게 좋은 상황
- 상태가 객체/배열 등 구조화되어 있을 때
- 여러 상태가 서로 영향을 주고받을 때
- 상태 변경 조건이 여러 개일 때 (조건 분기 많을 때)
- 같은 상태 로직을 여러 곳에서 재사용할 때
- 상태 변경 로직을 컴포넌트 바깥으로 빼고 싶을 때
5. 장점과 단점
항목 장점 단점
| 유지보수 | 상태 변경 로직이 한 곳에 정리돼 추적이 쉬움 | 단순한 경우엔 오히려 과함 |
| 코드 구조 | 복잡한 로직 분리가능, 테스트 편함 | 액션/타입 정의가 많아짐 |
| 재사용성 | 같은 reducer를 다른 컴포넌트에서 재사용 가능 | 코드가 길어질 수 있음 |
| 상태 흐름 | 명확하고 추론 가능 | 이해에 학습 곡선 있음 |
6. 주의할 점
- useReducer를 너무 간단한 컴포넌트에서 억지로 쓰면 오히려 복잡해질 수 있음
- dispatch({ type: '잘못된타입' })처럼 잘못된 액션이 들어오면 오류가 날 수 있으므로 default 처리를 꼭 해줘야 함
- reducer는 순수 함수여야 함 (외부 값 참조나 사이드 이펙트 있으면 안 됨)
결론
- useReducer는 복잡한 상태 관리, 로직 분리, 가독성 향상을 위한 훌륭한 도구
- useState만으로는 코드가 지저분해질 때 구조적으로 문제를 해결해줌
- 단순한 경우에는 과할 수 있지만, 상태가 커질수록 진가를 발휘함
생활코딩 실습정리
'Frontend > React' 카테고리의 다른 글
| Vite와 Create React App(CRA) 비교 (1) | 2025.08.11 |
|---|---|
| 생활코딩 React useReducer 실습 정리 (1) | 2025.07.27 |
| React State (0) | 2025.07.19 |
| 이벤트 핸들링 (1) | 2025.07.19 |
| Props 개념, 컴포넌트 재사용 (0) | 2025.07.19 |