Common components (e.g. <div>)

김동현·2026년 3월 17일

공통 컴포넌트 (예: <div>)

소개

<div> 같은 모든 브라우저 내장 컴포넌트들은 몇 가지 공통 props와 이벤트를 지원해요.


레퍼런스

공통 컴포넌트 (예: <div>)

<div className="wrapper">Some content</div>

아래에서 더 많은 예제를 확인하세요.

Props

아래의 특별한 React props들은 모든 내장 컴포넌트에서 지원돼요:

  • children: React 노드예요 (엘리먼트, 문자열, 숫자, 포탈, null이나 undefined, 불리언 같은 빈 노드, 또는 다른 React 노드들의 배열). 컴포넌트 안에 들어갈 내용을 지정해요. JSX를 사용할 때는 보통 <div><span /></div>처럼 태그를 중첩해서 children prop을 암묵적으로 지정하게 돼요.

  • dangerouslySetInnerHTML: { __html: '<p>some html</p>' } 형태의 객체로, 안에 원시(raw) HTML 문자열이 들어가요. DOM 노드의 innerHTML 프로퍼티를 덮어쓰고 전달된 HTML을 내부에 표시해요. 이건 극도로 주의해서 사용해야 해요! 안에 있는 HTML이 신뢰할 수 없는 경우 (예를 들어 사용자 데이터에 기반한 경우), XSS 취약점을 만들 위험이 있어요. dangerouslySetInnerHTML 사용에 대해 더 읽어보세요.

  • ref: useRefcreateRef에서 반환된 ref 객체, 또는 ref 콜백 함수, 또는 레거시 ref를 위한 문자열이에요. 여러분의 ref는 이 노드에 대한 DOM 엘리먼트로 채워질 거예요. ref로 DOM 조작하기에 대해 더 읽어보세요.

  • suppressContentEditableWarning: 불리언이에요. true이면, childrencontentEditable={true}를 동시에 가진 엘리먼트에 대해 React가 보여주는 경고를 억제해요 (원래 이 둘은 함께 작동하지 않거든요). contentEditable 콘텐츠를 수동으로 관리하는 텍스트 입력 라이브러리를 만들 때 사용하세요.

  • suppressHydrationWarning: 불리언이에요. 서버 렌더링을 사용할 때, 보통 서버와 클라이언트가 다른 내용을 렌더링하면 경고가 뜨는데요. 타임스탬프 같은 아주 드문 경우에는 정확한 일치를 보장하는 게 매우 어렵거나 불가능해요. suppressHydrationWarningtrue로 설정하면, React가 해당 엘리먼트의 속성과 내용의 불일치에 대해 경고하지 않아요. 한 단계 깊이에서만 작동하고, 탈출구(escape hatch)로 사용하도록 의도된 거예요. 남용하지 마세요. 하이드레이션 에러 억제에 대해 읽어보세요.

  • style: CSS 스타일이 담긴 객체예요. 예를 들어 { fontWeight: 'bold', margin: 20 } 이런 식이에요. DOM의 style 프로퍼티와 마찬가지로, CSS 프로퍼티 이름은 camelCase로 작성해야 해요. 예를 들어 font-weight 대신 fontWeight로요. 값으로 문자열이나 숫자를 전달할 수 있어요. width: 100처럼 숫자를 전달하면, React가 자동으로 값 뒤에 px("픽셀")을 붙여줘요. 단, 단위가 없는 프로퍼티는 제외예요. style은 스타일 값을 미리 알 수 없는 동적 스타일에만 사용하는 걸 권장해요. 그 외의 경우에는 className으로 일반 CSS 클래스를 적용하는 게 더 효율적이에요. classNamestyle에 대해 더 읽어보세요.

아래의 표준 DOM props도 모든 내장 컴포넌트에서 지원돼요:

  • accessKey: 문자열이에요. 엘리먼트에 대한 키보드 단축키를 지정해요. 일반적으로 권장되지 않아요.
  • aria-*: ARIA 속성을 사용하면 이 엘리먼트에 대한 접근성 트리 정보를 지정할 수 있어요. 전체 레퍼런스는 ARIA 속성을 참고하세요. React에서 모든 ARIA 속성 이름은 HTML에서와 정확히 같아요.
  • autoCapitalize: 문자열이에요. 사용자 입력의 대문자 변환 여부와 방식을 지정해요.
  • className: 문자열이에요. 엘리먼트의 CSS 클래스 이름을 지정해요. CSS 스타일 적용에 대해 더 읽어보세요.
  • contentEditable: 불리언이에요. true이면, 브라우저가 사용자에게 렌더링된 엘리먼트를 직접 편집할 수 있게 해줘요. 이건 Lexical 같은 리치 텍스트 입력 라이브러리를 구현할 때 사용돼요. contentEditable={true}인 엘리먼트에 React children을 전달하려고 하면 경고가 뜨는데, 사용자가 편집한 후에 React가 그 내용을 업데이트할 수 없기 때문이에요.
  • data-*: 데이터 속성을 사용하면 엘리먼트에 문자열 데이터를 붙일 수 있어요. 예를 들어 data-fruit="banana" 이런 식이에요. React에서는 보통 props나 state에서 데이터를 읽기 때문에 잘 사용되지 않아요.
  • dir: 'ltr' 또는 'rtl'이에요. 엘리먼트의 텍스트 방향을 지정해요.
  • draggable: 불리언이에요. 엘리먼트가 드래그 가능한지 지정해요. HTML 드래그 앤 드롭 API의 일부예요.
  • enterKeyHint: 문자열이에요. 가상 키보드에서 엔터 키에 어떤 동작을 표시할지 지정해요.
  • htmlFor: 문자열이에요. <label><output>에서 레이블을 특정 컨트롤과 연결할 수 있게 해줘요. for HTML 속성과 같아요. React는 HTML 속성 이름 대신 표준 DOM 프로퍼티 이름(htmlFor)을 사용해요.
  • hidden: 불리언 또는 문자열이에요. 엘리먼트를 숨길지 여부를 지정해요.
  • id: 문자열이에요. 이 엘리먼트의 고유 식별자를 지정하는데, 나중에 찾거나 다른 엘리먼트와 연결할 때 사용할 수 있어요. 같은 컴포넌트의 여러 인스턴스 간 충돌을 피하려면 useId로 생성하세요.
  • is: 문자열이에요. 지정하면, 컴포넌트가 커스텀 엘리먼트처럼 동작해요.
  • inputMode: 문자열이에요. 어떤 종류의 키보드를 표시할지 지정해요 (예를 들어 텍스트, 숫자, 전화번호).
  • itemProp: 문자열이에요. 구조화된 데이터 크롤러를 위해 엘리먼트가 어떤 프로퍼티를 나타내는지 지정해요.
  • lang: 문자열이에요. 엘리먼트의 언어를 지정해요.
  • onAnimationEnd: AnimationEvent 핸들러 함수예요. CSS 애니메이션이 완료되면 발생해요.
  • onAnimationEndCapture: 캡처 단계에서 발생하는 onAnimationEnd 버전이에요.
  • onAnimationIteration: AnimationEvent 핸들러 함수예요. CSS 애니메이션의 한 반복이 끝나고 다음 반복이 시작될 때 발생해요.
  • onAnimationIterationCapture: 캡처 단계에서 발생하는 onAnimationIteration 버전이에요.
  • onAnimationStart: AnimationEvent 핸들러 함수예요. CSS 애니메이션이 시작될 때 발생해요.
  • onAnimationStartCapture: 캡처 단계에서 발생하는 onAnimationStart 버전이에요.
  • onAuxClick: MouseEvent 핸들러 함수예요. 기본이 아닌 포인터 버튼이 클릭되었을 때 발생해요.
  • onAuxClickCapture: 캡처 단계에서 발생하는 onAuxClick 버전이에요.
  • onBeforeInput: InputEvent 핸들러 함수예요. 편집 가능한 엘리먼트의 값이 수정되기 전에 발생해요. React는 아직 네이티브 beforeinput 이벤트를 사용하지 않고, 대신 다른 이벤트들을 사용해서 폴리필하려고 시도해요.
  • onBeforeInputCapture: 캡처 단계에서 발생하는 onBeforeInput 버전이에요.
  • onBlur: FocusEvent 핸들러 함수예요. 엘리먼트가 포커스를 잃었을 때 발생해요. 브라우저 내장 blur 이벤트와 달리, React에서 onBlur 이벤트는 버블링돼요.
  • onBlurCapture: 캡처 단계에서 발생하는 onBlur 버전이에요.
  • onClick: MouseEvent 핸들러 함수예요. 포인팅 장치에서 기본 버튼이 클릭되었을 때 발생해요.
  • onClickCapture: 캡처 단계에서 발생하는 onClick 버전이에요.
  • onCompositionStart: CompositionEvent 핸들러 함수예요. 입력기(IME)가 새로운 구성(composition) 세션을 시작할 때 발생해요.

💡 부연 설명: IME(Input Method Editor)는 한국어, 중국어, 일본어 같은 언어에서 문자를 조합해서 입력하는 시스템이에요. 예를 들어 한국어로 "한"을 입력할 때 ㅎ → 하 → 한 순서로 조합이 이루어지는데, 이때 composition 이벤트가 발생해요.

  • onCompositionStartCapture: 캡처 단계에서 발생하는 onCompositionStart 버전이에요.
  • onCompositionEnd: CompositionEvent 핸들러 함수예요. 입력기(IME)가 구성 세션을 완료하거나 취소할 때 발생해요.
  • onCompositionEndCapture: 캡처 단계에서 발생하는 onCompositionEnd 버전이에요.
  • onCompositionUpdate: CompositionEvent 핸들러 함수예요. 입력기(IME)가 새 문자를 받았을 때 발생해요.
  • onCompositionUpdateCapture: 캡처 단계에서 발생하는 onCompositionUpdate 버전이에요.
  • onContextMenu: MouseEvent 핸들러 함수예요. 사용자가 컨텍스트 메뉴(우클릭 메뉴)를 열려고 할 때 발생해요.
  • onContextMenuCapture: 캡처 단계에서 발생하는 onContextMenu 버전이에요.
  • onCopy: ClipboardEvent 핸들러 함수예요. 사용자가 클립보드에 무언가를 복사하려고 할 때 발생해요.
  • onCopyCapture: 캡처 단계에서 발생하는 onCopy 버전이에요.
  • onCut: ClipboardEvent 핸들러 함수예요. 사용자가 클립보드에 무언가를 잘라내려고 할 때 발생해요.
  • onCutCapture: 캡처 단계에서 발생하는 onCut 버전이에요.
  • onDoubleClick: MouseEvent 핸들러 함수예요. 사용자가 두 번 클릭했을 때 발생해요. 브라우저의 dblclick 이벤트에 해당해요.
  • onDoubleClickCapture: 캡처 단계에서 발생하는 onDoubleClick 버전이에요.
  • onDrag: DragEvent 핸들러 함수예요. 사용자가 무언가를 드래그하는 동안 발생해요.
  • onDragCapture: 캡처 단계에서 발생하는 onDrag 버전이에요.
  • onDragEnd: DragEvent 핸들러 함수예요. 사용자가 드래그를 멈췄을 때 발생해요.
  • onDragEndCapture: 캡처 단계에서 발생하는 onDragEnd 버전이에요.
  • onDragEnter: DragEvent 핸들러 함수예요. 드래그된 콘텐츠가 유효한 드롭 대상에 들어갔을 때 발생해요.
  • onDragEnterCapture: 캡처 단계에서 발생하는 onDragEnter 버전이에요.
  • onDragOver: DragEvent 핸들러 함수예요. 드래그된 콘텐츠가 유효한 드롭 대상 위를 지나갈 때 발생해요. 드롭을 허용하려면 여기서 e.preventDefault()를 호출해야 해요.
  • onDragOverCapture: 캡처 단계에서 발생하는 onDragOver 버전이에요.
  • onDragStart: DragEvent 핸들러 함수예요. 사용자가 엘리먼트를 드래그하기 시작할 때 발생해요.
  • onDragStartCapture: 캡처 단계에서 발생하는 onDragStart 버전이에요.
  • onDrop: DragEvent 핸들러 함수예요. 무언가가 유효한 드롭 대상에 드롭되었을 때 발생해요.
  • onDropCapture: 캡처 단계에서 발생하는 onDrop 버전이에요.
  • onFocus: FocusEvent 핸들러 함수예요. 엘리먼트가 포커스를 받았을 때 발생해요. 브라우저 내장 focus 이벤트와 달리, React에서 onFocus 이벤트는 버블링돼요.
  • onFocusCapture: 캡처 단계에서 발생하는 onFocus 버전이에요.
  • onGotPointerCapture: PointerEvent 핸들러 함수예요. 엘리먼트가 프로그래밍 방식으로 포인터를 캡처했을 때 발생해요.
  • onGotPointerCaptureCapture: 캡처 단계에서 발생하는 onGotPointerCapture 버전이에요.
  • onKeyDown: KeyboardEvent 핸들러 함수예요. 키가 눌렸을 때 발생해요.
  • onKeyDownCapture: 캡처 단계에서 발생하는 onKeyDown 버전이에요.
  • onKeyPress: KeyboardEvent 핸들러 함수예요. 더 이상 사용되지 않아요(Deprecated). 대신 onKeyDown이나 onBeforeInput을 사용하세요.
  • onKeyPressCapture: 캡처 단계에서 발생하는 onKeyPress 버전이에요.
  • onKeyUp: KeyboardEvent 핸들러 함수예요. 키가 놓였을 때 발생해요.
  • onKeyUpCapture: 캡처 단계에서 발생하는 onKeyUp 버전이에요.
  • onLostPointerCapture: PointerEvent 핸들러 함수예요. 엘리먼트가 포인터 캡처를 중지했을 때 발생해요.
  • onLostPointerCaptureCapture: 캡처 단계에서 발생하는 onLostPointerCapture 버전이에요.
  • onMouseDown: MouseEvent 핸들러 함수예요. 포인터가 눌렸을 때 발생해요.
  • onMouseDownCapture: 캡처 단계에서 발생하는 onMouseDown 버전이에요.
  • onMouseEnter: MouseEvent 핸들러 함수예요. 포인터가 엘리먼트 안으로 들어갔을 때 발생해요. 캡처 단계가 없어요. 대신, onMouseLeaveonMouseEnter는 떠나는 엘리먼트에서 들어가는 엘리먼트로 전파돼요.
  • onMouseLeave: MouseEvent 핸들러 함수예요. 포인터가 엘리먼트 밖으로 나갔을 때 발생해요. 캡처 단계가 없어요. 대신, onMouseLeaveonMouseEnter는 떠나는 엘리먼트에서 들어가는 엘리먼트로 전파돼요.
  • onMouseMove: MouseEvent 핸들러 함수예요. 포인터의 좌표가 변경되었을 때 발생해요.
  • onMouseMoveCapture: 캡처 단계에서 발생하는 onMouseMove 버전이에요.
  • onMouseOut: MouseEvent 핸들러 함수예요. 포인터가 엘리먼트 밖으로 나가거나, 자식 엘리먼트로 들어갈 때 발생해요.
  • onMouseOutCapture: 캡처 단계에서 발생하는 onMouseOut 버전이에요.
  • onMouseUp: MouseEvent 핸들러 함수예요. 포인터가 놓였을 때 발생해요.
  • onMouseUpCapture: 캡처 단계에서 발생하는 onMouseUp 버전이에요.
  • onPointerCancel: PointerEvent 핸들러 함수예요. 브라우저가 포인터 인터랙션을 취소했을 때 발생해요.
  • onPointerCancelCapture: 캡처 단계에서 발생하는 onPointerCancel 버전이에요.
  • onPointerDown: PointerEvent 핸들러 함수예요. 포인터가 활성화되었을 때 발생해요.
  • onPointerDownCapture: 캡처 단계에서 발생하는 onPointerDown 버전이에요.
  • onPointerEnter: PointerEvent 핸들러 함수예요. 포인터가 엘리먼트 안으로 들어갔을 때 발생해요. 캡처 단계가 없어요. 대신, onPointerLeaveonPointerEnter는 떠나는 엘리먼트에서 들어가는 엘리먼트로 전파돼요.
  • onPointerLeave: PointerEvent 핸들러 함수예요. 포인터가 엘리먼트 밖으로 나갔을 때 발생해요. 캡처 단계가 없어요. 대신, onPointerLeaveonPointerEnter는 떠나는 엘리먼트에서 들어가는 엘리먼트로 전파돼요.
  • onPointerMove: PointerEvent 핸들러 함수예요. 포인터의 좌표가 변경되었을 때 발생해요.
  • onPointerMoveCapture: 캡처 단계에서 발생하는 onPointerMove 버전이에요.
  • onPointerOut: PointerEvent 핸들러 함수예요. 포인터가 엘리먼트 밖으로 나가거나, 포인터 인터랙션이 취소되거나, 기타 몇 가지 이유로 발생해요.
  • onPointerOutCapture: 캡처 단계에서 발생하는 onPointerOut 버전이에요.
  • onPointerUp: PointerEvent 핸들러 함수예요. 포인터가 더 이상 활성 상태가 아닐 때 발생해요.
  • onPointerUpCapture: 캡처 단계에서 발생하는 onPointerUp 버전이에요.
  • onPaste: ClipboardEvent 핸들러 함수예요. 사용자가 클립보드에서 무언가를 붙여넣으려고 할 때 발생해요.
  • onPasteCapture: 캡처 단계에서 발생하는 onPaste 버전이에요.
  • onScroll: Event 핸들러 함수예요. 엘리먼트가 스크롤되었을 때 발생해요. 이 이벤트는 버블링되지 않아요.
  • onScrollCapture: 캡처 단계에서 발생하는 onScroll 버전이에요.
  • onSelect: Event 핸들러 함수예요. input 같은 편집 가능한 엘리먼트 안에서 선택이 변경된 후에 발생해요. React는 onSelect 이벤트를 contentEditable={true} 엘리먼트에서도 작동하도록 확장했어요. 또한, 빈 선택과 편집(선택에 영향을 줄 수 있는)에서도 발생하도록 확장했어요.
  • onSelectCapture: 캡처 단계에서 발생하는 onSelect 버전이에요.
  • onTouchCancel: TouchEvent 핸들러 함수예요. 브라우저가 터치 인터랙션을 취소했을 때 발생해요.
  • onTouchCancelCapture: 캡처 단계에서 발생하는 onTouchCancel 버전이에요.
  • onTouchEnd: TouchEvent 핸들러 함수예요. 하나 이상의 터치 포인트가 제거되었을 때 발생해요.
  • onTouchEndCapture: 캡처 단계에서 발생하는 onTouchEnd 버전이에요.
  • onTouchMove: TouchEvent 핸들러 함수예요. 하나 이상의 터치 포인트가 이동했을 때 발생해요.
  • onTouchMoveCapture: 캡처 단계에서 발생하는 onTouchMove 버전이에요.
  • onTouchStart: TouchEvent 핸들러 함수예요. 하나 이상의 터치 포인트가 놓였을 때 발생해요.
  • onTouchStartCapture: 캡처 단계에서 발생하는 onTouchStart 버전이에요.
  • onTransitionEnd: TransitionEvent 핸들러 함수예요. CSS 트랜지션이 완료되었을 때 발생해요.
  • onTransitionEndCapture: 캡처 단계에서 발생하는 onTransitionEnd 버전이에요.
  • onWheel: WheelEvent 핸들러 함수예요. 사용자가 휠 버튼을 회전했을 때 발생해요.
  • onWheelCapture: 캡처 단계에서 발생하는 onWheel 버전이에요.
  • role: 문자열이에요. 보조 기술을 위해 엘리먼트의 역할을 명시적으로 지정해요.
  • slot: 문자열이에요. Shadow DOM을 사용할 때 슬롯 이름을 지정해요. React에서는 보통 JSX를 props로 전달하는 것으로 동등한 패턴을 구현해요. 예를 들어 <Layout left={<Sidebar />} right={<Content />} /> 이런 식이에요.
  • spellCheck: 불리언 또는 null이에요. 명시적으로 truefalse로 설정하면 맞춤법 검사를 활성화하거나 비활성화해요.
  • tabIndex: 숫자예요. 기본 Tab 버튼 동작을 재정의해요. -10 이외의 값 사용은 피하세요.
  • title: 문자열이에요. 엘리먼트에 대한 툴팁 텍스트를 지정해요.
  • translate: 'yes' 또는 'no'예요. 'no'를 전달하면 엘리먼트 내용이 번역 대상에서 제외돼요.

커스텀 속성도 props로 전달할 수 있어요. 예를 들어 mycustomprop="someValue" 이런 식이에요. 이건 서드파티 라이브러리와 통합할 때 유용할 수 있어요. 커스텀 속성 이름은 소문자여야 하고 on으로 시작하면 안 돼요. 값은 문자열로 변환될 거예요. null이나 undefined를 전달하면 커스텀 속성이 제거돼요.

아래 이벤트들은 <form> 엘리먼트에서만 발생해요:

아래 이벤트들은 <dialog> 엘리먼트에서만 발생해요. 브라우저 이벤트와 달리, React에서는 버블링돼요:

아래 이벤트들은 <details> 엘리먼트에서만 발생해요. 브라우저 이벤트와 달리, React에서는 버블링돼요:

아래 이벤트들은 <img>, <iframe>, <object>, <embed>, <link>, 그리고 SVG <image> 엘리먼트에서 발생해요. 브라우저 이벤트와 달리, React에서는 버블링돼요:

  • onLoad: Event 핸들러 함수예요. 리소스가 로드되었을 때 발생해요.
  • onLoadCapture: 캡처 단계에서 발생하는 onLoad 버전이에요.
  • onError: Event 핸들러 함수예요. 리소스를 로드할 수 없었을 때 발생해요.
  • onErrorCapture: 캡처 단계에서 발생하는 onError 버전이에요.

아래 이벤트들은 <audio><video> 같은 리소스에서 발생해요. 브라우저 이벤트와 달리, React에서는 버블링돼요:

  • onAbort: Event 핸들러 함수예요. 리소스가 완전히 로드되지 않았지만 에러 때문은 아닐 때 발생해요.
  • onAbortCapture: 캡처 단계에서 발생하는 onAbort 버전이에요.
  • onCanPlay: Event 핸들러 함수예요. 재생을 시작할 만큼 충분한 데이터가 있지만, 버퍼링 없이 끝까지 재생하기에는 충분하지 않을 때 발생해요.
  • onCanPlayCapture: 캡처 단계에서 발생하는 onCanPlay 버전이에요.
  • onCanPlayThrough: Event 핸들러 함수예요. 버퍼링 없이 끝까지 재생할 수 있을 만큼 충분한 데이터가 있을 가능성이 높을 때 발생해요.
  • onCanPlayThroughCapture: 캡처 단계에서 발생하는 onCanPlayThrough 버전이에요.
  • onDurationChange: Event 핸들러 함수예요. 미디어 지속 시간이 업데이트되었을 때 발생해요.
  • onDurationChangeCapture: 캡처 단계에서 발생하는 onDurationChange 버전이에요.
  • onEmptied: Event 핸들러 함수예요. 미디어가 비어있게 되었을 때 발생해요.
  • onEmptiedCapture: 캡처 단계에서 발생하는 onEmptied 버전이에요.
  • onEncrypted: Event 핸들러 함수예요. 브라우저가 암호화된 미디어를 만났을 때 발생해요.
  • onEncryptedCapture: 캡처 단계에서 발생하는 onEncrypted 버전이에요.
  • onEnded: Event 핸들러 함수예요. 재생할 것이 더 이상 없어서 재생이 멈췄을 때 발생해요.
  • onEndedCapture: 캡처 단계에서 발생하는 onEnded 버전이에요.
  • onError: Event 핸들러 함수예요. 리소스를 로드할 수 없었을 때 발생해요.
  • onErrorCapture: 캡처 단계에서 발생하는 onError 버전이에요.
  • onLoadedData: Event 핸들러 함수예요. 현재 재생 프레임이 로드되었을 때 발생해요.
  • onLoadedDataCapture: 캡처 단계에서 발생하는 onLoadedData 버전이에요.
  • onLoadedMetadata: Event 핸들러 함수예요. 메타데이터가 로드되었을 때 발생해요.
  • onLoadedMetadataCapture: 캡처 단계에서 발생하는 onLoadedMetadata 버전이에요.
  • onLoadStart: Event 핸들러 함수예요. 브라우저가 리소스 로딩을 시작했을 때 발생해요.
  • onLoadStartCapture: 캡처 단계에서 발생하는 onLoadStart 버전이에요.
  • onPause: Event 핸들러 함수예요. 미디어가 일시 정지되었을 때 발생해요.
  • onPauseCapture: 캡처 단계에서 발생하는 onPause 버전이에요.
  • onPlay: Event 핸들러 함수예요. 미디어가 더 이상 일시 정지 상태가 아닐 때 발생해요.
  • onPlayCapture: 캡처 단계에서 발생하는 onPlay 버전이에요.
  • onPlaying: Event 핸들러 함수예요. 미디어가 재생을 시작하거나 다시 시작했을 때 발생해요.
  • onPlayingCapture: 캡처 단계에서 발생하는 onPlaying 버전이에요.
  • onProgress: Event 핸들러 함수예요. 리소스가 로딩되는 동안 주기적으로 발생해요.
  • onProgressCapture: 캡처 단계에서 발생하는 onProgress 버전이에요.
  • onRateChange: Event 핸들러 함수예요. 재생 속도가 변경되었을 때 발생해요.
  • onRateChangeCapture: 캡처 단계에서 발생하는 onRateChange 버전이에요.
  • onResize: Event 핸들러 함수예요. 비디오 크기가 변경되었을 때 발생해요.
  • onResizeCapture: 캡처 단계에서 발생하는 onResize 버전이에요.
  • onSeeked: Event 핸들러 함수예요. 탐색(seek) 작업이 완료되었을 때 발생해요.
  • onSeekedCapture: 캡처 단계에서 발생하는 onSeeked 버전이에요.
  • onSeeking: Event 핸들러 함수예요. 탐색(seek) 작업이 시작되었을 때 발생해요.
  • onSeekingCapture: 캡처 단계에서 발생하는 onSeeking 버전이에요.
  • onStalled: Event 핸들러 함수예요. 브라우저가 데이터를 기다리고 있지만 계속 로딩되지 않을 때 발생해요.
  • onStalledCapture: 캡처 단계에서 발생하는 onStalled 버전이에요.
  • onSuspend: Event 핸들러 함수예요. 리소스 로딩이 일시 중단되었을 때 발생해요.
  • onSuspendCapture: 캡처 단계에서 발생하는 onSuspend 버전이에요.
  • onTimeUpdate: Event 핸들러 함수예요. 현재 재생 시간이 업데이트되었을 때 발생해요.
  • onTimeUpdateCapture: 캡처 단계에서 발생하는 onTimeUpdate 버전이에요.
  • onVolumeChange: Event 핸들러 함수예요. 볼륨이 변경되었을 때 발생해요.
  • onVolumeChangeCapture: 캡처 단계에서 발생하는 onVolumeChange 버전이에요.
  • onWaiting: Event 핸들러 함수예요. 일시적인 데이터 부족으로 재생이 멈췄을 때 발생해요.
  • onWaitingCapture: 캡처 단계에서 발생하는 onWaiting 버전이에요.

주의사항(Caveats)

  • childrendangerouslySetInnerHTML을 동시에 전달할 수 없어요.
  • 일부 이벤트(예: onAbortonLoad)는 브라우저에서는 버블링되지 않지만, React에서는 버블링돼요.

ref 콜백 함수

useRef에서 반환된 것 같은 ref 객체 대신, ref 속성에 함수를 전달할 수도 있어요.

<div ref={(node) => {
  console.log('Attached', node);

  return () => {
    console.log('Clean up', node)
  }
}}>

ref 콜백 사용 예제를 확인해보세요.

<div> DOM 노드가 화면에 추가되면, React는 DOM node를 인수로 해서 여러분의 ref 콜백을 호출할 거예요. 그리고 그 <div> DOM 노드가 제거되면, React는 콜백에서 반환된 클린업 함수를 호출할 거예요.

React는 여러분이 다른 ref 콜백을 전달할 때마다 ref 콜백을 호출해요. 위 예제에서 (node) => { ... }는 매 렌더링마다 다른 함수예요. 컴포넌트가 리렌더링되면, 이전 함수가 null을 인수로 호출되고, 다음 함수가 DOM 노드와 함께 호출될 거예요.

매개변수(Parameters)

  • node: DOM 노드예요. React는 ref가 연결될 때 DOM 노드를 전달해줘요. 매 렌더링마다 ref 콜백에 같은 함수 참조를 전달하지 않으면, 컴포넌트가 리렌더링될 때마다 콜백이 일시적으로 클린업되고 다시 생성될 거예요.

📝 참고

React 19에서 ref 콜백에 클린업 함수가 추가되었어요.

하위 호환성을 지원하기 위해, ref 콜백에서 클린업 함수가 반환되지 않으면, ref가 분리될 때 null로 콜백이 호출될 거예요. 이 동작은 향후 버전에서 제거될 예정이에요.

반환값(Returns)

  • 선택적 클린업 함수: ref가 분리될 때, React는 클린업 함수를 호출해요. ref 콜백에서 함수가 반환되지 않으면, React는 ref가 분리될 때 null을 인수로 다시 콜백을 호출할 거예요. 이 동작은 향후 버전에서 제거될 예정이에요.

주의사항(Caveats)

  • Strict Mode가 켜져 있으면, React는 첫 번째 실제 설정(setup) 전에 개발 모드 전용으로 한 번 추가 설정+클린업 사이클을 실행할 거예요. 이건 여러분의 클린업 로직이 설정 로직을 "미러링"하고, 설정이 하는 것을 중지하거나 되돌리는지 확인하는 스트레스 테스트예요. 이게 문제를 일으키면, 클린업 함수를 구현하세요.
  • 여러분이 다른 ref 콜백을 전달하면, React는 제공된 경우 이전 콜백의 클린업 함수를 호출할 거예요. 클린업 함수가 정의되어 있지 않으면, ref 콜백이 null을 인수로 호출돼요. 다음 함수는 DOM 노드와 함께 호출될 거예요.

React 이벤트 객체

여러분의 이벤트 핸들러는 React 이벤트 객체를 받게 돼요. "합성 이벤트(synthetic event)"라고도 불려요.

<button onClick={e => {
  console.log(e); // React event object
}} />

이건 기반이 되는 DOM 이벤트와 같은 표준을 준수하지만, 일부 브라우저 비일관성을 수정해요.

일부 React 이벤트는 브라우저의 네이티브 이벤트에 직접 매핑되지 않아요. 예를 들어 onMouseLeave에서 e.nativeEventmouseout 이벤트를 가리킬 거예요. 구체적인 매핑은 공개 API의 일부가 아니며 향후 변경될 수 있어요. 어떤 이유로 기반 브라우저 이벤트가 필요하다면, e.nativeEvent에서 읽으세요.

프로퍼티(Properties)

React 이벤트 객체는 표준 Event 프로퍼티 중 일부를 구현해요:

  • bubbles: 불리언이에요. 이벤트가 DOM을 통해 버블링되는지 반환해요.
  • cancelable: 불리언이에요. 이벤트를 취소할 수 있는지 반환해요.
  • currentTarget: DOM 노드예요. React 트리에서 현재 핸들러가 연결된 노드를 반환해요.
  • defaultPrevented: 불리언이에요. preventDefault가 호출되었는지 반환해요.
  • eventPhase: 숫자예요. 이벤트가 현재 어떤 단계에 있는지 반환해요.
  • isTrusted: 불리언이에요. 이벤트가 사용자에 의해 시작되었는지 반환해요.
  • target: DOM 노드예요. 이벤트가 발생한 노드를 반환해요 (먼 자식일 수도 있어요).
  • timeStamp: 숫자예요. 이벤트가 발생한 시간을 반환해요.

추가적으로, React 이벤트 객체는 다음 프로퍼티를 제공해요:

  • nativeEvent: DOM Event예요. 원본 브라우저 이벤트 객체예요.

메서드(Methods)

React 이벤트 객체는 표준 Event 메서드 중 일부를 구현해요:

추가적으로, React 이벤트 객체는 다음 메서드를 제공해요:

  • isDefaultPrevented(): preventDefault가 호출되었는지를 나타내는 불리언 값을 반환해요.
  • isPropagationStopped(): stopPropagation이 호출되었는지를 나타내는 불리언 값을 반환해요.
  • persist(): React DOM에서는 사용되지 않아요. React Native에서는 이벤트 이후에 이벤트의 프로퍼티를 읽으려면 이걸 호출하세요.
  • isPersistent(): React DOM에서는 사용되지 않아요. React Native에서는 persist가 호출되었는지 반환해요.

주의사항(Caveats)

  • currentTarget, eventPhase, target, type의 값은 React 코드가 기대하는 값을 반영해요. 내부적으로 React는 루트에서 이벤트 핸들러를 연결하지만, 이건 React 이벤트 객체에 반영되지 않아요. 예를 들어, e.currentTarget은 기반이 되는 e.nativeEvent.currentTarget과 같지 않을 수 있어요. 폴리필된 이벤트의 경우, e.type(React 이벤트 타입)이 e.nativeEvent.type(기반 타입)과 다를 수 있어요.

AnimationEvent 핸들러 함수

CSS 애니메이션 이벤트에 대한 이벤트 핸들러 타입이에요.

<div
  onAnimationStart={e => console.log('onAnimationStart')}
  onAnimationIteration={e => console.log('onAnimationIteration')}
  onAnimationEnd={e => console.log('onAnimationEnd')}
/>

매개변수(Parameters)


ClipboardEvent 핸들러 함수

Clipboard API 이벤트에 대한 이벤트 핸들러 타입이에요.

<input
  onCopy={e => console.log('onCopy')}
  onCut={e => console.log('onCut')}
  onPaste={e => console.log('onPaste')}
/>

매개변수(Parameters)


CompositionEvent 핸들러 함수

입력기(IME) 이벤트에 대한 이벤트 핸들러 타입이에요.

<input
  onCompositionStart={e => console.log('onCompositionStart')}
  onCompositionUpdate={e => console.log('onCompositionUpdate')}
  onCompositionEnd={e => console.log('onCompositionEnd')}
/>

매개변수(Parameters)


DragEvent 핸들러 함수

HTML 드래그 앤 드롭 API 이벤트에 대한 이벤트 핸들러 타입이에요.

<>
  <div
    draggable={true}
    onDragStart={e => console.log('onDragStart')}
    onDragEnd={e => console.log('onDragEnd')}
  >
    Drag source
  </div>

  <div
    onDragEnter={e => console.log('onDragEnter')}
    onDragLeave={e => console.log('onDragLeave')}
    onDragOver={e => { e.preventDefault(); console.log('onDragOver'); }}
    onDrop={e => console.log('onDrop')}
  >
    Drop target
  </div>
</>

매개변수(Parameters)


FocusEvent 핸들러 함수

포커스 이벤트에 대한 이벤트 핸들러 타입이에요.

<input
  onFocus={e => console.log('onFocus')}
  onBlur={e => console.log('onBlur')}
/>

예제를 확인해보세요.

매개변수(Parameters)


Event 핸들러 함수

일반적인 이벤트에 대한 이벤트 핸들러 타입이에요.

매개변수(Parameters)


InputEvent 핸들러 함수

onBeforeInput 이벤트에 대한 이벤트 핸들러 타입이에요.

<input onBeforeInput={e => console.log('onBeforeInput')} />

매개변수(Parameters)


KeyboardEvent 핸들러 함수

키보드 이벤트에 대한 이벤트 핸들러 타입이에요.

<input
  onKeyDown={e => console.log('onKeyDown')}
  onKeyUp={e => console.log('onKeyUp')}
/>

예제를 확인해보세요.

매개변수(Parameters)


사용법

CSS 스타일 적용하기

React에서는 className을 사용해서 CSS 클래스를 지정해요. HTML의 class 속성과 똑같이 동작해요:

<img className="avatar" />

그런 다음 별도의 CSS 파일에서 해당 클래스에 대한 CSS 규칙을 작성하면 돼요:

/* CSS 파일에서 */
.avatar {
  border-radius: 50%;
}

React는 CSS 파일을 어떻게 추가해야 하는지 정해놓지 않았어요. 가장 간단한 경우에는 HTML에 <link> 태그를 추가하면 돼요. 만약 빌드 도구나 프레임워크를 사용한다면, 해당 문서를 참고해서 프로젝트에 CSS 파일을 추가하는 방법을 알아보세요.

때로는 스타일 값이 데이터에 따라 달라지기도 해요. 이런 경우에는 style 속성을 사용해서 동적으로 스타일을 전달할 수 있어요:

<img
  className="avatar"
  style={{
    width: user.imageSize,
    height: user.imageSize
  }}
/>

위 예제에서 style={{}}은 특별한 문법이 아니에요. style={ } JSX 중괄호 안에 있는 일반적인 {} 객체예요. 스타일이 JavaScript 변수에 의존할 때만 style 속성을 사용하는 것을 권장해요.

💡 부연 설명: style={{ }}에서 바깥쪽 중괄호 { }는 "여기 안에 JavaScript 표현식이 들어갈 거야"라고 알려주는 JSX 문법이고, 안쪽 중괄호 { }는 JavaScript 객체를 만드는 문법이에요. 그래서 결과적으로 스타일 객체를 전달하는 거죠!

// src/App.js
import Avatar from './Avatar.js';

const user = {
  name: 'Hedy Lamarr',
  imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
  imageSize: 90,
};

export default function App() {
  return <Avatar user={user} />;
}
// src/Avatar.js
export default function Avatar({ user }) {
  return (
    <img
      src={user.imageUrl}
      alt={'Photo of ' + user.name}
      className="avatar"
      style={{
        width: user.imageSize,
        height: user.imageSize
      }}
    />
  );
}
/* src/styles.css */
.avatar {
  border-radius: 50%;
}
Deep Dive: 여러 CSS 클래스를 조건부로 적용하는 방법은?

CSS 클래스를 조건부로 적용하려면, JavaScript를 사용해서 직접 className 문자열을 만들어야 해요.

예를 들어, className={'row ' + (isSelected ? 'selected': '')}isSelectedtrue인지 여부에 따라 className="row" 또는 className="row selected"를 만들어내요.

이걸 더 읽기 쉽게 만들려면, classnames 같은 작은 헬퍼 라이브러리를 사용할 수 있어요:

import cn from 'classnames';

function Row({ isSelected }) {
  return (
    <div className={cn('row', isSelected && 'selected')}>
      ...
    </div>
  );
}

조건부 클래스가 여러 개일 때 특히 편리해요:

import cn from 'classnames';

function Row({ isSelected, size }) {
  return (
    <div className={cn('row', {
      selected: isSelected,
      large: size === 'large',
      small: size === 'small',
    })}>
      ...
    </div>
  );
}

💡 부연 설명: classnames 라이브러리는 조건에 따라 클래스를 추가하거나 제거하는 작업을 훨씬 깔끔하게 만들어줘요. 복잡한 삼항 연산자나 문자열 연결 없이도 선언적으로 클래스를 관리할 수 있어서 코드 가독성이 좋아져요!


ref로 DOM 노드 조작하기

때로는 JSX의 태그와 연결된 브라우저 DOM 노드를 가져와야 할 때가 있어요. 예를 들어, 버튼을 클릭했을 때 <input>에 포커스를 주고 싶다면, 브라우저의 <input> DOM 노드에서 focus()를 호출해야 해요.

태그에 대한 브라우저 DOM 노드를 얻으려면, ref를 선언하고 해당 태그에 ref 속성으로 전달하세요:

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);
  // ...
  return (
    <input ref={inputRef} />
    // ...

React는 화면에 렌더링된 후에 DOM 노드를 inputRef.current에 넣어줄 거예요.

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
}

ref로 DOM 조작하기에 대해 더 읽어보고 더 많은 예제를 확인하세요.

더 고급 사용 사례의 경우, ref 속성은 콜백 함수도 받을 수 있어요.


위험하게 내부 HTML 설정하기

다음과 같이 엘리먼트에 원시 HTML 문자열을 전달할 수 있어요:

const markup = { __html: '<p>some raw html</p>' };
return <div dangerouslySetInnerHTML={markup} />;

이건 위험해요. 기본 DOM의 innerHTML 프로퍼티와 마찬가지로, 극도의 주의를 기울여야 해요! 마크업이 완전히 신뢰할 수 있는 소스에서 오는 게 아니라면, 이 방법으로 XSS 취약점을 만드는 건 매우 쉬워요.

예를 들어, Markdown을 HTML로 변환하는 Markdown 라이브러리를 사용하고, 해당 파서에 버그가 없다고 신뢰하며, 사용자가 자신의 입력만 본다면, 결과 HTML을 다음과 같이 표시할 수 있어요:

// src/App.js
import { useState } from 'react';
import MarkdownPreview from './MarkdownPreview.js';

export default function MarkdownEditor() {
  const [postContent, setPostContent] = useState('_Hello,_ **Markdown**!');
  return (
    <>
      <label>
        Enter some markdown:
        <textarea
          value={postContent}
          onChange={e => setPostContent(e.target.value)}
        />
      </label>
      <hr />
      <MarkdownPreview markdown={postContent} />
    </>
  );
}
// src/MarkdownPreview.js
import { Remarkable } from 'remarkable';

const md = new Remarkable();

function renderMarkdownToHTML(markdown) {
  // 이건 출력 HTML이 같은 사용자에게 보여지고,
  // 이 Markdown 파서에 버그가 없다고 신뢰하기 때문에만 안전해요.
  const renderedHTML = md.render(markdown);
  return {__html: renderedHTML};
}

export default function MarkdownPreview({ markdown }) {
  const markup = renderMarkdownToHTML(markdown);
  return <div dangerouslySetInnerHTML={markup} />;
}
// package.json
{
  "dependencies": {
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "remarkable": "2.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}
textarea { display: block; margin-top: 5px; margin-bottom: 10px; }

{__html} 객체는 위 예제의 renderMarkdownToHTML 함수에서처럼 HTML이 생성되는 곳에 최대한 가깝게 만들어야 해요. 이렇게 하면 코드에서 사용되는 모든 원시 HTML이 명시적으로 그렇게 표시되고, HTML을 포함할 것으로 예상되는 변수만 dangerouslySetInnerHTML에 전달되도록 보장할 수 있어요. <div dangerouslySetInnerHTML={{__html: markup}} />처럼 인라인으로 객체를 만드는 것은 권장하지 않아요.

임의의 HTML을 렌더링하는 것이 왜 위험한지 보려면, 위 코드를 다음과 같이 바꿔보세요:

const post = {
  // 이 내용이 데이터베이스에 저장되어 있다고 상상해보세요.
  content: `<img src="" onerror='alert("you were hacked")'>`
};

export default function MarkdownPreview() {
  // 🔴 보안 구멍: 신뢰할 수 없는 입력을 dangerouslySetInnerHTML에 전달
  const markup = { __html: post.content };
  return <div dangerouslySetInnerHTML={markup} />;
}

HTML에 포함된 코드가 실행될 거예요. 해커가 이 보안 구멍을 사용해서 사용자 정보를 훔치거나 사용자를 대신해서 작업을 수행할 수 있어요. dangerouslySetInnerHTML은 신뢰할 수 있고 살균(sanitized)된 데이터에만 사용하세요.

💡 부연 설명: "살균(sanitize)"이란 악성 스크립트나 위험한 HTML 태그를 제거하는 과정을 말해요. DOMPurify 같은 라이브러리를 사용해서 사용자 입력을 안전하게 처리할 수 있어요. 절대로 사용자가 입력한 데이터를 그대로 dangerouslySetInnerHTML에 전달하면 안 돼요!


마우스 이벤트 처리하기

이 예제는 일반적인 마우스 이벤트들과 언제 발생하는지를 보여줘요.

export default function MouseExample() {
  return (
    <div
      onMouseEnter={e => console.log('onMouseEnter (parent)')}
      onMouseLeave={e => console.log('onMouseLeave (parent)')}
    >
      <button
        onClick={e => console.log('onClick (first button)')}
        onMouseDown={e => console.log('onMouseDown (first button)')}
        onMouseEnter={e => console.log('onMouseEnter (first button)')}
        onMouseLeave={e => console.log('onMouseLeave (first button)')}
        onMouseOver={e => console.log('onMouseOver (first button)')}
        onMouseUp={e => console.log('onMouseUp (first button)')}
      >
        First button
      </button>
      <button
        onClick={e => console.log('onClick (second button)')}
        onMouseDown={e => console.log('onMouseDown (second button)')}
        onMouseEnter={e => console.log('onMouseEnter (second button)')}
        onMouseLeave={e => console.log('onMouseLeave (second button)')}
        onMouseOver={e => console.log('onMouseOver (second button)')}
        onMouseUp={e => console.log('onMouseUp (second button)')}
      >
        Second button
      </button>
    </div>
  );
}
label { display: block; }
input { margin-left: 10px; }

포인터 이벤트 처리하기

이 예제는 일반적인 포인터 이벤트들과 언제 발생하는지를 보여줘요.

export default function PointerExample() {
  return (
    <div
      onPointerEnter={e => console.log('onPointerEnter (parent)')}
      onPointerLeave={e => console.log('onPointerLeave (parent)')}
      style={{ padding: 20, backgroundColor: '#ddd' }}
    >
      <div
        onPointerDown={e => console.log('onPointerDown (first child)')}
        onPointerEnter={e => console.log('onPointerEnter (first child)')}
        onPointerLeave={e => console.log('onPointerLeave (first child)')}
        onPointerMove={e => console.log('onPointerMove (first child)')}
        onPointerUp={e => console.log('onPointerUp (first child)')}
        style={{ padding: 20, backgroundColor: 'lightyellow' }}
      >
        First child
      </div>
      <div
        onPointerDown={e => console.log('onPointerDown (second child)')}
        onPointerEnter={e => console.log('onPointerEnter (second child)')}
        onPointerLeave={e => console.log('onPointerLeave (second child)')}
        onPointerMove={e => console.log('onPointerMove (second child)')}
        onPointerUp={e => console.log('onPointerUp (second child)')}
        style={{ padding: 20, backgroundColor: 'lightblue' }}
      >
        Second child
      </div>
    </div>
  );
}
label { display: block; }
input { margin-left: 10px; }

💡 부연 설명: 포인터 이벤트는 마우스, 터치, 펜 등 다양한 입력 장치를 통합적으로 처리할 수 있어요. 마우스 이벤트보다 더 범용적이라서, 요즘은 포인터 이벤트를 사용하는 것이 권장되는 경우가 많아요!


포커스 이벤트 처리하기

React에서 포커스 이벤트는 버블링돼요. currentTargetrelatedTarget을 사용해서 포커스나 블러 이벤트가 부모 엘리먼트 바깥에서 시작되었는지 구분할 수 있어요. 이 예제는 자식에 포커스가 갔을 때, 부모 엘리먼트에 포커스가 갔을 때, 그리고 전체 서브트리에 포커스가 들어오거나 나갈 때를 어떻게 감지하는지 보여줘요.

export default function FocusExample() {
  return (
    <div
      tabIndex={1}
      onFocus={(e) => {
        if (e.currentTarget === e.target) {
          console.log('focused parent');
        } else {
          console.log('focused child', e.target.name);
        }
        if (!e.currentTarget.contains(e.relatedTarget)) {
          // 자식들 사이에서 포커스를 바꿀 때는 트리거되지 않아요
          console.log('focus entered parent');
        }
      }}
      onBlur={(e) => {
        if (e.currentTarget === e.target) {
          console.log('unfocused parent');
        } else {
          console.log('unfocused child', e.target.name);
        }
        if (!e.currentTarget.contains(e.relatedTarget)) {
          // 자식들 사이에서 포커스를 바꿀 때는 트리거되지 않아요
          console.log('focus left parent');
        }
      }}
    >
      <label>
        First name:
        <input name="firstName" />
      </label>
      <label>
        Last name:
        <input name="lastName" />
      </label>
    </div>
  );
}
label { display: block; }
input { margin-left: 10px; }

💡 부연 설명:

  • e.currentTarget은 이벤트 핸들러가 연결된 엘리먼트예요.
  • e.target은 실제로 이벤트가 발생한 엘리먼트예요.
  • e.relatedTarget은 포커스 이벤트의 경우 포커스가 이동하기 전(또는 이동할) 엘리먼트예요.

이 세 가지를 조합하면 포커스가 어디서 어디로 이동했는지 정확하게 파악할 수 있어요!


키보드 이벤트 처리하기

이 예제는 일반적인 키보드 이벤트들과 언제 발생하는지를 보여줘요.

export default function KeyboardExample() {
  return (
    <label>
      First name:
      <input
        name="firstName"
        onKeyDown={e => console.log('onKeyDown:', e.key, e.code)}
        onKeyUp={e => console.log('onKeyUp:', e.key, e.code)}
      />
    </label>
  );
}
label { display: block; }
input { margin-left: 10px; }

💡 부연 설명:

  • e.key는 눌린 키의 값을 나타내요 (예: "a", "Enter", "Shift").
  • e.code는 물리적 키의 코드를 나타내요 (예: "KeyA", "Enter", "ShiftLeft").

키보드 레이아웃에 관계없이 특정 물리적 키를 감지하고 싶다면 e.code를, 사용자가 실제로 입력한 문자를 알고 싶다면 e.key를 사용하세요!

profile
프론트에_가까운_풀스택_개발자

0개의 댓글