WeniVooks

검색

React 베이스캠프

useState Hook

3. useState Hook

useState는 React에서 가장 기본적이고 중요한 Hook입니다. 함수 컴포넌트에서 상태를 관리할 수 있게 해주는 핵심 기능입니다.

useState 기본 문법
import { useState } from 'react';
 
const [상태값, 상태변경함수] = useState(초기값);
import { useState } from 'react';
 
const [상태값, 상태변경함수] = useState(초기값);
예제: 간단한 카운터
import { useState } from 'react';
 
function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <h2>카운트: {count}</h2>
      <button onClick={() => setCount(count + 1)}>증가</button>
      <button onClick={() => setCount(count - 1)}>감소</button>
      <button onClick={() => setCount(0)}>리셋</button>
    </div>
  );
}
import { useState } from 'react';
 
function Counter() {
  const [count, setCount] = useState(0);
 
  return (
    <div>
      <h2>카운트: {count}</h2>
      <button onClick={() => setCount(count + 1)}>증가</button>
      <button onClick={() => setCount(count - 1)}>감소</button>
      <button onClick={() => setCount(0)}>리셋</button>
    </div>
  );
}
좋아요 버튼 데모
useState의 동작 원리
1. 초기 렌더링

컴포넌트가 처음 렌더링될 때 useState의 초기값이 사용됩니다.

function App() {
  // 처음에는 name이 '게스트'로 설정됨
  const [name, setName] = useState('게스트');
 
  return <h1>안녕하세요, {name}님!</h1>; // "안녕하세요, 게스트님!"
}
function App() {
  // 처음에는 name이 '게스트'로 설정됨
  const [name, setName] = useState('게스트');
 
  return <h1>안녕하세요, {name}님!</h1>; // "안녕하세요, 게스트님!"
}
2. 상태 업데이트

setter 함수를 호출하면 React가 컴포넌트를 다시 렌더링합니다.

function NameChanger() {
  const [name, setName] = useState('게스트');
 
  const changeName = () => {
    setName('김개발'); // 이 함수가 호출되면 컴포넌트가 다시 렌더링됨
  };
 
  return (
    <div>
      <h1>안녕하세요, {name}님!</h1>
      <button onClick={changeName}>이름 변경</button>
    </div>
  );
}
function NameChanger() {
  const [name, setName] = useState('게스트');
 
  const changeName = () => {
    setName('김개발'); // 이 함수가 호출되면 컴포넌트가 다시 렌더링됨
  };
 
  return (
    <div>
      <h1>안녕하세요, {name}님!</h1>
      <button onClick={changeName}>이름 변경</button>
    </div>
  );
}
3. 리렌더링 과정
function RenderingDemo() {
  const [count, setCount] = useState(0);
 
  console.log('컴포넌트가 렌더링되었습니다!', count);
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        클릭 (콘솔 확인)
      </button>
    </div>
  );
}
function RenderingDemo() {
  const [count, setCount] = useState(0);
 
  console.log('컴포넌트가 렌더링되었습니다!', count);
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        클릭 (콘솔 확인)
      </button>
    </div>
  );
}
useState 활용 패턴
1. 입력 필드 관리
function InputDemo() {
  const [text, setText] = useState('');
  const [email, setEmail] = useState('');
 
  return (
    <div>
      <div>
        <label>텍스트: </label>
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
        <p>입력된 텍스트: {text}</p>
      </div>
      
      <div>
        <label>이메일: </label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <p>입력된 이메일: {email}</p>
      </div>
    </div>
  );
}
function InputDemo() {
  const [text, setText] = useState('');
  const [email, setEmail] = useState('');
 
  return (
    <div>
      <div>
        <label>텍스트: </label>
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
        />
        <p>입력된 텍스트: {text}</p>
      </div>
      
      <div>
        <label>이메일: </label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <p>입력된 이메일: {email}</p>
      </div>
    </div>
  );
}
2. 체크박스와 라디오 버튼
function FormControls() {
  const [isChecked, setIsChecked] = useState(false);
  const [selectedOption, setSelectedOption] = useState('');
 
  return (
    <div>
      <div>
        <label>
          <input
            type="checkbox"
            checked={isChecked}
            onChange={(e) => setIsChecked(e.target.checked)}
          />
          동의합니다
        </label>
        <p>동의 상태: {isChecked ? '동의함' : '동의 안함'}</p>
      </div>
 
      <div>
        <p>좋아하는 색상을 선택하세요:</p>
        {['빨강', '파랑', '녹색'].map(color => (
          <label key={color}>
            <input
              type="radio"
              name="color"
              value={color}
              checked={selectedOption === color}
              onChange={(e) => setSelectedOption(e.target.value)}
            />
            {color}
          </label>
        ))}
        <p>선택된 색상: {selectedOption}</p>
      </div>
    </div>
  );
}
function FormControls() {
  const [isChecked, setIsChecked] = useState(false);
  const [selectedOption, setSelectedOption] = useState('');
 
  return (
    <div>
      <div>
        <label>
          <input
            type="checkbox"
            checked={isChecked}
            onChange={(e) => setIsChecked(e.target.checked)}
          />
          동의합니다
        </label>
        <p>동의 상태: {isChecked ? '동의함' : '동의 안함'}</p>
      </div>
 
      <div>
        <p>좋아하는 색상을 선택하세요:</p>
        {['빨강', '파랑', '녹색'].map(color => (
          <label key={color}>
            <input
              type="radio"
              name="color"
              value={color}
              checked={selectedOption === color}
              onChange={(e) => setSelectedOption(e.target.value)}
            />
            {color}
          </label>
        ))}
        <p>선택된 색상: {selectedOption}</p>
      </div>
    </div>
  );
}
3. 토글 기능
function ToggleDemo() {
  const [isVisible, setIsVisible] = useState(true);
  const [isDarkMode, setIsDarkMode] = useState(false);
 
  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        {isVisible ? '숨기기' : '보이기'}
      </button>
      
      {isVisible && (
        <p>이 텍스트는 토글됩니다!</p>
      )}
 
      <button onClick={() => setIsDarkMode(!isDarkMode)}>
        {isDarkMode ? '라이트 모드' : '다크 모드'}
      </button>
    </div>
  );
}
function ToggleDemo() {
  const [isVisible, setIsVisible] = useState(true);
  const [isDarkMode, setIsDarkMode] = useState(false);
 
  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>
        {isVisible ? '숨기기' : '보이기'}
      </button>
      
      {isVisible && (
        <p>이 텍스트는 토글됩니다!</p>
      )}
 
      <button onClick={() => setIsDarkMode(!isDarkMode)}>
        {isDarkMode ? '라이트 모드' : '다크 모드'}
      </button>
    </div>
  );
}
4. 배열 상태 관리
function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [inputValue, setInputValue] = useState('');
 
  const addTodo = () => {
    if (inputValue.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: inputValue.trim(),
        completed: false
      }]);
      setInputValue('');
    }
  };
 
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
 
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
 
  return (
    <div>
      <h2>할 일 목록</h2>
      <div>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="할 일을 입력하세요"
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
        />
        <button onClick={addTodo}>추가</button>
      </div>
 
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span>
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>삭제</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [inputValue, setInputValue] = useState('');
 
  const addTodo = () => {
    if (inputValue.trim()) {
      setTodos([...todos, {
        id: Date.now(),
        text: inputValue.trim(),
        completed: false
      }]);
      setInputValue('');
    }
  };
 
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ));
  };
 
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
 
  return (
    <div>
      <h2>할 일 목록</h2>
      <div>
        <input
          type="text"
          value={inputValue}
          onChange={(e) => setInputValue(e.target.value)}
          placeholder="할 일을 입력하세요"
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
        />
        <button onClick={addTodo}>추가</button>
      </div>
 
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span>
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>삭제</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
5. 객체 상태 관리
function UserForm() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: '',
    city: ''
  });
 
  const handleInputChange = (field, value) => {
    setUser(prevUser => ({
      ...prevUser,
      [field]: value
    }));
  };
 
  const resetForm = () => {
    setUser({
      name: '',
      email: '',
      age: '',
      city: ''
    });
  };
 
  return (
    <div>
      <h2>사용자 정보</h2>
      <div>
        <input
          type="text"
          placeholder="이름"
          value={user.name}
          onChange={(e) => handleInputChange('name', e.target.value)}
        />
      </div>
      <div>
        <input
          type="email"
          placeholder="이메일"
          value={user.email}
          onChange={(e) => handleInputChange('email', e.target.value)}
        />
      </div>
      <div>
        <input
          type="number"
          placeholder="나이"
          value={user.age}
          onChange={(e) => handleInputChange('age', e.target.value)}
        />
      </div>
      <div>
        <input
          type="text"
          placeholder="도시"
          value={user.city}
          onChange={(e) => handleInputChange('city', e.target.value)}
        />
      </div>
 
      <button onClick={resetForm}>초기화</button>
 
      <div>
        <h3>입력된 정보</h3>
        <p>이름: {user.name}</p>
        <p>이메일: {user.email}</p>
        <p>나이: {user.age}</p>
        <p>도시: {user.city}</p>
      </div>
    </div>
  );
}
function UserForm() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: '',
    city: ''
  });
 
  const handleInputChange = (field, value) => {
    setUser(prevUser => ({
      ...prevUser,
      [field]: value
    }));
  };
 
  const resetForm = () => {
    setUser({
      name: '',
      email: '',
      age: '',
      city: ''
    });
  };
 
  return (
    <div>
      <h2>사용자 정보</h2>
      <div>
        <input
          type="text"
          placeholder="이름"
          value={user.name}
          onChange={(e) => handleInputChange('name', e.target.value)}
        />
      </div>
      <div>
        <input
          type="email"
          placeholder="이메일"
          value={user.email}
          onChange={(e) => handleInputChange('email', e.target.value)}
        />
      </div>
      <div>
        <input
          type="number"
          placeholder="나이"
          value={user.age}
          onChange={(e) => handleInputChange('age', e.target.value)}
        />
      </div>
      <div>
        <input
          type="text"
          placeholder="도시"
          value={user.city}
          onChange={(e) => handleInputChange('city', e.target.value)}
        />
      </div>
 
      <button onClick={resetForm}>초기화</button>
 
      <div>
        <h3>입력된 정보</h3>
        <p>이름: {user.name}</p>
        <p>이메일: {user.email}</p>
        <p>나이: {user.age}</p>
        <p>도시: {user.city}</p>
      </div>
    </div>
  );
}
고급 useState 패턴
1. 지연 초기 상태 (Lazy Initial State)
function ExpensiveComponent() {
  // 매번 렌더링될 때마다 복잡한 계산이 실행됨 (비효율적)
  const [data, setData] = useState(expensiveCalculation());
 
  // 함수를 전달하면 초기 렌더링 시에만 실행됨 (효율적)
  const [betterData, setBetterData] = useState(() => expensiveCalculation());
 
  return <div>데이터: {betterData}</div>;
}
 
function expensiveCalculation() {
  console.log('복잡한 계산 실행됨!');
  return Math.random() * 1000;
}
function ExpensiveComponent() {
  // 매번 렌더링될 때마다 복잡한 계산이 실행됨 (비효율적)
  const [data, setData] = useState(expensiveCalculation());
 
  // 함수를 전달하면 초기 렌더링 시에만 실행됨 (효율적)
  const [betterData, setBetterData] = useState(() => expensiveCalculation());
 
  return <div>데이터: {betterData}</div>;
}
 
function expensiveCalculation() {
  console.log('복잡한 계산 실행됨!');
  return Math.random() * 1000;
}
2. 함수형 업데이트
function Counter() {
  const [count, setCount] = useState(0);
 
  const handleIncrement = () => {
    // 현재 값 기반 업데이트
    setCount(count + 1);
  };
 
  const handleIncrementBetter = () => {
    // 함수형 업데이트 (권장)
    setCount(prevCount => prevCount + 1);
  };
 
  const handleMultipleIncrement = () => {
    // 이렇게 하면 1만 증가함
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  };
 
  const handleMultipleIncrementBetter = () => {
    // 이렇게 하면 3 증가함
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
  };
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleIncrement}>+1</button>
      <button onClick={handleIncrementBetter}>+1 (Better)</button>
      <button onClick={handleMultipleIncrement}>+3 (문제)</button>
      <button onClick={handleMultipleIncrementBetter}>+3 (해결)</button>
    </div>
  );
}
function Counter() {
  const [count, setCount] = useState(0);
 
  const handleIncrement = () => {
    // 현재 값 기반 업데이트
    setCount(count + 1);
  };
 
  const handleIncrementBetter = () => {
    // 함수형 업데이트 (권장)
    setCount(prevCount => prevCount + 1);
  };
 
  const handleMultipleIncrement = () => {
    // 이렇게 하면 1만 증가함
    setCount(count + 1);
    setCount(count + 1);
    setCount(count + 1);
  };
 
  const handleMultipleIncrementBetter = () => {
    // 이렇게 하면 3 증가함
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
    setCount(prev => prev + 1);
  };
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleIncrement}>+1</button>
      <button onClick={handleIncrementBetter}>+1 (Better)</button>
      <button onClick={handleMultipleIncrement}>+3 (문제)</button>
      <button onClick={handleMultipleIncrementBetter}>+3 (해결)</button>
    </div>
  );
}
3. 여러 상태 관리하기
function Calculator() {
  const [num1, setNum1] = useState(0);
  const [num2, setNum2] = useState(0);
  const [operation, setOperation] = useState('+');
  const [result, setResult] = useState(0);
 
  const calculate = () => {
    let newResult;
    switch (operation) {
      case '+':
        newResult = parseFloat(num1) + parseFloat(num2);
        break;
      case '-':
        newResult = parseFloat(num1) - parseFloat(num2);
        break;
      case '*':
        newResult = parseFloat(num1) * parseFloat(num2);
        break;
      case '/':
        newResult = parseFloat(num1) / parseFloat(num2);
        break;
      default:
        newResult = 0;
    }
    setResult(newResult);
  };
 
  return (
    <div>
      <h2>계산기</h2>
      <div>
        <input
          type="number"
          value={num1}
          onChange={(e) => setNum1(e.target.value)}
        />
        
        <select
          value={operation}
          onChange={(e) => setOperation(e.target.value)}
        >
          <option value="+">+</option>
          <option value="-">-</option>
          <option value="*">×</option>
          <option value="/">÷</option>
        </select>
 
        <input
          type="number"
          value={num2}
          onChange={(e) => setNum2(e.target.value)}
        />
 
        <button onClick={calculate}>=</button>
 
        <span>
          {result}
        </span>
      </div>
    </div>
  );
}
function Calculator() {
  const [num1, setNum1] = useState(0);
  const [num2, setNum2] = useState(0);
  const [operation, setOperation] = useState('+');
  const [result, setResult] = useState(0);
 
  const calculate = () => {
    let newResult;
    switch (operation) {
      case '+':
        newResult = parseFloat(num1) + parseFloat(num2);
        break;
      case '-':
        newResult = parseFloat(num1) - parseFloat(num2);
        break;
      case '*':
        newResult = parseFloat(num1) * parseFloat(num2);
        break;
      case '/':
        newResult = parseFloat(num1) / parseFloat(num2);
        break;
      default:
        newResult = 0;
    }
    setResult(newResult);
  };
 
  return (
    <div>
      <h2>계산기</h2>
      <div>
        <input
          type="number"
          value={num1}
          onChange={(e) => setNum1(e.target.value)}
        />
        
        <select
          value={operation}
          onChange={(e) => setOperation(e.target.value)}
        >
          <option value="+">+</option>
          <option value="-">-</option>
          <option value="*">×</option>
          <option value="/">÷</option>
        </select>
 
        <input
          type="number"
          value={num2}
          onChange={(e) => setNum2(e.target.value)}
        />
 
        <button onClick={calculate}>=</button>
 
        <span>
          {result}
        </span>
      </div>
    </div>
  );
}
useState 사용 시 주의사항
1. 상태 직접 수정 금지
// ❌ 잘못된 방법
const [items, setItems] = useState([1, 2, 3]);
items.push(4); // 직접 수정하면 안됨!
 
// ✅ 올바른 방법
setItems([...items, 4]); // 새 배열 생성
// ❌ 잘못된 방법
const [items, setItems] = useState([1, 2, 3]);
items.push(4); // 직접 수정하면 안됨!
 
// ✅ 올바른 방법
setItems([...items, 4]); // 새 배열 생성
2. 객체/배열 상태 업데이트
// ❌ 잘못된 방법
const [user, setUser] = useState({ name: 'John', age: 25 });
user.name = 'Jane'; // 직접 수정하면 안됨!
 
// ✅ 올바른 방법
setUser({ ...user, name: 'Jane' }); // 새 객체 생성
// ❌ 잘못된 방법
const [user, setUser] = useState({ name: 'John', age: 25 });
user.name = 'Jane'; // 직접 수정하면 안됨!
 
// ✅ 올바른 방법
setUser({ ...user, name: 'Jane' }); // 새 객체 생성
3. 비동기 특성 이해
function AsyncExample() {
  const [count, setCount] = useState(0);
 
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // 아직 이전 값이 출력됨!
  };
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleClick}>클릭</button>
    </div>
  );
}
function AsyncExample() {
  const [count, setCount] = useState(0);
 
  const handleClick = () => {
    setCount(count + 1);
    console.log(count); // 아직 이전 값이 출력됨!
  };
 
  return (
    <div>
      <p>카운트: {count}</p>
      <button onClick={handleClick}>클릭</button>
    </div>
  );
}
실습: 간단한 게임

useState를 활용한 숫자 맞추기 게임을 만들어봅시다:

import { useState } from 'react';
 
function NumberGuessingGame() {
  const [targetNumber] = useState(() => Math.floor(Math.random() * 100) + 1);
  const [guess, setGuess] = useState('');
  const [attempts, setAttempts] = useState(0);
  const [message, setMessage] = useState('1부터 100 사이의 숫자를 맞춰보세요!');
  const [gameOver, setGameOver] = useState(false);
  const [history, setHistory] = useState([]);
 
  const handleGuess = () => {
    const guessNum = parseInt(guess);
    
    if (isNaN(guessNum) || guessNum < 1 || guessNum > 100) {
      setMessage('1부터 100 사이의 숫자를 입력해주세요!');
      return;
    }
 
    const newAttempts = attempts + 1;
    setAttempts(newAttempts);
    setHistory([...history, guessNum]);
 
    if (guessNum === targetNumber) {
      setMessage(`🎉 정답입니다! ${newAttempts}번 만에 맞추셨네요!`);
      setGameOver(true);
    } else if (guessNum < targetNumber) {
      setMessage(`더 큰 수를 입력해보세요! (시도: ${newAttempts}번)`);
    } else {
      setMessage(`더 작은 수를 입력해보세요! (시도: ${newAttempts}번)`);
    }
 
    setGuess('');
  };
 
  const resetGame = () => {
    window.location.reload(); // 간단한 게임 리셋
  };
 
  return (
    <div>
      <h2>숫자 맞추기 게임</h2>
      <p>{message}</p>
      
      {!gameOver && (
        <div>
          <input
            type="number"
            value={guess}
            onChange={(e) => setGuess(e.target.value)}
            placeholder="숫자 입력"
            min="1"
            max="100"
            onKeyPress={(e) => e.key === 'Enter' && handleGuess()}
          />
          <button onClick={handleGuess}>추측</button>
        </div>
      )}
 
      <p>시도 횟수: {attempts}</p>
 
      {history.length > 0 && (
        <div>
          <h3>추측 기록</h3>
          <p>{history.join(', ')}</p>
        </div>
      )}
 
      {gameOver && (
        <button onClick={resetGame}>
          새 게임
        </button>
      )}
    </div>
  );
}
 
export default NumberGuessingGame;
import { useState } from 'react';
 
function NumberGuessingGame() {
  const [targetNumber] = useState(() => Math.floor(Math.random() * 100) + 1);
  const [guess, setGuess] = useState('');
  const [attempts, setAttempts] = useState(0);
  const [message, setMessage] = useState('1부터 100 사이의 숫자를 맞춰보세요!');
  const [gameOver, setGameOver] = useState(false);
  const [history, setHistory] = useState([]);
 
  const handleGuess = () => {
    const guessNum = parseInt(guess);
    
    if (isNaN(guessNum) || guessNum < 1 || guessNum > 100) {
      setMessage('1부터 100 사이의 숫자를 입력해주세요!');
      return;
    }
 
    const newAttempts = attempts + 1;
    setAttempts(newAttempts);
    setHistory([...history, guessNum]);
 
    if (guessNum === targetNumber) {
      setMessage(`🎉 정답입니다! ${newAttempts}번 만에 맞추셨네요!`);
      setGameOver(true);
    } else if (guessNum < targetNumber) {
      setMessage(`더 큰 수를 입력해보세요! (시도: ${newAttempts}번)`);
    } else {
      setMessage(`더 작은 수를 입력해보세요! (시도: ${newAttempts}번)`);
    }
 
    setGuess('');
  };
 
  const resetGame = () => {
    window.location.reload(); // 간단한 게임 리셋
  };
 
  return (
    <div>
      <h2>숫자 맞추기 게임</h2>
      <p>{message}</p>
      
      {!gameOver && (
        <div>
          <input
            type="number"
            value={guess}
            onChange={(e) => setGuess(e.target.value)}
            placeholder="숫자 입력"
            min="1"
            max="100"
            onKeyPress={(e) => e.key === 'Enter' && handleGuess()}
          />
          <button onClick={handleGuess}>추측</button>
        </div>
      )}
 
      <p>시도 횟수: {attempts}</p>
 
      {history.length > 0 && (
        <div>
          <h3>추측 기록</h3>
          <p>{history.join(', ')}</p>
        </div>
      )}
 
      {gameOver && (
        <button onClick={resetGame}>
          새 게임
        </button>
      )}
    </div>
  );
}
 
export default NumberGuessingGame;
정리

useState Hook의 핵심을 학습했습니다:

  1. useState는 함수 컴포넌트에서 상태를 관리하는 Hook입니다
  2. [상태값, setter함수] = useState(초기값) 형태로 사용합니다
  3. 상태 변경 시 컴포넌트가 재렌더링됩니다
  4. 직접 수정 대신 setter 함수를 사용해야 합니다
  5. 함수형 업데이트로 더 안전한 상태 변경이 가능합니다

다음 장에서는 이벤트 처리에 대해 더 자세히 알아보겠습니다.

3.1 State란?3.3 이벤트 처리 심화