React와 Redux에서의 불변성: 상태 관리를 효율적으로 개선하는 법
2025-02-10 08:13:55React와 Redux에서의 불변성 이해하기
React와 Redux는 현대 웹 개발에서 널리 사용되는 라이브러리입니다. 두 라이브러리 모두 상태 관리의 효율성을 위해 "불변성(immutability)" 개념을 중요시합니다. 이 글에서는 불변성이 왜 중요한지, 그리고 이러한 원칙을 어떻게 효과적으로 적용할 수 있는지에 대해 심도 깊게 알아보겠습니다.
React에서의 불변성과 useState
상태 변경 시 올바르지 않은 방법
React에서 상태는 불변으로 취급되어야 합니다. 아래 예시는 상태를 변경할 때 잘못된 접근 방식의 예를 보여줍니다:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
count++; // ❌ 상태를 직접 수정 (재렌더링이 되지 않음)
setCount(count);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
이 접근 방식에서는 count가 직접 수정되지만, React는 상태의 새로운 참조가 생성되었다고 판단하지 않아 재렌더링을 하지 않습니다.
올바른 불변성 유지 방식
불변성을 유지하며 상태를 업데이트하는 올바른 방법은 아래와 같습니다:
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1); // ✅ 새로운 값을 생성하여 재렌더링을 트리거
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
이 방법은 setCount가 새로운 값을 반환하여 React가 상태 변화로 인식하게끔 합니다.
Redux에서의 불변성과 상태 업데이트
Redux는 상태 변화를 추적하기 위해 불변성을 만족해야 합니다.
직접 상태를 변경하는 잘못된 접근
Redux에서 상태를 직접 변경하면 안 됩니다. 예를 들어:
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
if (action.type === "INCREMENT") {
state.count++; // ❌ 직접 수정 (변화 탐지 불가)
return state;
}
return state;
}
위의 코드는 Redux에서 상태 변화를 제대로 감지하지 못하게 합니다.
Redux에서 불변성을 유지하는 올바른 방법
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
if (action.type === "INCREMENT") {
return { ...state, count: state.count + 1 }; // ✅ 새로운 객체 생성
}
return state;
}
이 경우 Redux는 새로운 상태 객체를 감지할 수 있어 UI를 업데이트합니다.
React와 Redux에서의 배열 불변성 관리
배열 상태의 잘못된 변경
배열을 상태로 다룰 때, 직접 조작하면 올바르게 작동하지 않습니다:
const [todos, setTodos] = useState(["Learn React"]);
const addTodo = () => {
todos.push("Learn Redux"); // ❌ 배열 직접 수정
setTodos(todos);
};
이 방법은 상태의 참조를 변경하지 않기 때문에 문제가 발생합니다.
배열 불변성을 유지하는 방법
불변성을 유지하기 위해 배열을 업데이트할 때는 다음과 같이 합니다:
const [todos, setTodos] = useState(["Learn React"]);
const addTodo = () => {
setTodos([...todos, "Learn Redux"]); // ✅ 새로운 배열 생성
};
Spread 연산자를 사용해 새로운 배열을 생성하여 불변성을 유지합니다.
Immer.js로 불변성을 더 쉽게 관리하기
복잡한 상태 관리에서 immutability를 쉽게 다루기 위해 Immer.js를 사용할 수 있습니다. Immer.js는 코드가 다소 가변적인 것처럼 보이도록 작성하게 하지만 실제로는 불변성을 유지합니다.
Immer.js 사용 예시
import produce from "immer";
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
return produce(state, (draft) => {
if (action.type === "INCREMENT") {
draft.count++; // ✅ 불변성을 지키는 수정
}
});
}
Immer.js를 사용하면 코드는 간단해지고, 불변성을 걱정할 필요 없이 상태를 관리할 수 있습니다.
결론 및 주요 포인트
React와 Redux에서 상태를 관리할 때 불변성을 유지하는 것이 왜 중요한지 이해하는 것이 핵심입니다. 다음은 주요 포인트입니다:
- React는
setState를 사용해 새로운 객체나 배열을 받아야 재렌더링을 트리거합니다. - Redux는 직접적인 상태 변경을 피하고, 대신 새로운 상태 객체를 반환해야 합니다.
- Spread 연산자나
Object.assign을 활용하여 불변성을 유지하십시오. - Immer.js는 복잡한 상태 업데이트에 대해 손쉽게 불변성을 유지할 수 있게 도와줍니다.
추가 리소스
위 리소스들을 참고하여 불변성과 상태 관리에 대한 보다 깊이 있는 이해를 높일 수 있습니다.