[리액트를 다루는 기술] 4장 이벤트 핸들링

정통파 개발자·2024년 12월 26일

웹브라우저에서 이벤트 요소는 유저와의 상호작용에서 뺄래야 뺼 수 없는 중요한 요소이다. 정말 정말 자주 사용하는 마우스, 키보드 이벤트 외에도 다양한 이벤트가 있고 적재 적소에 활용한다면 좋은 UI/UX 를 만들 수 있을것이다. 😎

이벤트란? 유저가 웹 브라우저에서 DOM 요소와 상호작용 하는 모든것을 말한다.

리액트의 이벤트

1. React.SyntheticEvent

자바스크립트 네이티브 이벤트(Event) 객체를 감싸는 리액트 객체이다. 네이티브 이벤트 인터페이스가 같으므로 순수 자바스크립트에서 HTML 이벤트를 다룰 때와 똑같이 사용한다.

2. 사용 시 주의사항

  • HTML 이벤트 속성명과 달리 카멜케이스를 사용한다 (onclick -> onClick)
  • 이벤트 속성 내 값은 함수 형태의 값을 넣는다.
  • DOM 요소에만 이벤트를 설정 할 수 있다.

3. 예제 코드

클래스형 컴포넌트

// 1번 생성자에 의해
class ClickButton extends Component {
  constructor() {
    this.handleClick = this.handleClick.bind(this);
  }
  
  function handleClick()  {
    console.log('Button clicked!');
    alert('Button clicked!');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me!</button>
      </div>
    );
  }
}

export default ClickButton;
// 화살표 함수를 이용
class ClickButton extends Component {
   handleClick = () => {
    console.log('Button clicked!');
    alert('Button clicked!');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me!</button>
      </div>
    );
  }
}

export default ClickButton;
  • 1번 생성자를 이용한 함수 생성에 bind 해줘야 하는 이유
    일반 함수(function() {...})에서 this는 함수를 호출하는 방법에 따라 결정되는 객체를 참조한다. 즉, this는 현재 실행 중(런타임)인 코드의 실행 컨텍스트에 따라 값이 결정된다.
  • 2번 화살표 함수(() => {...})는 작성된 위치의 스코프(렉시컬 스코프)에서 this를 상속받아 사용한다.
  • 렉시컬 스코프(Lexical Scope)란? 코드를 작성한 위치(문법적 구조)에 따라 변수의 유효 범위를 결정하는 방식이다.
    대부분의 현대 프로그래밍 언어는 렉시컬 스코핑을 사용한다.
    즉, 어디서 호출되었는지가 아니라, 어디서 정의되었는지에 따라 스코프가 결정된다.
  • 다이나믹 스코프(Dynamic Scope)란? 다이나믹 스코프는 함수가 호출된 시점의 실행 컨텍스트를 기반으로 스코프를 결정하는 방식이다. 즉 런타임에 따라 변수 참조가 달라질 수 있다.

함수형 컴포넌트

const ClickButton = () => {
  // 함수형 형태
  const handleClick = () => {
    console.log('Button clicked!');
    alert('Button clicked!');
  };

  return (
    <div>
      <button onClick={handleClick}>Click Me!</button>
    </div>
  );
};

3. 종류

Clipboard Events

  1. 기본적으로 텍스트나 콘텐츠를 복사, 잘라내기, 붙여넣기 작업과 관련된 이벤트
  2. 주로 사용되는 요소는 <input>, <textarea>
  3. 이벤트 종류
  • onCopy 사용자가 복사(Copy) 동작을 수행할 때 발생하는 이벤트
  • onCut 사용자가 잘라내기(Cut) 동작을 수행할 때 발생하는 이벤트
  • onPaste 사용자가 붙여넣기(Paste) 동작을 수행할 때 발생하는 이벤트

Composition Events

  1. IME(입력기)를 사용하는 언어(예: 한글, 일본어, 중국어 등)에서 입력 조합 상태를 추적할 수 있도록 설계된 이벤트
  2. 주로 사용되는 요소는 <input>, <textarea>
  3. 이벤트 종류
  • onCompositionStart 입력 조합이 시작될 때 발생 (예: ㅎ)
  • onCompositionUpdate 입력 조합이 진행 중일 때 발생 (예: 하)
  • onCompositionEnd 입력 조합이 완료될 때 발생 (예: 한)

Keyboard Events

  1. 사용자가 키보드로 입력을 수행할 때 발생하는 이벤트
  2. 주로 사용되는 요소는 <input>, <textarea>
  3. 이벤트 종류
  • onKeyDown 키가 눌릴 때 발생하는 이벤트
  • onKeyPress 키 입력 시 발생하는 이벤트 (Deprecated, onKeyDown 사용 권장)
  • onKeyUp 키를 뗄 때 발생하는 이벤트
  1. 예제
//  키 조합 동작 구현 (Ctrl + S)
function App() {
  const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
    if (event.ctrlKey && event.key === 's') {
      event.preventDefault(); // 기본 동작 방지
      alert('Ctrl + S 키가 눌렸습니다!');
    }
  };

  return (
    <div
      tabIndex={0}
      onKeyDown={handleKeyDown}>
      Ctrl+S를 눌러보세요
    </div>
  );
}

Focus Events

  1. 사용자가 요소에 포커스를 맞추거나 벗어날 때 발생하는 이벤트
  2. 주로 사용되는 요소는 <input>, <textarea>, <select>, <button>
  3. 이벤트 종류
  • onFocus 요소에서 포커스가 맞춰질 때 발생하는 이벤트
  • onBlur 요소에서 포커스가 벗어날 때 발생하는 이벤트

Form Events

  1. 폼 요소에서 발생하는 다양한 상호작용 이벤트, 주로 입력 처리, 폼 제출, 유효성 검사 등의 작업
  2. 주로 사용되는 요소는 <form>, <input>, <textarea>, <select>
  3. 이벤트 종류
  • onChange 폼 요소가 입력 또는 선택에 의해 값이 변경될때 발생하는 이벤트
  • onInput 사용자가 입력하는 즉시 발생
  • onInvalid HTML5 폼 검증에서 유효성 검사 실패 시 발생
  • onReset 폼이 리셋될 때 발생
  • onSubmit 폼이 제출될 때 발생

    onInvalid는 HTML5 유효성 검사 속성과 함께 작동한다.
    required: 필수 입력
    min, max: 숫자 범위 제한.
    minLength, maxLength: 문자열 길이 제한.
    pattern: 정규식을 사용한 입력 형식 제한.

Image Events

  1. 이미지를 포함한 리소스가 로드되거나 로드 중 에러가 발생했을 때 트리거되는 이벤트
  2. 주로 사용되는 요소는 <img>, <script>, <link>
  3. 이벤트 종류
  • onError 이미지나 스크립트, 비디오 등에서 리소스를 찾지 못하거나 로드하지 못할 경우 발생하는 이벤트
  • onLoad 이미지, 스크립트, 스타일 등에서 리소스가 완전히 로드된 경우 발생하는 이벤트

Mouse Events

  1. 사용자가 마우스와 상호작용할 때 발생하는 이벤트이다. 클릭, 드래그, 이동 등 다양한 동작을 처리
  2. 주로 사용되는 요소는 <button>, <div>, <span>, <a>
  3. 이벤트 종류
  • onClick 마우스 버튼을 클릭할 때 발생
  • onContextMenu 마우스 우클릭(컨텍스트 메뉴 열기) 시 발생
  • onDoubleClick 마우스를 두 번 클릭할 때 발생
  • onDrag 드래그가 시작될 때부터 진행 중일 때까지 발생
  • onDragStart 드래그가 시작될 때 발생
  • onDragEnd 드래그가 끝났을 때 발생
  • onDragEnter 드래그 중 요소에 들어왔을 때 발생
  • onDragLeave 드래그 중 요소에서 벗어났을 때 발생
  • onDragOver 드래그 중인 요소가 다른 요소 위에 있을 때 발생
  • onDrop 드래그 중인 요소가 다른 요소 위에 드롭될 때 발생
  • onMouseDown 마우스 버튼을 누를 때 발생
  • onMouseEnter 마우스가 요소에 들어올 때 발생
  • onMouseLeave 마우스가 요소에 벗어날 때 발생
  • onMouseMove 마우스가 요소 안에서 이동할 때마다 발생
  • onMouseOut 마우스가 요소 바깥으로 이동할 때 발생
  • onMouseOver 마우스가 요소 위로 올라갈 때 발생. (하위 요소 포함, onMouseEnter와 다르게, 자식 요소에 진입해도 이벤트 발생)
  • onMouseUp 마우스 버튼을 눌렀다가 뗄 때 발생

Touch Events

  • onTouchCancel 터치 이벤트가 시스템에 의해 취소될 때 발생 (예, 전화수신, 다른 앱 활성화)
  • onTouchEnd 사용자가 화면에서 손가락을 뗄 때 발생
  • onTouchMove 사용자가 터치한 손가락을 움직일 때 발생
    -onTouchStart 사용자가 화면을 터치하기 시작할 때 발생

Pointer Events

  1. 마우스, 터치 스크린, 스타일러스 펜 등 다양한 입력 장치를 일관되게 처리할 수 있도록 설계된 이벤트, 기존 Mouse EventsTouch Events를 통합한 이벤트 시스템으로, 모든 입력 장치를 포괄적으로 다룰 수 있음
  2. 모든 DOM 요소에서 사용 가능
  3. 이벤트 종류
  • onPointerDown 포인터(마우스, 터치 등)가 요소를 누를 때 발생
  • onPointerMove 포인터가 요소 위에서 이동할 때 발생
  • onPointerUp 포인터가 눌린 상태에서 뗄 때 발생
  • onPointerCancel 포인터 동작이 시스템에 의해 취소될 때 발생 (예: 터치 이벤트 중 다른 앱 실행)
  • onGotPointerCapture 요소가 포인터 캡처(즉, 모든 포인터 이벤트를 해당 요소로 전달)를 획득할 때 발생
  • onLostPointerCapture 요소가 포인터 캡처를 잃을 때 발생
  • onPointerEnter 포인터가 요소에 들어올 때 발생 (버블링되지 않음
  • onPointerLeave 포인터가 요소를 벗어날 때 발생 (버블링되지 않음)
  • onPointerOver 포인터가 요소 위로 올라갈 때 발생 (하위 요소 포함)
  • onPointerOut 포인터가 요소 바깥으로 이동할 때 발생 (하위 요소 포함)
  1. 터치 장치 또는 스타일러스 펜을 다루는 UI에 유용, 다양한 입력 장치를 지원하는 애플리케이션에 유용

Selection Events

  1. 사용자가 텍스트를 드래그를 통해, 또는 더블클릭으로 선택했을 때 발생하는 이벤트
  2. 주로 사용되는 요소는 <input>, <textarea>
  3. 이벤트 종류
  • onSelect 사용자가 텍스트를 선택했을 때 발생하는 이벤트 (마우스로 드래그하거나 키보드로 텍스트를 선택할 때 발생함)

UI Events

  • onScroll 사용자가 스크롤 동작을 수행할 때 발생하는 이벤트

Wheel Events

  • onWheel 이벤트는 사용자가 마우스 휠을 스크롤하거나 터치패드로 스크롤 동작을 수행할 때 발생.

Animation Events

  • onAnimationStart CSS 애니메이션이 시작될 때 발생
  • onAnimationEnd CSS 애니메이션이 종료될 때 발생
  • onAnimationIteration CSS 애니메이션이 한 번 반복될 때마다 발생

Transition Events

  • onTransitionEnd CSS 트랜지션이 끝났을 때 발생

Other Events

  • onToggle onToggle 이벤트는 HTML5 details 요소가 열리거나 닫힐 때 발생

자세한 사항은 아래 링크를 통해 확인가능하다.
SyntheticEvent 공식문서 링크


이벤트 흐름

1. 이벤트 버블링(Event Bubbling)

  • 개념: 이벤트가 발생한 요소에서 부모 요소로 전파되는 과정이다.
  • 특징: 기본동작이며, 대부분 이벤트 onClick, onChange 등에서 적용된다.
function App() {
  const handleDivClick = () => {
    console.log('부모 <div> 클릭');
  };

  const handleButtonClick = () => {
    console.log('자식 <button> 클릭');
  };

  return (
    <div onClick={handleDivClick}>
      <button onClick={handleButtonClick}>클릭</button>
    </div>
  );
}

Console 결과

자식 <button> 클릭
부모 <div> 클릭

2. 이벤트 캡쳐링(Event Capturing)

  • 개념: 이벤트가 발생한 요소까지 부모 요소에서 자식 요소로 내려오며 전파되는 과정이다.
  • 특징: 기본적으로 React의 SyntheticEvent는 버블링 이벤트를 처리한다. 캡처 단계에서 처리하려면 onClickCapture와 같은 Capture 이벤트를 사용해야 함
function App() {
  const handleDivClick = () => {
    console.log('부모 <div> 클릭 (캡처)');
  };

  const handleButtonClick = () => {
    console.log('자식 <button> 클릭');
  };

  return (
    <div onClickCapture={handleDivClick}>
      <button onClick={handleButtonClick}>클릭</button>
    </div>
  );
}

Console 결과

부모 <div> 클릭 (캡처)
자식 <button> 클릭

3. 이벤트 중단

  1. stopPropagation 이벤트가 부모로 전파되지 않도록 중단
function App() {
  const handleDivClick = () => {
    console.log('부모 <div> 클릭');
  };

  const handleButtonClick = (event: React.MouseEvent) => {
    event.stopPropagation(); // 부모로 전파 중단
    console.log('자식 <button> 클릭');
  };

  return (
    <div onClick={handleDivClick}>
      <button onClick={handleButtonClick}>클릭</button>
    </div>
  );
}

Console 결과

자식 <button> 클릭
  1. preventDefault 커스텀 동작을 정의하거나 기본 동작을 비활성화 하기위한 기본 동작(예: 링크 이동, 폼 제출)을 막기 위해 사용
function App() {
  const handleLinkClick = (event: React.MouseEvent) => {
    event.preventDefault(); // 링크 이동 막기
    console.log('커스텀 동작 실행');
  };

  return <a href="https://example.com" onClick={handleLinkClick}>링크</a>;
}
profile
🙋🏻‍♀️

0개의 댓글