React useState, 이것만 알면 끝! (초보자 완벽 가이드)

React useState, 이것만 알면 끝! (초보자 완벽 가이드)

React를 처음 배우면 가장 먼저 만나는 개념이 바로 useState입니다. “상태(state)가 뭐지?”, “왜 일반 변수를 안 쓰지?” 하는 의문이 들 수 있어요. 걱정 마세요. 이 글을 끝까지 읽으면 useState를 자신 있게 사용할 수 있습니다.

useState가 뭔가요?

useState는 React에서 컴포넌트의 상태를 관리하는 함수입니다.

“상태”란 시간이 지나면서 변할 수 있는 데이터를 말해요. 예를 들어:
– 버튼을 클릭한 횟수
– 입력 필드에 적은 텍스트
– 다크 모드 on/off 여부

일반 변수(let count = 0)를 쓰면 값이 바뀌어도 화면이 업데이트되지 않습니다. 하지만 useState를 쓰면 값이 바뀔 때 React가 자동으로 화면을 다시 그려줍니다.

기본 사용법: 카운터 만들기

가장 간단한 예제로 시작해볼게요. 버튼을 누르면 숫자가 올라가는 카운터입니다.

import { useState } from 'react';

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

  return (
    <div>
      <p>클릭 횟수: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        +1
      </button>
    </div>
  );
}

코드 해석

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

이 한 줄이 useState의 핵심입니다:

요소 설명
count 현재 상태 값 (처음에는 0)
setCount 상태를 변경하는 함수
useState(0) 초기값을 0으로 설정

버튼을 클릭하면 setCount(count + 1)이 실행되고, count가 1 증가한 후 화면이 자동으로 업데이트됩니다.

주의! setState 직후에 값을 확인하면 안 됩니다

초보자가 가장 많이 하는 실수입니다.

// 잘못된 예시
function handleClick() {
  setCount(count + 1);
  console.log(count); // 여전히 이전 값이 출력됨!
}

왜 그럴까요? 상태 변경은 비동기로 동작하기 때문입니다.

setCount를 호출하면 React는 “다음 렌더링 때 이 값으로 바꿔야겠다”라고 예약만 해둡니다. 바로 바뀌는 게 아니에요.

해결 방법

변경된 값이 필요하다면 함수형 업데이트를 사용하세요:

// 올바른 방법
setCount(prevCount => prevCount + 1);

이렇게 하면 항상 최신 상태를 기반으로 업데이트됩니다.

객체와 배열 상태: 불변성이 핵심!

useState로 객체나 배열을 관리할 때 절대 하면 안 되는 것이 있습니다.

잘못된 방법 (직접 수정)

// 이렇게 하면 안 됩니다!
const [user, setUser] = useState({ name: '철수', age: 25 });

function updateAge() {
  user.age = 26;        // 직접 수정
  setUser(user);        // React가 변화를 감지 못함!
}

왜 안 될까요? React는 객체의 참조(주소)가 바뀌었는지로 변화를 감지합니다. 내용만 바꾸고 같은 객체를 넘기면 “아, 똑같네”라고 판단해서 화면을 업데이트하지 않아요.

올바른 방법 (새 객체 생성)

// 스프레드 연산자로 새 객체 만들기
function updateAge() {
  setUser({ ...user, age: 26 });
}

...user는 기존 객체의 모든 속성을 복사하고, age: 26으로 덮어씁니다.

배열도 마찬가지

const [items, setItems] = useState(['사과', '바나나']);

// 추가
setItems([...items, '오렌지']);

// 삭제 (filter 사용)
setItems(items.filter(item => item !== '바나나'));

// 수정 (map 사용)
setItems(items.map(item =>
  item === '사과' ? '청사과' : item
));

여러 상태 관리하기

상태가 여러 개 필요하다면? useState를 여러 번 호출하면 됩니다.

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [isLoading, setIsLoading] = useState(false);

  // ...
}

관련된 상태를 객체로 묶을 수도 있어요:

const [form, setForm] = useState({
  email: '',
  password: ''
});

// 업데이트
setForm({ ...form, email: 'test@example.com' });

어떤 방식이 좋을까요?
독립적인 상태: 각각 useState 사용
함께 변하는 상태: 객체로 묶기

마무리

지금까지 배운 내용을 정리하면:

  1. useState는 컴포넌트에서 변하는 데이터를 관리합니다
  2. const [값, 세터함수] = useState(초기값) 형태로 사용합니다
  3. 상태 변경은 비동기로 동작합니다
  4. 객체/배열은 새로 만들어서 업데이트해야 합니다

이제 useState의 기본기를 익혔습니다! 다음 단계로는 useEffect를 배워보세요. 컴포넌트가 화면에 나타나거나 상태가 바뀔 때 특정 작업을 실행할 수 있습니다.

위로 스크롤