개요
useInsertionEffect
는 CSS-in-JS 라이브러리 작성자를 위한 React Hook으로, 레이아웃 Effect가 실행되기 전에 DOM에 요소(주로 스타일)를 삽입할 수 있게 해줍니다. 일반적인 React 개발자라면 대부분 useEffect
나 useLayoutEffect
를 사용하면 충분합니다.
useInsertionEffect(setup, dependencies?)
Reference
useInsertionEffect(setup, dependencies?)
컴포넌트의 최상위에서 useInsertionEffect
를 호출하면, 레이아웃 Effect가 실행되기 전에 스타일 등 요소를 DOM에 삽입할 수 있습니다.
import { useInsertionEffect } from 'react';
// CSS-in-JS 라이브러리 내부 예시
function useCSS(rule) {
useInsertionEffect(() => {
// ... <style> 태그를 삽입하는 로직 ...
});
return rule;
}
파라미터
setup
: Effect의 로직을 담은 함수. 선택적으로 cleanup 함수를 반환할 수 있습니다. 컴포넌트가 DOM에 추가될 때(그리고 dependencies가 변경될 때) setup 함수가 실행됩니다. 컴포넌트가 제거될 때 cleanup 함수가 실행됩니다.dependencies
(선택): setup에서 참조하는 모든 반응형 값의 배열. 값이 바뀌면 cleanup → setup 순서로 실행됩니다. 생략하면 매 렌더마다 실행됩니다.
반환값
- 반환값 없음 (undefined)
주의사항 및 Caveats
- Effect는 클라이언트에서만 실행됩니다. 서버 렌더링 중에는 실행되지 않습니다.
useInsertionEffect
내부에서는 state를 업데이트할 수 없습니다.- 이 Hook이 실행될 때 ref는 아직 연결되지 않았을 수 있습니다.
- DOM이 업데이트된 시점에 실행된다는 보장이 없습니다.
- cleanup과 setup이 컴포넌트별로 interleaving(교차) 방식으로 실행됩니다.
사용법
CSS-in-JS 라이브러리에서 동적 스타일 삽입
전통적으로는 CSS 파일을 사용하지만, 일부 팀은 스타일을 JS 코드에서 직접 작성하기 위해 CSS-in-JS를 사용합니다. 이때 런타임에 <style>
태그를 삽입해야 한다면, 반드시 useInsertionEffect
에서 삽입해야 합니다.
let isInserted = new Set();
function useCSS(rule) {
useInsertionEffect(() => {
if (!isInserted.has(rule)) {
isInserted.add(rule);
document.head.appendChild(getStyleForRule(rule));
}
});
return rule;
}
function Button() {
const className = useCSS('...');
return <div className={className} />;
}
서버 렌더링과의 차이
서버에서는 useInsertionEffect가 실행되지 않으므로, 서버에서 사용된 CSS rule을 따로 수집해야 합니다.
let collectedRulesSet = new Set();
function useCSS(rule) {
if (typeof window === 'undefined') {
collectedRulesSet.add(rule);
}
useInsertionEffect(() => {
// ...
});
return rule;
}
Deep Dive: 왜 useLayoutEffect보다 빠른가?
렌더링 중에 스타일을 삽입하면, React가 비동기 업데이트를 처리할 때 매 프레임마다 스타일을 재계산하게 되어 매우 느려질 수 있습니다. useInsertionEffect
는 레이아웃 Effect가 실행되기 전에 스타일을 삽입하므로, 레이아웃 계산이 올바른 스타일을 기준으로 이루어집니다.
Pitfall (주의사항)
- CSS-in-JS 라이브러리 작성자가 아니라면 대부분의 경우 이 Hook을 사용할 필요가 없습니다.
- 런타임
<style>
태그 삽입은 성능상 권장되지 않으며, 꼭 필요한 경우에만 사용하세요.
반응형