[React 19] 공식문서 톺아보기 - React DOM 컴포넌트 (1)
• Study
모든 브라우저 컴포넌트가 지원하는 Props와 이벤트에 대해 공부하였습니다. 내용이 많아서 자주 쓰이거나 몰랐던 부분 위주로 정리하였습니다.
Common
React Props
children
: React 노드(요소, 문자열, 숫자, Portal,null
,undefined
, 불리언 타입과 같은 빈 노드, 또는 다른 React 노드의 배열) 이다. 컴포넌트 내부의 콘텐츠를 지정한다.dangerouslySetInnerHTML
: 원시 HTML 문자열이 포함된{ __html: '<p>some html</p>' }
형식의 객체이다. DOM 노드의innerHTML
프로퍼티를 덮어쓰고 전달된 HTML을 내부에 표시한다. 이것은 어떤 과정을 거치지 않고 스크립트 등을 포함할 경우 그대로 실행하기 때문에 매우 주의해서 사용해야 한다. XSS 취약점이 발생할 수 있다.children
과dangerouslySetInnerHTML
는 모두 내부 콘텐츠를 지정하는 속성이며 따라서 동시에 전달할 수 없다.
style
:{ fontWeight: 'bold', margin: 20 }
와 같이 CSS 스타일이 있는 객체이다.
DOM Props
aria-*
: ARIA 속성을 사용하면 이 요소에 대한 접근성 트리 정보를 지정할 수 있다. React에서 모든 ARIA 어트리뷰트의 이름은 HTML에서의 이름과 완전히 동일하다.translate
:'yes'
나'no'
중 하나이다.'no'
를 전달하면 요소의 콘텐츠가 번역에서 제외된다. 서비스의 이름같은 경우 번역되지 않게 막을 수 있다. 예를들어 'React'를 '반응'으로 번역되는것을 막을 수 있다.contentEditable
: 불리언 타입으로,true
일 때 브라우저는 사용자가 렌더링 된 요소를 직접 편집할 수 있도록 한다. 이는 Lexical과 같은 서식이 있는 텍스트 입력 라이브러리를 구현하는 데 사용된다.contentEditable={true}
가 있는 요소는 사용자에 의해 직접 DOM이 수정될 수 있다. 직접 수정하게 되면 가상 DOM과 실제 DOM 사이에 차이가 생겨 React에서 편집한 내용을 인식하지 못한다. 따라서 리렌더링이 발생할때 사용자의 편집 내용을 덮어쓸 수 있으므로contentEditable={true}
가 있는 요소에 React의 자식을 전달하려고 하면 경고를 표시한다.
htmlFor
: 문자열 타입이다.<label>
이나<output>
의 경우 label을 일부 동작에 연결할 수 있다. 이는 HTML 어트리뷰트의for
과 동일하다. React는 HTML 어트리뷰트의 이름 대신htmlFor
와 같은 표준 DOM 프로퍼티의 이름을 사용한다.onDoubleClick
:MouseEvent
핸들러 함수이다. 두 번 클릭하면 발생한다. 브라우저의dblclick
이벤트에 해당한다.onKeyDown
:KeyboardEvent
핸들러 함수이다. 키를 누르면 실행된다.onkeypress
는 더이상 사용되지 않는다.onCopy
,onPaste
:ClipboardEvent
핸들러 함수이다. 사용자가 클립보드에서 복사하고 붙여 넣으려고 할 때 발생한다. 복사 붙여넣기를 방지할때 이 이벤트를 통해 제어할 수 있다.enterKeyHint
: 문자열 타입이다. 가상 키보드의 입력 키에 어떤 동작을 표시할지 지정한다.enter
,search
,send
등을 지정할수 있다.inputMode
: 문자열 타입이다. 표시할 키보드의 종류(예시: 텍스트, 숫자 또는 전화번호)를 지정한다.
inputMode 와 input 태그의 type 의 차이
<!-- type: 숫자만 허용 (e, +, - 등 입력 불가) -->
<input type="number" />
<!-- inputmode: 숫자 키보드 표시 (but 모든 문자 입력 가능) -->
<input inputmode="numeric" />
<!-- type: 숫자만 허용 (e, +, - 등 입력 불가) -->
<input type="number" />
<!-- inputmode: 숫자 키보드 표시 (but 모든 문자 입력 가능) -->
<input inputmode="numeric" />
- 입력값의 유효성 검사, 데스크톱 영향 등에 대해서
type
을 지정하는것이 더 유리하다.
<!-- 신용카드 번호 (실제로는 문자열) -->
<input pattern="[0-9\s]{13,19}" inputmode="numeric" />
<!-- 신용카드 번호 (실제로는 문자열) -->
<input pattern="[0-9\s]{13,19}" inputmode="numeric" />
- 다만 과한 유효성 검사말고 모바일 가상 키보드등 ui에만 영향을 주고 싶을때는
inputMode
를 사용할 수 있고pattern
속성을 통해 유효성 검사도 함께 진행할 수 있다. - type을 number로 지정한 경우에 입력창 우측에 '스피너'라고하는 화살표가 생기게 되는데 미관상의 이유로 제거하고 싶을때는
input::-webkit-outer-spin-button
,input::-webkit-inner-spin-button
와 같은 css 속성을 통해 없앨 수 있다.
audio, video props
onCanPlay
: 재생을 시작하기에 충분한 데이터가 있지만 버퍼링 없이 끝까지 재생할 수 없을 때 발생한다.onEmptied
: 미디어가 비어있을 때 발생한다.onEnded
: 재생할 내용이 남아 있지 않아 재생이 중지되면 발생한다.onWaiting
: 일시적인 데이터 부족으로 인해 재생이 중지된 경우 발생한다.
Mouse vs Pointer vs Touch
- Mouse
- 마우스 입력 전용으로 설계되었다.
- 모든 브라우저에서 지원된다.
- Pointer
- 모든 입력 장치 통합 지원 (마우스, 터치, 펜, 모션 센서 등).
pointerType
속성으로 입력 장치 구분 가능 ("mouse"
,"touch"
,"pen"
).- 멀티터치 지원: 동시에 여러 포인트(예: 두 손가락)를 추적할 수 있다.
- IE11을 제외한 모든 최신 브라우저에서 지원된다.
- Touch
- 마우스에는 반응하지 않는다.
- 멀티 터치를 지원한다.
- 스크롤/확대 등 기본 브라우저 동작과 충돌할 수 있어서
preventDefault()
사용을 주의해야 한다. 예를들어touchstart
이벤트에e.preventDefault();
를 실행할 경우 해당 요소는 터치뿐만 아니라 기본적인 상호작용인 스크롤, 줌이 동작하지 않게 된다.
ref
콜백 함수
<div ref={(node) => {
console.log('Attached', node);
return () => {
console.log('Clean up', node)
}
}}>
<div ref={(node) => {
console.log('Attached', node);
return () => {
console.log('Clean up', node)
}
}}>
useRef
에서 반환되는ref
객체 대신,ref
속성에 함수를 전달할 수 있다.- DOM 노드가 제거되면 React는 콜백에서 반환된 정리 함수를 호출한다. (리액트 19에서 추가된 기능)
- DOM 노드가 생성되거나 제거될 타이밍에 실행할 코드를 이곳에 선언할 수 있다. 혹은 DOM에 직접 이벤트 리스너를 붙이는 경우에도 사용할 수 있다.
React 이벤트 객체
<button
onClick={(e) => {
console.log(e); // React 이벤트 객체
}}
/>
<button
onClick={(e) => {
console.log(e); // React 이벤트 객체
}}
/>
React의 SyntheticEvent(합성 이벤트)는 React가 브라우저의 네이티브 이벤트를 감싸서 만든 크로스 브라우저 호환 이벤트 객체다. 실제 DOM 이벤트와 유사하지만, 모든 브라우저에서 일관된 동작을 보장하기 위해 설계되었다. 예를들어 SyntheticMouseEvent는 실제 DOM 이벤트인 MouseEvent와 맵핑된다.
React 17+에서는 SyntheticEvent 클래스가 일반 객체로 바뀌면서 명칭도 SyntheticEvent가 아닌 그냥 이벤트 객체라고 칭하고 있다.
- 일부 React의 이벤트는 브라우저의 네이티브 이벤트에 직접 매핑되지 않는다.
- _ React는 크로스 브라우저 호환성과 성능 최적화를 위해 자체적인 이벤트 시스템을 구현했다. 이로 인해 일부 React 이벤트는 브라우저의 네이티브 이벤트와 1:1로 매핑되지 않는다.
- 브라우저 이벤트는 실제 DOM기반인 반면 리액트 이벤트는 가상 DOM에 기반한 이벤트이다.
addEventListener
로 직접 DOM에 바인딩한 경우, 리액트의 합성 이벤트 시스템 바깥에서 동작한다.
- React 이벤트와 네이티브 이벤트의 동작이 다른 이벤트 예시
onChange
:oninput
과 유사하고 폼 입력 시 실시간으로 반응하도록 확장한다.onMouseEnter
/onMouseLeave
:mouseover
/mouseout
은 버블링 되지만, 버블링을 모방하지 않아 자식 요소 진입 시 불필요한 트리거를 방지한다.onFocus
/onBlur
: 버블링되게끔 수정했다.
- 이벤트 객체의 프로퍼티
bubbles
: 불리언 타입이다. 이벤트가 DOM을 통해 버블링되는지 여부를 반환한다.cancelable
: 불리언 타입이다. 이벤트를 취소할 수 있는지를 반환한다.currentTarget
: DOM 노드이다. React 트리에서 현재 핸들러가 연결된 노드를 반환한다.defaultPrevented
: 불리언 타입이다.preventDefault
가 호출되었는지 여부를 반환한다.eventPhase
: 숫자 타입이다. 이벤트가 현재 어느 단계에 있는지 반환한다.isTrusted
: 불리언 타입이다. 사용자에 의해 이벤트가 시작되었는지에 대한 여부를 반환한다.target
: DOM 노드이다. (멀리 있는 자식일 수도 있는) 이벤트가 발생한 노드를 반환한다.timeStamp
: 숫자 타입이다. 이벤트가 발생한 시간을 반환한다.nativeEvent
: DOMEvent
이벤트이다. 원래의 브라우저 이벤트 객체이다.preventDefault()
: 이벤트에 대한 기본 브라우저 동작을 방지한다.stopPropagation()
: React 트리를 통한 이벤트 전파를 중지한다.
currentTarget
,eventPhase
,target
,type
의 값은 React 코드가 예상하는 값을 반영한다. 내부적으로는 React는 이벤트 핸들러를 루트에 첨부하지만, React 이벤트 객체에는 반영되지 않는다. 예를 들어e.currentTarget
은 기본e.nativeEvent.currentTarget
과 동일하지 않을 수 있다.
React의 이벤트를 사용하는 것과 addEventListener
를 이용한 이벤트 사용의 차이
- React는 가상 DOM에 자체 이벤트 시스템을 구축하여 사용한다.
- 그런데
addEventListener
를 사용할 경우는 브라우저의 기본 이벤트 API를 직접호출하므로 React의 추상화 계층을 우회한다. 그래서 React에서 진행한 최적화된 이벤트 시스템의 혜택을 받을 수 없다. - 실행시점에도 차이가 있는데, 네이티브 이벤트가 항상 먼저 실행되고 React 이벤트의 경우는 이벤트 위임을 통해 루트에서 처리되므로 약간의 지연이 발생한다.
- 이벤트 전파 충돌의 측면에서 원치 않는 결과가 나올수 있어 혼용 사용은 유지보수를 어렵게 만들 수 있다. 예륻 들어 React 이벤트 속에서
e.stopPropagation()
를 작성하더라도 네이티브 이벤트를 차단하지는 못한다.e.nativeEvent.stopImmediatePropagation();
를 통해 브라우저의 이벤트 차단 함수를 사용해야한다. - React가 지원하지 않는 이벤트, 고성능 스크롤/터치 처리, 서드파티 라이브러리 연동 등에서 네이티브 이벤트를 사용한다.
그 외 React 이벤트 객체
AnimationEvent
: CSS 애니메이션 이벤트ClipboardEvent
: 클립보드 API 이벤트CompositionEvent
: 입력 메서드 편집기 이벤트DragEvent
: HTML 드래그 앤 드롭 API 이벤트FocusEvent
: 포커싱 이벤트InputEvent
: 입력 이벤트KeyboardEvent
: 키보드 이벤트MouseEvent
: 마우스 이벤트PointerEvent
: 포인터 이벤트TouchEvent
: 터치 이벤트TransitionEvent
: CSS 전환 이벤트UIEvent
: 일반적인 UI 이벤트WheelEvent
:onWheel
이벤트