ReactJS - useReducer 사용법
안녕하세요, 프로그래밍에 도전하는 여러분! 오늘 우리는 React hooks의 세계로 흥미로운 여정을 떠납니다. 특히 강력한 useReducer
hook에 집중해보겠습니다. 프로그래밍 초보자라도 걱정하지 마세요. 저는 수년 동안 수많은 학생들을 가르치며 이 단계별로 안내해왔습니다. 시작해보겠습니다!
useReducer는 무엇인가요?
자세한 내용에 들어가기 전에 useReducer
에 대해 이해해보겠습니다. 마치 비디오 게임을 플레이할 때, 캐릭터가 다양한 상태를 가지고 있다고 상상해보세요 - 체력, 힘, 속도 등. 게임을 진행하면서 이 상태들이 행동에 따라 변합니다. useReducer
는 이러한 상태 변화를 특정 규칙에 따라 관리하는 게임 엔진과 같습니다.
React 용어로는, useReducer
는 우리의 애플리케이션에서 복잡한 상태 로직을 관리하는 데 도움을 주는 hook입니다. 상태에 여러 서브 값이 있거나, 다음 상태가 이전 상태에 따라 달라질 때 특히 유용합니다.
useReducer hook의 서명
이제 useReducer
를 코드에서 어떻게 사용하는지 살펴보겠습니다. 기본 구조는 다음과 같습니다:
const [state, dispatch] = useReducer(reducer, initialState);
이를 구성해보겠습니다:
-
state
: 현재 상태입니다. 게임 비유에서는 캐릭터의 현재 체력과 같습니다. -
dispatch
: 상태를 업데이트하기 위해 사용하는 함수입니다. -
reducer
: 상태가 어떻게 변할지 지정하는 함수입니다. -
initialState
: 애플리케이션의 시작 상태입니다.
지금은 약간 혼란스러울 수 있지만, 걱정하지 마세요! 곧 실제로 보여드리면 이해가 될 것입니다.
reducer hook 적용하기
이제 useReducer
가 어떻게 작동하는지 이해하기 위해 간단한 카운터 애플리케이션을 만들어보겠습니다. 기본 설정으로 시작하고 그 위에 올리겠습니다.
import React, { useReducer } from 'react';
// Step 1: 초기 상태 정의
const initialState = { count: 0 };
// Step 2: reducer 함수 생성
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
// Step 3: Counter 컴포넌트 생성
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
export default Counter;
이를 단계별로 설명해보겠습니다:
-
useReducer
를 React에서 import합니다. -
initialState
를 카운트가 0인 상태로 정의합니다. - 현재 상태와 액션을 기반으로 새로운 상태를 반환하는
reducer
함수를 생성합니다. -
Counter
컴포넌트에서useReducer
를 사용하여 현재 상태와dispatch
함수를 얻습니다. - 현재 카운트와 두 개의 버튼을 렌더합니다. '+' 버튼은 'increment' 액션을 디스패치하고, '-' 버튼은 'decrement' 액션을 디스패치합니다.
'+' 버튼을 클릭하면 'increment' 액션을 디스패치하여 카운트를 증가시키고, '-' 버튼은 'decrement' 액션을 디스패치하여 카운트를 감소시킵니다.
useReducer 사용하기
이제 기본 예제를 보았으니, 더 복잡한 시나리오를 탐구해보겠습니다. 우리는 간단한 작업 관리 애플리케이션을 만들어 useReducer
를 사용하여 작업을 추가하고 제거하는 방법을 보겠습니다.
import React, { useReducer, useState } from 'react';
// Step 1: 초기 상태 정의
const initialState = { tasks: [] };
// Step 2: reducer 함수 생성
function reducer(state, action) {
switch (action.type) {
case 'ADD_TASK':
return { tasks: [...state.tasks, action.payload] };
case 'REMOVE_TASK':
return { tasks: state.tasks.filter((task, index) => index !== action.payload) };
default:
return state;
}
}
// Step 3: TaskManager 컴포넌트 생성
function TaskManager() {
const [state, dispatch] = useReducer(reducer, initialState);
const [newTask, setNewTask] = useState('');
const handleAddTask = () => {
if (newTask.trim()) {
dispatch({ type: 'ADD_TASK', payload: newTask });
setNewTask('');
}
};
const handleRemoveTask = (index) => {
dispatch({ type: 'REMOVE_TASK', payload: index });
};
return (
<div>
<input
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
placeholder="새로운 작업 입력"
/>
<button onClick={handleAddTask}>작업 추가</button>
<ul>
{state.tasks.map((task, index) => (
<li key={index}>
{task}
<button onClick={() => handleRemoveTask(index)}>제거</button>
</li>
))}
</ul>
</div>
);
}
export default TaskManager;
이 더 복잡한 예제에서:
-
initialState
는 작업의 배열을 가집니다. -
reducer
함수는 'ADD_TASK'와 'REMOVE_TASK' 두 가지 액션을 처리합니다. -
TaskManager
컴포넌트에서는useReducer
를 작업 관리에 사용하고,useState
를 입력 필드 관리에 사용합니다. - 작업을 추가하고 제거하는 함수를 정의하고, 이 함수들이 적절한 액션을 디스패치합니다.
- 새로운 작업을 입력할 수 있는 입력 필드와 추가 버튼, 현재 작업 목록과 각 작업에 대한 제거 버튼을 렌더합니다.
이 예제는 useReducer
가 복잡한 상태 로직을 깔끔하고 정리된 방식으로 관리하는 데 어떻게 도움이 되는지 보여줍니다.
메서드 표
여기서 다루었던 주요 메서드와 개념을 요약하는 표를 제공합니다:
메서드/개념 | 설명 | 예제 |
---|---|---|
useReducer | 복잡한 상태 로직을 관리하는 React hook | const [state, dispatch] = useReducer(reducer, initialState); |
reducer | 상태가 어떻게 변할지 지정하는 함수 | function reducer(state, action) { ... } |
dispatch | 상태를 업데이트하기 위해 사용하는 함수 | dispatch({ type: 'ADD_TASK', payload: newTask }) |
액션 | 상태에 어떤 변화를 가져올지 설명하는 객체 | { type: 'INCREMENT' } |
초기 상태 | 애플리케이션의 시작 상태 | const initialState = { count: 0 }; |
useReducer
를 효과적으로 사용하는 데는 연습이 필요합니다. 즉시 이해가 되지 않는다면 낙담하지 마세요 - 경험 많은 개발자들도 새로운 개념을 이해하는 데 시간이 필요합니다. 계속 코딩하고 실험하고, 가장 중요한 것은 즐겁게 만들어보세요! 당신이 복잡한 상태를 프로처럼 관리할 수 있을 때까지입니다. 행복하게 코딩하세요!
Credits: Image by storyset