WeniVooks

검색

React 베이스캠프

이벤트 처리 심화

3. 이벤트 처리 심화

React에서 다양한 이벤트를 처리하는 고급 기법들을 배워보겠습니다. 사용자의 입력을 받고, 폼을 처리하며, 복잡한 상호작용을 구현하는 방법을 알아봅시다.

기본 이벤트 처리
클릭 이벤트
import { useState } from 'react';
 
function ClickExample() {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState('버튼을 클릭해보세요');
 
  const handleClick = () => {
    setCount(count + 1);
    setMessage(`버튼을 ${count + 1}번 클릭했습니다`);
  };
 
  const handleReset = () => {
    setCount(0);
    setMessage('초기화되었습니다');
  };
 
  return (
    <div>
      <h3>클릭 이벤트 예제</h3>
      <p>{message}</p>
      <p>클릭 횟수: {count}</p>
      <button onClick={handleClick}>클릭하기</button>
      <button onClick={handleReset}>초기화</button>
    </div>
  );
}
import { useState } from 'react';
 
function ClickExample() {
  const [count, setCount] = useState(0);
  const [message, setMessage] = useState('버튼을 클릭해보세요');
 
  const handleClick = () => {
    setCount(count + 1);
    setMessage(`버튼을 ${count + 1}번 클릭했습니다`);
  };
 
  const handleReset = () => {
    setCount(0);
    setMessage('초기화되었습니다');
  };
 
  return (
    <div>
      <h3>클릭 이벤트 예제</h3>
      <p>{message}</p>
      <p>클릭 횟수: {count}</p>
      <button onClick={handleClick}>클릭하기</button>
      <button onClick={handleReset}>초기화</button>
    </div>
  );
}
입력 이벤트
import { useState } from 'react';
 
function InputExample() {
  const [text, setText] = useState('');
  const [savedText, setSavedText] = useState('');
 
  const handleInputChange = (event) => {
    setText(event.target.value);
  };
 
  const handleSave = () => {
    setSavedText(text);
    setText('');
  };
 
  const handleKeyPress = (event) => {
    if (event.key === 'Enter') {
      handleSave();
    }
  };
 
  return (
    <div>
      <h3>입력 이벤트 예제</h3>
      <input
        type="text"
        value={text}
        onChange={handleInputChange}
        onKeyPress={handleKeyPress}
        placeholder="텍스트를 입력하세요"
      />
      <button onClick={handleSave}>저장</button>
      <p>현재 입력: {text}</p>
      <p>저장된 텍스트: {savedText}</p>
    </div>
  );
}
import { useState } from 'react';
 
function InputExample() {
  const [text, setText] = useState('');
  const [savedText, setSavedText] = useState('');
 
  const handleInputChange = (event) => {
    setText(event.target.value);
  };
 
  const handleSave = () => {
    setSavedText(text);
    setText('');
  };
 
  const handleKeyPress = (event) => {
    if (event.key === 'Enter') {
      handleSave();
    }
  };
 
  return (
    <div>
      <h3>입력 이벤트 예제</h3>
      <input
        type="text"
        value={text}
        onChange={handleInputChange}
        onKeyPress={handleKeyPress}
        placeholder="텍스트를 입력하세요"
      />
      <button onClick={handleSave}>저장</button>
      <p>현재 입력: {text}</p>
      <p>저장된 텍스트: {savedText}</p>
    </div>
  );
}
폼 이벤트 처리
간단한 로그인 폼
import { useState } from 'react';
 
function LoginForm() {
  const [formData, setFormData] = useState({
    username: '',
    password: ''
  });
  const [isLoggedIn, setIsLoggedIn] = useState(false);
 
  const handleInputChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };
 
  const handleSubmit = (event) => {
    event.preventDefault(); // 페이지 새로고침 방지
    
    if (formData.username && formData.password) {
      setIsLoggedIn(true);
      alert('로그인 성공!');
    } else {
      alert('사용자명과 비밀번호를 모두 입력해주세요');
    }
  };
 
  const handleLogout = () => {
    setIsLoggedIn(false);
    setFormData({ username: '', password: '' });
  };
 
  if (isLoggedIn) {
    return (
      <div>
        <h3>환영합니다, {formData.username}님!</h3>
        <button onClick={handleLogout}>로그아웃</button>
      </div>
    );
  }
 
  return (
    <div>
      <h3>로그인</h3>
      <form onSubmit={handleSubmit}>
        <div>
          <label>사용자명:</label>
          <input
            type="text"
            name="username"
            value={formData.username}
            onChange={handleInputChange}
          />
        </div>
        <div>
          <label>비밀번호:</label>
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleInputChange}
          />
        </div>
        <button type="submit">로그인</button>
      </form>
    </div>
  );
}
import { useState } from 'react';
 
function LoginForm() {
  const [formData, setFormData] = useState({
    username: '',
    password: ''
  });
  const [isLoggedIn, setIsLoggedIn] = useState(false);
 
  const handleInputChange = (event) => {
    const { name, value } = event.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };
 
  const handleSubmit = (event) => {
    event.preventDefault(); // 페이지 새로고침 방지
    
    if (formData.username && formData.password) {
      setIsLoggedIn(true);
      alert('로그인 성공!');
    } else {
      alert('사용자명과 비밀번호를 모두 입력해주세요');
    }
  };
 
  const handleLogout = () => {
    setIsLoggedIn(false);
    setFormData({ username: '', password: '' });
  };
 
  if (isLoggedIn) {
    return (
      <div>
        <h3>환영합니다, {formData.username}님!</h3>
        <button onClick={handleLogout}>로그아웃</button>
      </div>
    );
  }
 
  return (
    <div>
      <h3>로그인</h3>
      <form onSubmit={handleSubmit}>
        <div>
          <label>사용자명:</label>
          <input
            type="text"
            name="username"
            value={formData.username}
            onChange={handleInputChange}
          />
        </div>
        <div>
          <label>비밀번호:</label>
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleInputChange}
          />
        </div>
        <button type="submit">로그인</button>
      </form>
    </div>
  );
}
체크박스와 라디오 버튼
import { useState } from 'react';
 
function SelectionForm() {
  const [preferences, setPreferences] = useState({
    newsletter: false,
    notifications: false,
    theme: 'light',
    language: 'ko'
  });
 
  const handleCheckboxChange = (event) => {
    const { name, checked } = event.target;
    setPreferences({
      ...preferences,
      [name]: checked
    });
  };
 
  const handleRadioChange = (event) => {
    const { name, value } = event.target;
    setPreferences({
      ...preferences,
      [name]: value
    });
  };
 
  return (
    <div>
      <h3>설정</h3>
      
      <div>
        <h4>알림 설정</h4>
        <label>
          <input
            type="checkbox"
            name="newsletter"
            checked={preferences.newsletter}
            onChange={handleCheckboxChange}
          />
          뉴스레터 구독
        </label>
        <br />
        <label>
          <input
            type="checkbox"
            name="notifications"
            checked={preferences.notifications}
            onChange={handleCheckboxChange}
          />
          푸시 알림
        </label>
      </div>
 
      <div>
        <h4>테마 선택</h4>
        <label>
          <input
            type="radio"
            name="theme"
            value="light"
            checked={preferences.theme === 'light'}
            onChange={handleRadioChange}
          />
          라이트 모드
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="theme"
            value="dark"
            checked={preferences.theme === 'dark'}
            onChange={handleRadioChange}
          />
          다크 모드
        </label>
      </div>
 
      <div>
        <h4>언어 선택</h4>
        <select
          name="language"
          value={preferences.language}
          onChange={handleRadioChange}
        >
          <option value="ko">한국어</option>
          <option value="en">English</option>
          <option value="ja">日本語</option>
        </select>
      </div>
 
      <div>
        <h4>현재 설정</h4>
        <p>뉴스레터: {preferences.newsletter ? '구독함' : '구독안함'}</p>
        <p>알림: {preferences.notifications ? '켜짐' : '꺼짐'}</p>
        <p>테마: {preferences.theme}</p>
        <p>언어: {preferences.language}</p>
      </div>
    </div>
  );
}
import { useState } from 'react';
 
function SelectionForm() {
  const [preferences, setPreferences] = useState({
    newsletter: false,
    notifications: false,
    theme: 'light',
    language: 'ko'
  });
 
  const handleCheckboxChange = (event) => {
    const { name, checked } = event.target;
    setPreferences({
      ...preferences,
      [name]: checked
    });
  };
 
  const handleRadioChange = (event) => {
    const { name, value } = event.target;
    setPreferences({
      ...preferences,
      [name]: value
    });
  };
 
  return (
    <div>
      <h3>설정</h3>
      
      <div>
        <h4>알림 설정</h4>
        <label>
          <input
            type="checkbox"
            name="newsletter"
            checked={preferences.newsletter}
            onChange={handleCheckboxChange}
          />
          뉴스레터 구독
        </label>
        <br />
        <label>
          <input
            type="checkbox"
            name="notifications"
            checked={preferences.notifications}
            onChange={handleCheckboxChange}
          />
          푸시 알림
        </label>
      </div>
 
      <div>
        <h4>테마 선택</h4>
        <label>
          <input
            type="radio"
            name="theme"
            value="light"
            checked={preferences.theme === 'light'}
            onChange={handleRadioChange}
          />
          라이트 모드
        </label>
        <br />
        <label>
          <input
            type="radio"
            name="theme"
            value="dark"
            checked={preferences.theme === 'dark'}
            onChange={handleRadioChange}
          />
          다크 모드
        </label>
      </div>
 
      <div>
        <h4>언어 선택</h4>
        <select
          name="language"
          value={preferences.language}
          onChange={handleRadioChange}
        >
          <option value="ko">한국어</option>
          <option value="en">English</option>
          <option value="ja">日本語</option>
        </select>
      </div>
 
      <div>
        <h4>현재 설정</h4>
        <p>뉴스레터: {preferences.newsletter ? '구독함' : '구독안함'}</p>
        <p>알림: {preferences.notifications ? '켜짐' : '꺼짐'}</p>
        <p>테마: {preferences.theme}</p>
        <p>언어: {preferences.language}</p>
      </div>
    </div>
  );
}
이벤트 객체 활용
마우스 이벤트 정보
import { useState } from 'react';
 
function MouseEventExample() {
  const [mouseInfo, setMouseInfo] = useState({
    x: 0,
    y: 0,
    button: '',
    clickCount: 0
  });
 
  const handleMouseMove = (event) => {
    setMouseInfo(prev => ({
      ...prev,
      x: event.clientX,
      y: event.clientY
    }));
  };
 
  const handleMouseClick = (event) => {
    const buttonNames = ['왼쪽', '휠', '오른쪽'];
    setMouseInfo(prev => ({
      ...prev,
      button: buttonNames[event.button] || '알 수 없음',
      clickCount: prev.clickCount + 1
    }));
  };
 
  return (
    <div>
      <h3>마우스 이벤트 정보</h3>
      <div
        onMouseMove={handleMouseMove}
        onClick={handleMouseClick}
      >
        마우스를 움직이거나 클릭해보세요
      </div>
      <p>마우스 위치: ({mouseInfo.x}, {mouseInfo.y})</p>
      <p>마지막 클릭 버튼: {mouseInfo.button}</p>
      <p>총 클릭 횟수: {mouseInfo.clickCount}</p>
    </div>
  );
}
import { useState } from 'react';
 
function MouseEventExample() {
  const [mouseInfo, setMouseInfo] = useState({
    x: 0,
    y: 0,
    button: '',
    clickCount: 0
  });
 
  const handleMouseMove = (event) => {
    setMouseInfo(prev => ({
      ...prev,
      x: event.clientX,
      y: event.clientY
    }));
  };
 
  const handleMouseClick = (event) => {
    const buttonNames = ['왼쪽', '휠', '오른쪽'];
    setMouseInfo(prev => ({
      ...prev,
      button: buttonNames[event.button] || '알 수 없음',
      clickCount: prev.clickCount + 1
    }));
  };
 
  return (
    <div>
      <h3>마우스 이벤트 정보</h3>
      <div
        onMouseMove={handleMouseMove}
        onClick={handleMouseClick}
      >
        마우스를 움직이거나 클릭해보세요
      </div>
      <p>마우스 위치: ({mouseInfo.x}, {mouseInfo.y})</p>
      <p>마지막 클릭 버튼: {mouseInfo.button}</p>
      <p>총 클릭 횟수: {mouseInfo.clickCount}</p>
    </div>
  );
}
키보드 이벤트
import { useState } from 'react';
 
function KeyboardExample() {
  const [keyInfo, setKeyInfo] = useState({
    lastKey: '',
    keyHistory: [],
    specialKeys: []
  });
 
  const handleKeyDown = (event) => {
    const specialKeys = [];
    if (event.ctrlKey) specialKeys.push('Ctrl');
    if (event.shiftKey) specialKeys.push('Shift');
    if (event.altKey) specialKeys.push('Alt');
 
    setKeyInfo(prev => ({
      lastKey: event.key,
      keyHistory: [...prev.keyHistory.slice(-9), event.key],
      specialKeys: specialKeys
    }));
 
    // 특별한 키 조합 처리
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault();
      alert('저장 기능 (Ctrl+S가 눌렸습니다)');
    }
  };
 
  return (
    <div>
      <h3>키보드 이벤트</h3>
      <input
        type="text"
        placeholder="키를 눌러보세요"
        onKeyDown={handleKeyDown}
      />
      <p>마지막 키: {keyInfo.lastKey}</p>
      <p>눌린 특수키: {keyInfo.specialKeys.join(', ') || '없음'}</p>
      <p>키 히스토리: {keyInfo.keyHistory.join(' → ')}</p>
      <p>Ctrl+S를 눌러보세요!</p>
    </div>
  );
}
import { useState } from 'react';
 
function KeyboardExample() {
  const [keyInfo, setKeyInfo] = useState({
    lastKey: '',
    keyHistory: [],
    specialKeys: []
  });
 
  const handleKeyDown = (event) => {
    const specialKeys = [];
    if (event.ctrlKey) specialKeys.push('Ctrl');
    if (event.shiftKey) specialKeys.push('Shift');
    if (event.altKey) specialKeys.push('Alt');
 
    setKeyInfo(prev => ({
      lastKey: event.key,
      keyHistory: [...prev.keyHistory.slice(-9), event.key],
      specialKeys: specialKeys
    }));
 
    // 특별한 키 조합 처리
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault();
      alert('저장 기능 (Ctrl+S가 눌렸습니다)');
    }
  };
 
  return (
    <div>
      <h3>키보드 이벤트</h3>
      <input
        type="text"
        placeholder="키를 눌러보세요"
        onKeyDown={handleKeyDown}
      />
      <p>마지막 키: {keyInfo.lastKey}</p>
      <p>눌린 특수키: {keyInfo.specialKeys.join(', ') || '없음'}</p>
      <p>키 히스토리: {keyInfo.keyHistory.join(' → ')}</p>
      <p>Ctrl+S를 눌러보세요!</p>
    </div>
  );
}
이벤트 전파 제어
이벤트 버블링 예제
import { useState } from 'react';
 
function BubblingExample() {
  const [log, setLog] = useState([]);
 
  const addLog = (message) => {
    setLog(prev => [...prev, `${new Date().toLocaleTimeString()}: ${message}`]);
  };
 
  const handleParentClick = () => {
    addLog('부모 요소 클릭됨');
  };
 
  const handleChildClick = () => {
    addLog('자식 요소 클릭됨');
  };
 
  const handleStopPropagation = (event) => {
    event.stopPropagation();
    addLog('전파 중단된 자식 클릭됨');
  };
 
  const clearLog = () => {
    setLog([]);
  };
 
  return (
    <div>
      <h3>이벤트 전파 예제</h3>
      
      <div onClick={handleParentClick}>
        부모 요소 (클릭 가능)
        
        <div onClick={handleChildClick}>
          일반 자식 요소
        </div>
 
        <div onClick={handleStopPropagation}>
          전파 중단 자식 요소
        </div>
      </div>
 
      <button onClick={clearLog}>로그 지우기</button>
      
      <div>
        <h4>이벤트 로그:</h4>
        <ul>
          {log.map((entry, index) => (
            <li key={index}>{entry}</li>
          ))}
        </ul>
      </div>
    </div>
  );
}
import { useState } from 'react';
 
function BubblingExample() {
  const [log, setLog] = useState([]);
 
  const addLog = (message) => {
    setLog(prev => [...prev, `${new Date().toLocaleTimeString()}: ${message}`]);
  };
 
  const handleParentClick = () => {
    addLog('부모 요소 클릭됨');
  };
 
  const handleChildClick = () => {
    addLog('자식 요소 클릭됨');
  };
 
  const handleStopPropagation = (event) => {
    event.stopPropagation();
    addLog('전파 중단된 자식 클릭됨');
  };
 
  const clearLog = () => {
    setLog([]);
  };
 
  return (
    <div>
      <h3>이벤트 전파 예제</h3>
      
      <div onClick={handleParentClick}>
        부모 요소 (클릭 가능)
        
        <div onClick={handleChildClick}>
          일반 자식 요소
        </div>
 
        <div onClick={handleStopPropagation}>
          전파 중단 자식 요소
        </div>
      </div>
 
      <button onClick={clearLog}>로그 지우기</button>
      
      <div>
        <h4>이벤트 로그:</h4>
        <ul>
          {log.map((entry, index) => (
            <li key={index}>{entry}</li>
          ))}
        </ul>
      </div>
    </div>
  );
}
실습: 간단한 계산기
import { useState } from 'react';
 
function Calculator() {
  const [display, setDisplay] = useState('0');
  const [previousValue, setPreviousValue] = useState(null);
  const [operation, setOperation] = useState(null);
  const [waitingForOperand, setWaitingForOperand] = useState(false);
 
  const inputNumber = (num) => {
    if (waitingForOperand) {
      setDisplay(String(num));
      setWaitingForOperand(false);
    } else {
      setDisplay(display === '0' ? String(num) : display + num);
    }
  };
 
  const inputOperation = (nextOperation) => {
    const inputValue = parseFloat(display);
 
    if (previousValue === null) {
      setPreviousValue(inputValue);
    } else if (operation) {
      const currentValue = previousValue || 0;
      const result = calculate(currentValue, inputValue, operation);
 
      setDisplay(String(result));
      setPreviousValue(result);
    }
 
    setWaitingForOperand(true);
    setOperation(nextOperation);
  };
 
  const calculate = (firstValue, secondValue, operation) => {
    switch (operation) {
      case '+':
        return firstValue + secondValue;
      case '-':
        return firstValue - secondValue;
      case '*':
        return firstValue * secondValue;
      case '/':
        return firstValue / secondValue;
      case '=':
        return secondValue;
      default:
        return secondValue;
    }
  };
 
  const performCalculation = () => {
    const inputValue = parseFloat(display);
 
    if (previousValue !== null && operation) {
      const result = calculate(previousValue, inputValue, operation);
      setDisplay(String(result));
      setPreviousValue(null);
      setOperation(null);
      setWaitingForOperand(true);
    }
  };
 
  const clear = () => {
    setDisplay('0');
    setPreviousValue(null);
    setOperation(null);
    setWaitingForOperand(false);
  };
 
  return (
    <div>
      <h3>계산기</h3>
      
      <div>
        {display}
      </div>
 
      <table>
        <tbody>
          <tr>
            <td><button onClick={clear}>C</button></td>
            <td><button onClick={() => inputOperation('/')}>/</button></td>
            <td><button onClick={() => inputOperation('*')}>*</button></td>
            <td><button onClick={() => inputOperation('-')}>-</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(7)}>7</button></td>
            <td><button onClick={() => inputNumber(8)}>8</button></td>
            <td><button onClick={() => inputNumber(9)}>9</button></td>
            <td rowSpan="2"><button onClick={() => inputOperation('+')}>+</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(4)}>4</button></td>
            <td><button onClick={() => inputNumber(5)}>5</button></td>
            <td><button onClick={() => inputNumber(6)}>6</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(1)}>1</button></td>
            <td><button onClick={() => inputNumber(2)}>2</button></td>
            <td><button onClick={() => inputNumber(3)}>3</button></td>
            <td rowSpan="2"><button onClick={performCalculation}>=</button></td>
          </tr>
          <tr>
            <td colSpan="2"><button onClick={() => inputNumber(0)}>0</button></td>
            <td><button>.</button></td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}
import { useState } from 'react';
 
function Calculator() {
  const [display, setDisplay] = useState('0');
  const [previousValue, setPreviousValue] = useState(null);
  const [operation, setOperation] = useState(null);
  const [waitingForOperand, setWaitingForOperand] = useState(false);
 
  const inputNumber = (num) => {
    if (waitingForOperand) {
      setDisplay(String(num));
      setWaitingForOperand(false);
    } else {
      setDisplay(display === '0' ? String(num) : display + num);
    }
  };
 
  const inputOperation = (nextOperation) => {
    const inputValue = parseFloat(display);
 
    if (previousValue === null) {
      setPreviousValue(inputValue);
    } else if (operation) {
      const currentValue = previousValue || 0;
      const result = calculate(currentValue, inputValue, operation);
 
      setDisplay(String(result));
      setPreviousValue(result);
    }
 
    setWaitingForOperand(true);
    setOperation(nextOperation);
  };
 
  const calculate = (firstValue, secondValue, operation) => {
    switch (operation) {
      case '+':
        return firstValue + secondValue;
      case '-':
        return firstValue - secondValue;
      case '*':
        return firstValue * secondValue;
      case '/':
        return firstValue / secondValue;
      case '=':
        return secondValue;
      default:
        return secondValue;
    }
  };
 
  const performCalculation = () => {
    const inputValue = parseFloat(display);
 
    if (previousValue !== null && operation) {
      const result = calculate(previousValue, inputValue, operation);
      setDisplay(String(result));
      setPreviousValue(null);
      setOperation(null);
      setWaitingForOperand(true);
    }
  };
 
  const clear = () => {
    setDisplay('0');
    setPreviousValue(null);
    setOperation(null);
    setWaitingForOperand(false);
  };
 
  return (
    <div>
      <h3>계산기</h3>
      
      <div>
        {display}
      </div>
 
      <table>
        <tbody>
          <tr>
            <td><button onClick={clear}>C</button></td>
            <td><button onClick={() => inputOperation('/')}>/</button></td>
            <td><button onClick={() => inputOperation('*')}>*</button></td>
            <td><button onClick={() => inputOperation('-')}>-</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(7)}>7</button></td>
            <td><button onClick={() => inputNumber(8)}>8</button></td>
            <td><button onClick={() => inputNumber(9)}>9</button></td>
            <td rowSpan="2"><button onClick={() => inputOperation('+')}>+</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(4)}>4</button></td>
            <td><button onClick={() => inputNumber(5)}>5</button></td>
            <td><button onClick={() => inputNumber(6)}>6</button></td>
          </tr>
          <tr>
            <td><button onClick={() => inputNumber(1)}>1</button></td>
            <td><button onClick={() => inputNumber(2)}>2</button></td>
            <td><button onClick={() => inputNumber(3)}>3</button></td>
            <td rowSpan="2"><button onClick={performCalculation}>=</button></td>
          </tr>
          <tr>
            <td colSpan="2"><button onClick={() => inputNumber(0)}>0</button></td>
            <td><button>.</button></td>
          </tr>
        </tbody>
      </table>
    </div>
  );
}
정리

이벤트 처리의 심화 내용을 학습했습니다:

  1. 다양한 이벤트 타입: 클릭, 입력, 키보드, 마우스 이벤트
  2. 폼 이벤트: 체크박스, 라디오 버튼, 셀렉트 박스 처리
  3. 이벤트 객체: 이벤트 정보 활용과 특수키 감지
  4. 이벤트 전파: stopPropagation()을 활용한 버블링 제어
  5. 실습 예제: 계산기를 통한 복합적인 이벤트 처리

React에서 이벤트를 다룰 때 가장 중요한 것은 상태 업데이트와 이벤트 핸들러를 적절히 연결하는 것입니다. preventDefault()와 stopPropagation() 같은 메서드를 적절히 활용하면 더욱 정교한 사용자 인터랙션을 구현할 수 있습니다.

다음 장에서는 컴포넌트 생명주기와 useEffect에 대해 알아보겠습니다.

3.2 useState Hook3.4 컴포넌트 생명주기와 useEffect