useState가 클로저로 만들어진걸 알고 계신가요?
React의 useState와 클로저의 깊은 관계 이해하기
React의 useState Hook은 우리가 함수형 컴포넌트에서 상태를 관리할 수 있게 해주는 강력한 도구입니다. 하지만 useState가 어떻게 동작하는지, 특히 클로저(Closure)와 어떤 관계가 있는지 깊이 이해하고 계신가요? 오늘은 useState의 내부 동작 원리와 클로저의 관계에 대해 자세히 알아보겠습니다.
클로저란 무엇인가?
클로저는 함수와 그 함수가 선언된 렉시컬 환경의 조합입니다. 쉽게 말해, 함수가 자신이 생성될 때의 환경을 기억하는 것입니다. 다음 예시를 통해 클로저의 기본 개념을 이해해보겠습니다:
function createCounter() {
let count = 0; // 외부 변수
return function() { // 내부 함수
return count++; // 외부 변수를 참조
};
}
const counter = createCounter();
console.log(counter()); // 0
console.log(counter()); // 1
이 예시에서 내부 함수는 외부 변수 count
에 대한 참조를 유지합니다. 이것이 바로 클로저의 핵심 개념입니다.
useState는 어떻게 클로저를 활용하는가?
useState의 내부 구현을 간단히 모방해보면 다음과 같습니다:
function createUseState() {
const states = [];
let stateIndex = 0;
return function useState(initialValue) {
const currentIndex = stateIndex;
if (states[currentIndex] === undefined) {
states[currentIndex] = initialValue;
}
const setState = (newValue) => {
states[currentIndex] = newValue;
// 실제 React에서는 여기서 리렌더링을 트리거합니다
};
stateIndex++;
return [states[currentIndex], setState];
};
}
// React 내부에서 이와 유사한 방식으로 구현됩니다
const useState = createUseState();
이 구현에서 주목할 점들:
상태 보존:
states
배열은 클로저를 통해 보존됩니다. 이는 컴포넌트가 리렌더링되더라도 상태가 유지되는 이유입니다.독립성: 각 useState 호출은 자신만의 독립적인 상태를 가집니다. 이는 클로저가 각각의 상태 값을 독립적으로 관리할 수 있게 해주기 때문입니다.
캡슐화: 상태 값은 외부에서 직접 접근할 수 없고, 오직 setState 함수를 통해서만 수정할 수 있습니다.
실제 사용 예시
실제 React 컴포넌트에서 useState가 클로저를 활용하는 방식을 살펴보겠습니다:
function CounterComponent() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
const increment = () => {
setCount(count + 1); // 클로저를 통해 현재 count 값 접근
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>증가</button>
<input
value={text}
onChange={(e) => setText(e.target.value)}
/>
</div>
);
}
이 컴포넌트에서 각각의 useState 호출은 독립적인 상태를 가지며, 이는 클로저를 통해 관리됩니다. increment 함수는 자신이 생성될 때의 환경을 기억하고 있어, count 값에 접근할 수 있습니다.
클로저를 활용한 useState의 장점
- 상태 격리: 각 컴포넌트의 상태는 완벽하게 격리되어 있습니다.
- 메모리 효율: 필요한 상태만 메모리에 유지됩니다.
- 안전성: 상태 변경은 반드시 setState 함수를 통해서만 가능합니다.
결론
useState Hook이 클로저를 활용하는 방식을 이해하면, React의 상태 관리가 어떻게 동작하는지 더 깊이 이해할 수 있습니다. 이는 단순히 API를 사용하는 것을 넘어서, 더 효율적이고 버그 없는 코드를 작성하는 데 도움이 됩니다. 특히 복잡한 상태 관리나 성능 최적화가 필요한 상황에서 이러한 이해는 큰 도움이 될 것입니다.