[React Hook 완전 정복] Step 1: useState 기초와 활용

Suyo·2025년 6월 11일
0

React는 클래스형 컴포넌트에서 함수형 컴포넌트 중심으로 구조가 변화하면서, Hook이라는 개념을 도입했다. 그중에서도 useState는 가장 기초적이면서도 자주 사용되는 Hook으로, 컴포넌트 내부에 상태(state)를 선언하고 조작할 수 있게 해준다.

이 글에서는 공식 문서의 내용을 바탕으로, useState의 기본적인 사용법과 동작 원리를 정리해보았다.


Hook이란?

Hook은 함수형 컴포넌트에서 상태 값 관리생명주기 처리 같은 React 고유 기능을 사용할 수 있도록 도와주는 함수이다.
Hook 이전에는 상태 관리나 라이프사이클 처리를 위해 클래스형 컴포넌트를 사용해야 했지만, Hook을 통해 더 간결하고 선언적인 코드 작성이 가능해졌다.


Hook 사용 규칙

공식 문서에 따르면, Hook은 다음과 같은 두 가지 규칙을 반드시 따라야 한다.

1. 항상 컴포넌트 함수의 최상단에서 호출해야 한다

Hook은 컴포넌트가 렌더링될 때 호출 순서를 기준으로 상태를 연결하므로, 조건문이나 반복문, 중첩 함수 내부에서는 사용할 수 없다.

// ❌ 잘못된 예시
function MyComponent() {
  if (someCondition) {
    const [value, setValue] = useState(0); // 조건문 내부 호출 ❌
  }
}

// ✅ 올바른 예시
function MyComponent() {
  const [value, setValue] = useState(0); // 항상 최상단에서 호출
}

2. 오직 React 함수형 컴포넌트 또는 커스텀 Hook에서만 사용해야 한다

Hook은 일반 함수나 클래스 컴포넌트에서는 사용할 수 없다.
React의 렌더링 흐름과 상태 관리 시스템은 함수형 컴포넌트 기반으로 동작하기 때문에, 다음과 같은 코드에서는 오류가 발생한다.

// ❌ 잘못된 예시 1: 일반 함수에서 Hook 사용 (에러 발생)
function notAComponent() {
  const [value, setValue] = useState(0); // 오류: 일반 함수에서는 Hook 사용 불가
  return value;
}

// ❌ 잘못된 예시 2: 클래스 컴포넌트에서 Hook 사용 (에러 발생)
class MyComponent extends React.Component {
  render() {
    const [count, setCount] = useState(0); // 오류: 클래스에서는 Hook 사용 불가
    return <div>{count}</div>;
  }
}

// ✅ 올바른 예시 1: 함수형 컴포넌트에서 Hook 사용
function FunctionalComponent() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

// ✅ 올바른 예시 2: 커스텀 Hook 내부에서 사용
function useCounter(initialValue) {
  const [count, setCount] = useState(initialValue);
  return [count, setCount];
}

function CustomHookComponent() {
  const [count, setCount] = useCounter(0);
  return (
    <div>
      <p>커스텀 훅 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

useState란?

useState는 컴포넌트에 상태를 선언하고 해당 값을 변경할 수 있는 가장 기본적인 Hook이다.
호출 시에는 배열을 반환하며, 구조 분해 할당으로 상태값상태를 갱신하는 함수를 각각 받아 사용할 수 있다.

const [state, setState] = useState(initialValue);
  • state: 현재 상태 값
  • setState: 상태를 변경하는 함수
  • initialValue: 상태의 초기값

기본 예제

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // 초기값 0

  return (
    <div>
      <p>현재 카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

설명

  • useState(0)은 초기값을 0으로 설정하며, count는 현재 상태 값을, setCount는 그 값을 갱신하는 함수이다.
  • 버튼 클릭 시 setCount(count + 1)을 호출하면, React는 컴포넌트를 다시 렌더링하며 count의 변경된 값을 반영한다.

상태 변경은 비동기적이다

setState 함수는 즉시 상태를 바꾸는 것이 아니라, React가 다음 렌더링에서 새로운 값을 반영하도록 예약하는 구조로 동작한다.

setCount(count + 1);
console.log(count); // 여전히 이전 값일 수 있다!

따라서 이전 상태를 기반으로 새로운 상태를 계산할 때는 다음과 같이 함수형 업데이트를 사용하는 것이 안전하다.

setCount(prevCount => prevCount + 1);

상태는 어떤 타입이든 가능하다

초기값으로는 숫자뿐 아니라 문자열, 배열, 객체 등 모든 JavaScript 값을 사용할 수 있다.

const [name, setName] = useState("Alice");
const [todos, setTodos] = useState(["공부하기", "운동하기"]);
const [user, setUser] = useState({ name: "민수", age: 26 });

객체나 배열은 불변성을 유지한 채로 업데이트하는 것이 좋다:

setUser(prev => ({ ...prev, age: prev.age + 1 }));

계산 비용이 큰 초기값은 함수로 전달하자

const [data, setData] = useState(() => heavyComputation());

이렇게 함수로 전달하면, heavyComputation()처음 렌더링 시에만 실행된다. 매 렌더링마다 호출되는 것을 방지할 수 있다.


좋습니다! 글의 마무리 부분에 들어갈 수 있는 useState 핵심 개념 요약을 아래와 같이 정리해드릴게요. 시리즈형 블로그의 흐름을 유지하면서, 독자가 다시 한 번 중요한 내용을 짚고 넘어갈 수 있도록 구성했습니다.


핵심 정리

useState를 제대로 이해하기 위해 기억해야 할 핵심 포인트는 다음과 같다:

  1. 컴포넌트 내부 상태를 선언할 수 있게 해주는 Hook이다.
    → 상태 값과 상태 변경 함수를 [state, setState] 형태로 제공한다.

  2. 초기값은 숫자, 문자열, 배열, 객체 등 모든 JS 값이 가능하다.
    → 계산 비용이 클 경우 함수로 전달하여 최초 1회만 실행할 수도 있다.

  3. 상태 변경은 비동기적이다.
    setState 이후 바로 값을 읽으면 이전 값일 수 있다.
    → 이전 상태 기반 업데이트는 함수형으로 처리하는 것이 안전하다.

    setCount(prev => prev + 1);
  4. Hook은 컴포넌트 최상단에서만 사용해야 하며, 조건문이나 반복문, 일반 함수 내부에서는 사용할 수 없다.

  5. Hook은 함수형 컴포넌트 또는 커스텀 Hook에서만 사용할 수 있다.
    → 클래스 컴포넌트나 일반 함수에서 사용 시 오류가 발생한다.


마무리

useState는 가장 단순하지만 가장 널리 사용되는 Hook으로, 상태 기반 UI를 구현하는 데 있어 출발점이 되는 개념이다.
Hook의 규칙과 useState의 작동 방식을 정확히 이해하는 것이, 이후 다룰 useEffect, useRef 등 더 복잡한 Hook들을 배우는 데 튼튼한 기반이 된다.


참고 자료

profile
Mee-

0개의 댓글