codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
노트›frontend

React 19 와 React Compiler

2026-04-28 게시· 2026-05-18 갱신·0회 조회

React 19 와 React Compiler

React 19 는 React 의 큰 변곡점 중 하나로 자주 거론됩니다. 그 가운데 React Compiler 는 그동안 손으로 적던 메모를 일부 자동화합니다.

1. React 에 대한 이야기

React 는 2011 년 Facebook 의 Jordan Walke 가 사내 도구 (News Feed) 를 위해 만들었고, 2013 년 5 월 JSConf US 에서 오픈소스로 공개됐습니다. 라이선스는 MIT (2017 년 일시적으로 BSD+Patents 였다가 MIT 로 환원).

버전 시기 사건
0.14 2015 react-dom 분리.
16 2017-09 Fiber 재작성. error boundary · fragments · portals.
16.8 2019-02 Hooks 정식. useState · useEffect.
17 2020-10 "no new features" 릴리스. 점진적 업그레이드 경로.
18 2022-03 Concurrent renderer · automatic batching · useTransition.
19 2024-12 GA Server Components 안정 · use · Actions · ref-as-prop · <form action> 통합.

19 와 함께 (별도 패키지로) React Compiler 가 공개됐고, 이후 1.0 정식 버전에 도달했습니다.

2. React 19 핵심

  • Actions — <form action={fn}> 또는 useActionState · useFormStatus 로 폼 제출의 pending/error/optimistic 상태를 하나의 API 로 묶습니다.
  • use(thenable) — 컴포넌트에서 promise 또는 context 를 직접 unwrap. Suspense 와 결합합니다.
  • ref as prop — forwardRef 가 사실상 필요 없어집니다. function X({ ref }) { ... } 가 가능합니다.
  • useOptimistic — 낙관적 UI 갱신을 위한 훅.
  • 메타데이터 통합 — <title> · <meta> · <link rel="stylesheet"> 를 컴포넌트 트리 어디서든 선언하면 React 가 head 로 끌어올립니다.

3. React Compiler 의 자동화

전통적인 React 에서 재렌더 최적화는 손으로 합니다.

const value = useMemo(() => heavy(a, b), [a, b])
const onClick = useCallback(() => setX(x + 1), [x])
const Memo = memo(Child)

Compiler 는 빌드 타임에 컴포넌트 함수를 분석해 같은 입력이면 같은 결과를 재사용하도록 메모이제이션을 자동 삽입합니다 (공식 문서 표현으로 "auto-memoization"). 결과적으로 useMemo · useCallback · memo 를 수동으로 적을 일이 줄어듭니다. 출력 코드는 react-compiler-runtime 의 c() 캐시 슬롯을 사용합니다.

전제 조건이 있습니다. React 의 규칙을 지키는 코드여야 합니다.

  • 렌더 함수는 순수 (같은 props/state 면 같은 출력).
  • 렌더 중 props·state 를 변경하지 않습니다.
  • Hooks 의 규칙 (최상단 호출, 조건부 호출 금지) 을 지킵니다.

규칙을 어기면 Compiler 는 그 컴포넌트를 건너뜁니다 (opt-out). ESLint 의 eslint-plugin-react-compiler 가 위반을 미리 잡아냅니다.

4. Compiler 가 해결하지 못하는 자리

자동 메모는 참조 안정성 (referential equality) 을 컴포넌트 경계 안에서 다룹니다. 다음은 여전히 사람이 봐야 합니다.

  • 외부 mutation 의존 — useEffect 의 deps 에 변하는 객체가 들어오는 패턴. Compiler 는 effect 본문을 감싸지 않습니다.
  • Observer · subscription — IntersectionObserver · ResizeObserver 의 콜백을 안정 참조로 유지해야 effect cleanup 이 올바릅니다. useCallback 또는 useEffectEvent 가 필요할 수 있습니다.
  • AbortController 패턴 — effect 안에서 만든 controller 의 abort 호출은 cleanup 에서 손으로 합니다.
  • 스프레드 deps — useEffect(fn, [...deps]) 처럼 동적 길이 deps 는 Compiler 가 보증할 수 없습니다.
  • 외부 라이브러리 콜백 — 라이브러리가 동일 참조를 요구할 때 (예: addEventListener/removeEventListener 짝맞춤) 는 명시적 보존이 안전합니다.

즉 Compiler 는 "수동 메모를 새로 작성할 필요" 를 줄이지만 모든 경우의 수동 메모를 대체하지 않습니다.

5. UI 라이브러리 비교

라이브러리 첫 릴리스 특징
React 2013 VDOM · Hooks · Server Components.
Vue 2014, Evan You reactive proxy · 단일 파일 컴포넌트.
Svelte 2016, Rich Harris 컴파일러가 런타임을 거의 없앤다. 5 에서 runes 도입 (2024).
Solid 2021, Ryan Carniato fine-grained reactivity. JSX 사용.
Preact 2015 React 호환의 작은 구현. 3KB 대.
Qwik 2022, Misko Hevery resumability — hydration 을 미루는 모델.

Compiler 는 "수동 메모" 라는 React 특유의 부담을 줄이려는 시도입니다. 다른 라이브러리는 같은 자리에 다른 답을 가집니다 (Vue 의 reactive · Svelte 의 컴파일 타임 추적 · Solid 의 signal).

6. 설치와 설정

pnpm add react@19 react-dom@19
pnpm add -D babel-plugin-react-compiler eslint-plugin-react-compiler
// babel.config.js
export default {
  plugins: [
    ["babel-plugin-react-compiler", { /* options */ }]
  ]
}

Next.js 는 next.config.js 의 experimental.reactCompiler 옵션, Vite 는 vite-plugin-react 의 babel.plugins 항목으로 배선합니다.

7. 19 의 폼 액션

import { useActionState } from "react"

async function submit(prev: State, form: FormData) {
  const r = await fetch("/api", { method: "POST", body: form })
  return await r.json()
}

export function NewItem() {
  const [state, action, pending] = useActionState(submit, { error: null })
  return (
    <form action={action}>
      <input name="title" />
      <button disabled={pending}>저장</button>
      {state.error && <p>{state.error}</p>}
    </form>
  )
}

8. Compiler 가 처리하는 모양

// before: 손으로 메모
const items = useMemo(() => list.filter(p), [list, p])

// after: 그냥 표현식. Compiler 가 캐시 슬롯에 넣음.
const items = list.filter(p)

9. 자주 걸리는 자리

점진 도입 — Compiler 는 파일·디렉토리 단위로 켤 수 있습니다. 큰 코드베이스에서 한 번에 켜는 것보다 단계 도입이 안전합니다.

DevTools 표시 — Compiler 가 적용된 컴포넌트는 React DevTools 에서 "Memo ✨" 같은 표시가 붙습니다. 안 붙으면 규칙 위반으로 건너뛴 것일 수 있습니다.

Strict Mode 의 이중 호출 — React 18+ Strict Mode 는 effect 를 의도적으로 두 번 실행합니다. 부작용을 가진 코드는 Compiler 와 무관하게 멱등성을 가져야 합니다.

자동 메모는 0 비용이 아닙니다 — 캐시 비교 비용 자체가 추가됩니다. 아주 작은 컴포넌트는 오히려 손해라는 경우도 보고됩니다. 일반적인 권장은 "Compiler 켜고 측정 후 판단".

수동 메모와의 공존 — 기존 useMemo · useCallback 을 강제로 제거할 필요는 없습니다. Compiler 는 그 위에 자기 캐시를 더하는 것이 아니라 그대로 둡니다.

하고픈 말

React Compiler 는 매뉴얼 메모의 부담을 크게 줄여 줍니다. 다만 모든 자리를 대체하지는 않습니다. 규칙을 지키는 코드 + 예외 케이스 (Observer · 외부 콜백 등) 의 수동 메모 유지가 가장 균형잡힌 흐름입니다.

Next

  • nextjs-app-router
  • state-philosophy

React 공식 사이트 · React Compiler 문서 · React 19 릴리스 노트 · Rules of React · eslint-plugin-react-compiler · Vue.js · SolidJS 를 참고합니다.

frontend 카테고리의 다른 글

카테고리 전체 보기 →
  • 도메인 위젯의 통일성 — 4개 도메인에 3개 위젯만 두지 마라
  • 관리자 UI — ResourceTable SSOT 패턴
  • 페이지 로딩 UX
  • 네이티브 통합 — OS 기능들
  • OCR · STT · TTS
  • SQLite — 로컬 앱의 단일 파일 DB