무엇
<div>·<span> 같은 모든 내장 DOM 요소가 공통으로 받는 props의 묶음이다. ref·style·className·이벤트 핸들러처럼 특정 태그가 아니라 브라우저 요소 전반에 통하는 것들이다.
HTML 속성을 거의 그대로 쓰되 이름이 몇 개 다르다. class는 className, for는 htmlFor, 인라인 스타일은 문자열이 아니라 객체다.
<label htmlFor="email">이메일</label>
<input id="email" className="field" style={{ marginTop: 8 }} />
무슨 일이 일어나나
style은 camelCase 키를 가진 객체다. font-weight가 아니라 fontWeight, 숫자를 주면 단위 없는 속성이 아닌 한 자동으로 px가 붙는다.
이벤트 핸들러는 전부 camelCase다(onClick·onChange·onKeyDown). 핸들러는 브라우저 네이티브 이벤트가 아니라 React의 합성 이벤트(SyntheticEvent)를 받는다. e.target은 이벤트가 난 요소, e.currentTarget은 핸들러가 붙은 요소이고, e.preventDefault()·e.stopPropagation()이 있으며 원본은 e.nativeEvent로 꺼낸다. 캡처 단계가 필요하면 onClickCapture처럼 Capture 접미사를 쓴다. 단 onMouseEnter·onMouseLeave는 캡처 단계가 없다.
data-*·aria-* 같은 커스텀 속성은 소문자로, on으로 시작하지 않게 쓰면 그대로 DOM에 전달된다. 값이 null·undefined면 속성 자체가 빠진다.
사용법
ref로 DOM 노드를 잡는다. useRef로 만든 참조를 ref에 넘기면 마운트 후 .current에 실제 노드가 담긴다. React 19부터 ref는 함수 컴포넌트에서도 평범한 prop이라, DOM 요소에 바로 넘기는 이 용법에는 forwardRef가 필요 없다.
import { useRef } from 'react'
export function FocusInput() {
const inputRef = useRef<HTMLInputElement>(null)
return (
<>
<input ref={inputRef} />
<button onClick={() => inputRef.current?.focus()}>포커스</button>
</>
)
}
콜백 ref는 정리 함수를 돌려줄 수 있다. React 19에서 ref 콜백이 함수를 반환하면, 노드가 떨어질 때 그 함수가 불린다.
<div
ref={(node) => {
// 노드 붙음
return () => {
// 노드 떨어짐 — 정리
}
}}
/>
실무 예시
원시 HTML을 직접 꽂아야 하면 dangerouslySetInnerHTML을 쓴다. 이름 그대로 XSS 위험이 있어, 신뢰할 수 있고 정화된 문자열에만 쓴다. children과 동시에 줄 수 없다.
export function RenderMarkup({ html }: { html: string }) {
// html은 이미 sanitize된 신뢰 가능한 값이어야 한다
return <div dangerouslySetInnerHTML={{ __html: html }} />
}
왜 중요한가
이 공통 props는 React로 마크업을 쓸 때 매일 만지는 표면이다. className·htmlFor·객체 style처럼 HTML과 다른 지점, 합성 이벤트의 target/currentTarget 구분, ref로 실제 노드에 닿는 법은 특정 컴포넌트가 아니라 모든 요소에 통하는 기본기다. 개별 태그 문서를 뒤지기 전에 여기 한 번 정리해 두면, 어느 요소를 쓰든 같은 규칙이 반복된다는 걸 알게 된다.
Reference