프론트엔드 개발

useState가 클로저로 만들어진걸 알고 계신가요?

쫌수 2025. 1. 16. 21:21

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();

이 구현에서 주목할 점들:

  1. 상태 보존: states 배열은 클로저를 통해 보존됩니다. 이는 컴포넌트가 리렌더링되더라도 상태가 유지되는 이유입니다.

  2. 독립성: 각 useState 호출은 자신만의 독립적인 상태를 가집니다. 이는 클로저가 각각의 상태 값을 독립적으로 관리할 수 있게 해주기 때문입니다.

  3. 캡슐화: 상태 값은 외부에서 직접 접근할 수 없고, 오직 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의 장점

  1. 상태 격리: 각 컴포넌트의 상태는 완벽하게 격리되어 있습니다.
  2. 메모리 효율: 필요한 상태만 메모리에 유지됩니다.
  3. 안전성: 상태 변경은 반드시 setState 함수를 통해서만 가능합니다.

결론

useState Hook이 클로저를 활용하는 방식을 이해하면, React의 상태 관리가 어떻게 동작하는지 더 깊이 이해할 수 있습니다. 이는 단순히 API를 사용하는 것을 넘어서, 더 효율적이고 버그 없는 코드를 작성하는 데 도움이 됩니다. 특히 복잡한 상태 관리나 성능 최적화가 필요한 상황에서 이러한 이해는 큰 도움이 될 것입니다.