Skip to content

[week1] 1주차 실습 - useState 직접 구현#1

Open
jogpfls wants to merge 1 commit intomainfrom
week1
Open

[week1] 1주차 실습 - useState 직접 구현#1
jogpfls wants to merge 1 commit intomainfrom
week1

Conversation

@jogpfls
Copy link
Member

@jogpfls jogpfls commented Nov 9, 2025

🛠️ 실습 요약

클로저를 활용하여 React의 useState를 직접 구현했습니다.

import { useReducer } from "react";

let state;

export default function useState(init) {
  // 값이 바뀔 때 강제 렌더링을 유도하기 위한 useReducer
  const [, force] = useReducer((x) => x + 1, 0);

  // 최초 렌더링 시 초기값 설정
  if (state === undefined) {
    state = init;
  }

  const setState = (next) => {
    const prev = state;
    const nextVal = typeof next === "function" ? next(prev) : next;

    // 값이 같다면 렌더링 생략
    if (Object.is(prev, nextVal)) return;

    state = nextVal; // 내부 상태 갱신
    force(); // 강제 렌더링
  };

  return [state, setState];
}

코드 설명

let state
→ 전역 스코프가 아닌, 클로저를 통해 컴포넌트마다 고유한 상태를 유지합니다.
함수 외부에서 직접 접근할 수 없고 useState가 반환하는 setState만을 통해 값이 변경됩니다.

리렌더링 구현을 흉내를 위한 useReducer 사용
→ 내부적으로 불변 상태를 갱신하고, dispatch 대신 force()를 호출해 리렌더링을 트리거합니다.
useReducer를 단순 카운터로 사용하여 React 내부의 “렌더 트리거” 역할을 흉내냈습니다.

Object.is 비교
→ 이전 값과 새 값을 비교하여 값이 동일하면 불필요한 렌더링을 방지합니다.
실제 React의 useState 구현 로직과 유사한 방식이기도 하고 이번 주차때 배운 Object.is를 사용해보았습니다.

클로저와의 연관성

클로저는 함수가 선언될 당시의 Lexical Environment을 기억하는 함수입니다.
위 코드에서 setState는 외부 함수(useState)의 지역 변수 state를 참조하므로 컴포넌트가 리렌더링된 이후에도 state 값이 사라지지 않고 은닉된 상태로 유지됩니다. 이로써 React의 useState가 내부적으로 클로저 기반으로 동작함을 직접 확인할 수 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants