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 사용
– 함께 변하는 상태: 객체로 묶기
마무리
지금까지 배운 내용을 정리하면:
- useState는 컴포넌트에서 변하는 데이터를 관리합니다
const [값, 세터함수] = useState(초기값)형태로 사용합니다- 상태 변경은 비동기로 동작합니다
- 객체/배열은 새로 만들어서 업데이트해야 합니다
이제 useState의 기본기를 익혔습니다! 다음 단계로는 useEffect를 배워보세요. 컴포넌트가 화면에 나타나거나 상태가 바뀔 때 특정 작업을 실행할 수 있습니다.