React 19.3
개요
이 스킬은 React 19.3에서 자주 실수하기 쉬운 규칙들을 담고 있습니다: 존재해서는 안 되는 Effect, 의존성 함정, Actions와 Transitions, Server Components 경계, React Compiler 도입, 그리고 19에서 제거되거나 비권장된 API들입니다. 모든 주장은 해당 페이지 URL을 함께 제시합니다.
지원 버전
React 19.3, react.dev에서 문서화된 릴리스. 이전 메이저 버전은 18.react.dev 및 이전 사이트에서 확인할 수 있습니다. https://react.dev/versions
퀵 스타트를 읽은 후, 작업에 해당하는 참조 파일 하나를 열어 사용하세요.
퀵 스타트
- Effect는 React가 제어하지 않는 시스템과 동기화할 때만 사용하세요. 렌더링 중에 값을 파생하고,
key로 상태를 재설정하며, 사용자에 의해 발생된 로직은 이벤트 핸들러에서 실행하세요. https://react.dev/learn/you-might-not-need-an-effect - 의존성은 코드를 따라갑니다:
react-hooks/exhaustive-deps를 절대 무시하지 마세요. 하나를 제거하려면 객체와 함수를 Effect 안으로 이동시키거나, 업데이터를 사용하거나, Effect Event에서 값을 읽어오세요. https://react.dev/learn/removing-effect-dependencies
const onConnected = useEffectEvent(() => {
showNotification('Connected!', theme);
});
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.on('connected', () => { onConnected(); });
connection.connect();
return () => connection.disconnect();
}, [roomId]);
https://react.dev/learn/separating-events-from-effects
- Effect는 setup, cleanup, setup 과정을 반드시 견뎌야 합니다: Strict Mode는 개발 환경에서 이를 실행합니다. cleanup을 올바르게 수정하고, ref 가드로 두 번째 실행을 숨기지 마세요. https://react.dev/learn/synchronizing-with-effects
ref는 함수 컴포넌트의 prop입니다. Provider로<Context value={x}>를 렌더링하세요. ref 콜백은 cleanup 함수를 반환할 수 있습니다. https://react.dev/reference/react/useRef 및 https://react.dev/reference/react/createContext 및 https://react.dev/reference/react-dom/components/commonstartTransition내부의await이후에 상태를 설정하는 것은 Transition이 아닙니다: 다른startTransition으로 감싸세요. https://react.dev/reference/react/useTransition<form action>을 사용할 때,useActionState리듀서는(prevState, formData)를 받습니다. Action(<form action>또는startTransition) 내에서dispatchAction을 호출하세요. https://react.dev/reference/react/useActionStateuseFormStatus는 부모<form>만 읽습니다: 자식 컴포넌트에서 호출하세요. https://react.dev/reference/react-dom/hooks/useFormStatususe(promise)는 캐시된 Promise가 필요합니다: 렌더링 중에 생성된 Promise는 매 렌더링마다 다시 생성됩니다.use를try/catch로 감싸지 마세요: Error Boundary를 사용하세요. https://react.dev/reference/react/use'use server'는 Server Functions를 표시하며, 지시어가 없는 Server Components는 표시하지 않습니다. 모든 Server Function 인자의 유효성을 검증하고 권한을 확인하세요. https://react.dev/reference/rsc/server-components 및 https://react.dev/reference/rsc/use-server- 브라우저 전용 컴포넌트:
typeof window나 mounted 플래그 대신,<Suspense>경계 아래에서react-dom의browser를 사용하는use(browser())를 사용하세요. https://react.dev/reference/react-dom/browser - React Compiler를 사용할 때는 일반 코드를 작성하고 Effect 의존성과 같은 정밀한 제어가 필요한 경우에만
useMemo또는useCallback을 유지하세요. 기존 메모이제이션은 그대로 두세요. https://react.dev/learn/react-compiler/introduction eslint-plugin-react-hooksrecommended로 린트하세요. 여기에 컴파일러 규칙이 포함되어 있으므로eslint-plugin-react-compiler는 제거하세요. https://react.dev/blog/2025/10/07/react-compiler-1- 컴포넌트는 모듈 레벨에서 정의하고, 다른 컴포넌트 내부에서는 절대 정의하지 마세요. https://react.dev/reference/eslint-plugin-react-hooks/lints/static-components
&&왼쪽에 숫자를 절대 두지 마세요:count && <p/>는0을 렌더링합니다. https://react.dev/learn/conditional-rendering
참조 파일
| 파일 | 다음을 위해 열기 |
|---|---|
| references/state.md | useState, 업데이터, 렌더링 중 설정, useReducer, 불변 업데이트, 상태 구조, key 리셋 |
| references/refs-and-context.md | useRef, ref 콜백, ref prop, useImperativeHandle, context, useId, useSyncExternalStore |
| references/effects.md | Effect를 사용하지 말아야 할 때, useEffect 타이밍, Strict Mode 정리, 데이터 가져오기, useLayoutEffect, useInsertionEffect |
| references/effect-dependencies.md | 의존성 제거, useEffectEvent, 커스텀 Hook, additionalEffectHooks |
| references/memoization.md | useMemo, useCallback, memo, 컴파일러 유무에 따른 사용 |
| references/react-compiler.md | 설치, 옵션, 지시어, 점진적 도입, 컴파일러 디버깅 |
| references/rules-and-lints.md | React 규칙, Hook 규칙, eslint-plugin-react-hooks 규칙, Strict Mode |
| references/components-and-tooling.md | Key, 조건부 렌더링, Fragment ref, Profiler, act, TypeScript, DevTools |
| references/transitions-and-suspense.md | useTransition, startTransition, useDeferredValue, use, lazy, <Suspense> |
| references/view-transitions-and-activity.md | <ViewTransition>, addTransitionType, <Activity> |
| references/actions-and-optimistic.md | useActionState, useOptimistic, useFormStatus, <form action> |
| references/form-elements-and-events.md | 제어 입력, <select>, <textarea>, 공통 prop, 이벤트, 커스텀 엘리먼트 |
| references/server-components.md | Server Components, 'use client', 직렬화 가능한 prop, cache, cacheSignal, taint |
| references/server-functions.md | 'use server', Server Functions 호출, permalink, 보안 |
| references/client-roots-and-hydration.md | createRoot, hydrateRoot, 불일치, 오류 보고, Error Boundary |
| references/server-rendering.md | renderToPipeableStream, renderToReadableStream, 상태 코드, prerender, resume |
| references/dom-apis-and-resources.md | browser, createPortal, flushSync, preload, preinit, <img>, <link>, <script>, <title> |
| references/upgrading-to-19.md | 업그레이드 단계, codemod, 제거 및 비권장 API, TypeScript 변경 사항, 19.2 및 19.3 |
| references/legacy-apis.md | Children, cloneElement, 클래스 컴포넌트, forwardRef, PureComponent |
오래된 패턴
| 오래된 사용법 | 대체 방법 | 출처 |
|---|---|---|
forwardRef((props, ref) => ...) | function MyInput({ ref, ...props }) | https://react.dev/reference/react/forwardRef |
<Context.Provider value={x}> | <Context value={x}> | https://react.dev/reference/react/createContext |
<Context.Consumer> 렌더 prop | useContext(Context) 또는 use(Context) | https://react.dev/reference/react/createContext |
ReactDOM.useFormState | react에서 useActionState | https://react.dev/blog/2024/12/05/react-19 |
ReactDOM.render, ReactDOM.hydrate | createRoot(el).render(), hydrateRoot | https://react.dev/reference/react-dom |
unmountComponentAtNode | root.unmount() | https://react.dev/reference/react-dom |
findDOMNode | DOM ref | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
문자열 ref, this.refs | ref 콜백 또는 createRef | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
contextTypes, getChildContext | createContext, static contextType | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
element.ref | element.props.ref | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
react-test-renderer, Shallow 렌더링 | Testing Library | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
타입의 전역 JSX 네임스페이스 | declare module "react" { namespace JSX {} } | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
| UMD 빌드 스크립트 태그 | esm.sh와 같은 ESM CDN | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
propTypes | TypeScript | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
함수 컴포넌트의 defaultProps | ES 기본 매개변수 | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
import { act } from 'react-dom/test-utils' | import { act } from 'react' | https://react.dev/blog/2024/04/25/react-19-upgrade-guide |
동기 act(() => ...) | await act(async () => ...) | https://react.dev/reference/react/act |
null 호출에 의존하는 ref 콜백 | cleanup 함수 반환 | https://react.dev/reference/react-dom/components/common |
SSR용 renderToString | renderToPipeableStream 또는 renderToReadableStream | https://react.dev/reference/react-dom/server/renderToString |
renderToNodeStream, renderToStaticNodeStream | react-dom/server 스트리밍 API | https://react.dev/reference/react-dom |
| 서버에서 throw하여 SSR 건너뛰기 | use(browser()) | https://react.dev/reference/react/Suspense |
Effect에서 설정된 isClient 상태, 렌더링 중 typeof window | <Suspense> 아래의 use(browser()) | https://react.dev/reference/react-dom/browser |
eslint-plugin-react-compiler | eslint-plugin-react-hooks | https://react.dev/blog/2025/10/07/react-compiler-1 |
"use no forget" | "use no memo" | https://react.dev/reference/react-compiler/directives/use-no-memo |
@vitejs/plugin-react 6의 react({ babel: { plugins: [...] } }) | @rolldown/plugin-babel과 함께 reactCompilerPreset 사용 | https://react.dev/learn/react-compiler/installation |
componentWillMount, componentWillReceiveProps, componentWillUpdate | UNSAFE_ 이름 또는 해당 페이지의 대안 | https://react.dev/reference/react/Component |