핵심 요약
React Compiler 1.0이 정식 stable 단계에 진입했다(React 19.2 기반). Meta Quest Store 등 대규모 프로덕션에서 검증됐고 초기 로드·페이지 전환 최대 12% 개선, 일부 인터랙션은 2.5배 빨라졌다. useMemo·useCallback·React.memo를 99% 안 써도 된다.
- 빌드 타임 자동 메모이제이션
- React Native에도 동일 적용
- 코드 재작성 없이 도입
- opt-in/opt-out 디렉티브 지원
1. 무엇을 자동화하는가
Before — 수동 메모이제이션
function ProductList({ products, filter }) {
const filtered = useMemo(
() => products.filter(p => p.category === filter),
[products, filter]
)
const handleClick = useCallback(
(id) => router.push('/product/' + id),
[router]
)
return filtered.map(p => (
<ProductCard key={p.id} product={p} onClick={handleClick} />
))
}
const ProductCard = memo(({ product, onClick }) => { ... })After — 컴파일러가 자동으로
function ProductList({ products, filter }) {
const filtered = products.filter(p => p.category === filter)
const handleClick = (id) => router.push('/product/' + id)
return filtered.map(p => (
<ProductCard key={p.id} product={p} onClick={handleClick} />
))
}
function ProductCard({ product, onClick }) { ... }
// 같은 props면 자동 스킵2. 설치 — Vite/Next.js
# 설치
npm i -D babel-plugin-react-compiler
# Next.js 16+
// next.config.js
module.exports = {
experimental: { reactCompiler: true },
}
# Vite
// vite.config.ts
import react from '@vitejs/plugin-react'
export default {
plugins: [react({
babel: { plugins: ['babel-plugin-react-compiler'] }
})],
}3. eslint-plugin-react-compiler — 필수
컴파일러는 "Rules of React"를 어긴 코드에선 안전상 메모이제이션을 포기한다. ESLint 플러그인이 위반을 잡아준다.
npm i -D eslint-plugin-react-hooks@latest
// .eslintrc
{
"extends": ["plugin:react-hooks/recommended-latest"]
}흔한 위반 사례:
- render 중 mutation (
props.foo = bar) - render 중 ref 읽기 (
ref.current) - conditional hook 호출
4. 점진적 도입 — opt-in 모드
// next.config.js — 특정 디렉터리만
experimental: {
reactCompiler: {
compilationMode: 'annotation', // "use memo" 디렉티브 있는 파일만
},
}// app/products/page.tsx
'use memo'
export default function Products() { ... } // 컴파일러 적용역으로 특정 컴포넌트만 제외:
function LegacyComponent() {
'use no memo' // 컴파일러 비활성
// ...
}5. 실측 효과 (Meta Quest Store)
| 지표 | 개선 |
|---|---|
| 초기 로드 | +12% |
| 페이지 전환 | +12% |
| 주요 인터랙션 (검색·필터) | 2.5x 빠름 |
| 메모리 | 중립 |
6. 코드 사이즈 영향
컴파일러는 useMemoCache 호출을 추가해 약 5~15% 번들 사이즈 증가. 대신 직접 작성한 useMemo/useCallback을 모두 삭제하면 상쇄 또는 감소.
7. 안 되는 케이스
- 비표준 JSX 변환기 사용 시 — 표준 React JSX만 지원
- 매우 오래된 React — React 17 이상 필요(공식은 18.3+)
- 외부 의존성의 비순수 함수 호출 — 컴파일러가 보수적으로 메모이제이션 포기
8. 마이그레이션 단계
- 1주차: ESLint 플러그인 추가 + 위반 수정
- 2주차: 컴파일러 도입(annotation 모드) — 1~2개 라우트만
- 3~4주차: React DevTools Profiler로 효과 측정
- 5주차+: 전체 모드(
compilationMode: 'all')로 전환 - 이후: 기존 useMemo/useCallback 점진 제거 (선택)
9. 디버깅 팁
// React DevTools에서
// 1) Profiler → "Why did this render?" 활성화
// 2) 메모이제이션 적용된 컴포넌트는 "Memoized" 표시
// 3) 적용 안 된 곳은 ESLint 경고 메시지 확인
// 컴파일러가 무시한 컴포넌트 찾기
// babel.config.js
plugins: [['babel-plugin-react-compiler', {
logger: { logEvent: (filename, event) => {
if (event.kind === 'CompileSkipped') console.log(filename, event)
}}
}]]자주 묻는 질문
그럼 useMemo는 영영 안 써도 되나?
99%는 그렇다. 예외: (1) 매우 비싼 계산(이미지 처리·암호화)에 명시적 의존성 표현이 가독성에 도움될 때, (2) 컴파일러가 메모이제이션을 포기한 곳을 ESLint로 확인하고 보강.
React Native도 적용되나?
예. 0.78+ 권장. 동일 패키지(babel-plugin-react-compiler)로 적용.
Server Components와도 호환?
예. 컴파일러는 클라이언트 컴포넌트만 처리. 서버 컴포넌트는 영향 없음.

댓글 0