개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Hooks — 함수형 컴포넌트에서 상태와 생명주기를 사용하는 API

2026년 5월 2일
ReactHooksuseStateuseEffect

React 16.8 이전에는 상태 관리와 생명주기 처리를 위해 반드시 클래스 컴포넌트를 사용해야 했습니다. Hooks는 함수형 컴포넌트에서도 이러한 기능을 사용할 수 있도록 React 16.8에서 도입된 API입니다.

Hooks 탄생 배경

클래스 컴포넌트 방식에는 몇 가지 고질적인 문제가 있었습니다.

첫째, 로직 재사용이 어렵습니다. 상태 관련 로직을 컴포넌트 간에 공유하려면 Higher-Order Component나 Render Props 같은 패턴을 사용해야 했는데, 이는 컴포넌트 트리를 깊게 만들어 코드를 추적하기 어렵게 만들었습니다.

둘째, 복잡한 컴포넌트는 이해하기 어렵습니다. 연관된 로직이 componentDidMount, componentDidUpdate, componentWillUnmount에 흩어져 작성되기 때문에 코드 응집도가 낮습니다.

셋째, 클래스 문법 자체의 장벽이 있습니다. this 바인딩 문제, 이벤트 핸들러마다 필요한 bind 호출 등은 JavaScript를 막 배운 개발자에게 높은 진입 장벽이 되었습니다.

Hooks는 이 문제들을 함수형 컴포넌트 안에서 해결합니다. 관련 로직을 하나의 Hook으로 묶어 재사용할 수 있고, this 바인딩도 필요 없습니다.

Hook 규칙

Hooks를 올바르게 사용하려면 두 가지 규칙을 반드시 지켜야 합니다. React는 내부적으로 Hook 호출 순서에 의존하여 각 Hook의 상태를 연결하기 때문에 이 규칙을 어기면 버그가 발생합니다.

규칙 1: 최상위에서만 호출합니다.

반복문, 조건문, 중첩 함수 안에서 Hook을 호출하면 안 됩니다. 컴포넌트가 렌더링될 때마다 Hook이 항상 같은 순서로 호출되어야 React가 상태를 올바르게 연결할 수 있습니다.

// 잘못된 사용
function Component({ isLoggedIn }) {
  if (isLoggedIn) {
    const [name, setName] = useState(""); // 조건문 안에서 호출 — 금지
  }
}

// 올바른 사용
function Component({ isLoggedIn }) {
  const [name, setName] = useState("");
  if (!isLoggedIn) return null;
  // ...
}

규칙 2: React 함수에서만 호출합니다.

Hook은 React 함수형 컴포넌트 또는 커스텀 Hook 안에서만 호출해야 합니다. 일반 JavaScript 함수에서는 호출할 수 없습니다.

주요 Hook 소개

useState: 컴포넌트에 상태를 추가합니다. 현재 상태 값과 상태를 업데이트하는 함수를 반환합니다.

const [count, setCount] = useState(0);

useEffect: 렌더링 이후 Side Effect를 처리합니다. 데이터 패칭, 구독 설정, DOM 직접 조작 등에 사용합니다.

Side Effect: 렌더링 결과와 무관하게 외부 시스템과 상호작용하는 모든 작업. 네트워크 요청, 타이머, DOM 조작 등이 해당됨.

useEffect(() => {
  document.title = `카운트: ${count}`;
}, [count]);

useContext: Context 값을 구독합니다. 컴포넌트 트리 깊숙이 있는 컴포넌트도 Context Provider의 값을 직접 읽을 수 있습니다.

useRef: 렌더링을 트리거하지 않는 변경 가능한 참조 값을 만들거나, DOM 요소에 직접 접근할 때 사용합니다.

useMemo / useCallback: 계산 비용이 큰 값이나 함수를 메모이제이션하여 불필요한 재계산을 방지합니다.

메모이제이션(Memoization): 이전에 계산한 결과를 저장해 두고, 같은 입력이 들어왔을 때 재계산 없이 저장된 결과를 반환하는 최적화 기법.

커스텀 Hook: use로 시작하는 함수를 만들어 상태 관련 로직을 컴포넌트에서 분리하고 재사용할 수 있습니다. 로직 재사용이 Hooks 도입의 핵심 목적 중 하나입니다.

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  useEffect(() => {
    const handler = () => setWidth(window.innerWidth);
    window.addEventListener("resize", handler);
    return () => window.removeEventListener("resize", handler);
  }, []);
  return width;
}

커스텀 Hook은 코드를 함수 단위로 쪼개는 자연스러운 수단이 되며, 테스트와 유지보수도 용이하게 만듭니다.

← 이전 글Event Handling — React에서 사용자 이벤트를 처리하는 방식
다음 글 →useEffect — 렌더링 이후 Side Effect를 처리하는 Hook