
함수형 프로그래밍에서는 데이터의 불변성이 매우 중요하다. 이는 부작용(side effects)을 최소화하고, 프로그램의 예측 가능성을 높이는 데 기여한다.
React에서 상태(state) 관리는 UI의 일관성과 성능 최적화에 중요한 역할을 한다.
useState는 React 컴포넌트에서 상태를 관리하는 훅이다. useState를 사용하면 컴포넌트 내에서 상태를 선언하고, 이 상태를 업데이트할 수 있다.useEffect는 컴포넌트가 렌더링될 때마다 특정 작업을 수행할 수 있게 해주는 훅이다. 예를 들어 API 호출, 구독 설정/해제 등이 이에 해당한다.useState만으로는 한계가 있다. 이럴 때 useReducer가 유용하다.useReducer는 상태 업데이트 로직을 컴포넌트 외부에 작성할 수 있게 해준다. 이를 통해 상태 관리 로직을 더 깔끔하게 분리하고 테스트하기 쉬워진다.React에서 불변성을 유지하는 것은 성능 최적화와 버그 방지에 매우 중요하다. 특히, React의 useState와 useReducer를 사용할 때 불변성을 유지하면 리액트의 리렌더링 프로세스를 효율적으로 관리할 수 있다.
Object.assign()을 사용하여 새로운 객체나 배열을 생성할 수 있다.
useReducer는 React의 상태 관리 훅 중 하나로, 주로 복잡한 상태 로직을 다룰 때 사용한다. useState와 비교했을 때, useReducer는 보다 구조화된 방식으로 상태를 관리할 수 있게 해주며, 특히 여러 하위 값이 있는 복잡한 상태 객체를 다룰 때 유리하다.
useReducer는 두 가지 주요 요소로 구성된다: reducer 함수와 초기 상태(initial state)이다.
Reducer 함수: 이 함수는 현재 상태와 업데이트를 위한 액션을 인자로 받아, 새로운 상태를 반환한다. 이 함수는 순수 함수로 작성되어야 하며, 이전 상태를 직접 변경하지 않고 새로운 상태 객체를 생성하여 반환해야 한다.
초기 상태(Initial State): useReducer를 사용할 때 초기 상태를 설정할 수 있다. 이 상태는 reducer 함수에 의해 관리된다.
import React, { useReducer } from 'react';
// 초기 상태 정의
const initialState = {
count: 0
};
// reducer 함수 정의
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</>
);
}
위 예시에서 reducer 함수는 현재 상태(state)와 액션 객체(action)를 받아 새로운 상태를 반환한다. 이 때, 상태를 직접 변경하지 않고, 새로운 객체를 생성하여 반환하는 것이 중요하다. 이는 불변성을 유지하는 핵심이다.
JavaScript에서 객체의 불변성을 유지하는 방법은 여러 가지가 있다. 가장 간단한 방법은 전개 연산자(Spread Operator)를 사용하는 것이다.
예시:
const object = { a: 1, b: 2 };
const newObject = { ...object, b: 3 }; // { a: 1, b: 3 }
여기서 newObject는 object의 복사본이며, b의 값만 변경되었다. 이렇게 하면 원본 객체는 변경되지 않는다.
배열의 경우에도 전개 연산자를 사용하여 불변성을 유지할 수 있다.
예시:
const array = [1, 2, 3];
const newArray = [...array, 4]; // [1, 2, 3, 4]
newArray는 array의 복사본이며, 새로운 요소가 추가되었다. 이 경우에도 원본 배열은 변경되지 않는다.
React에서 useReducer를 사용하면 복잡한 상태 관리를 보다 효과적으로 할 수 있다. 이 과정에서 불변성을 유지하는 것은 매우 중요하며, 이를 위해 순수 함수와 전개 연산자 등을 활용할 수 있다. 불변성을 유지하면 애플리케이션의 성능을 향상시키고, 예측 가능한 코드를 작성하는 데 도움이 된다.