본문 바로가기
개발/React

React 19 업데이트 변경 점

by 그레이웅 2025. 1. 10. 23:54
반응형

 

React 19

React 19가 2024.12 월에 정식 릴리즈되었다.

어떤 점이 주요하게 변경되었을까..?

React 공식 블로그에서 주요 변경점을 확인할 수 있다. 

주요 변경점을 몇 가지 정리해 보자면 다음과 같다.

 

https://react.dev/blog/2024/12/05/react-19

1. 주요 기능

Actions: 비동기 상태 업데이트를 간소화하는 기능으로, 수동으로 대기 상태, 오류 처리, 낙관적 업데이트를 관리할 필요 없이 비동기 함수를 통해 상태를 업데이트할 수 있습니다.

  • useTransition : React19 이전에는 비동기 작업과 같이 사용하면 제약이 있어, 비동기 함수와 같이 사용하도록 개선
// Using pending state from Actions
function UpdateName({}) {
  const [name, setName] = useState("");
  const [error, setError] = useState(null);
  const [isPending, startTransition] = useTransition();

  const handleSubmit = () => {
    startTransition(async () => {
      const error = await updateName(name);
      if (error) {
        setError(error);
        return;
      } 
      redirect("/path");
    })
  };

  return (
    <div>
      <input value={name} onChange={(event) => setName(event.target.value)} />
      <button onClick={handleSubmit} disabled={isPending}>
        Update
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}

 

- 새로운 훅

  • useActionState: 비동기 작업의 상태를 관리하는 데 사용됨.
// Using <form> Actions and useActionState
function ChangeName({ name, setName }) {
  const [error, submitAction, isPending] = useActionState(
    async (previousState, formData) => {
      const error = await updateName(formData.get("name"));
      if (error) {
        return error;
      }
      redirect("/path");
      return null;
    },
    null,
  );

  return (
    <form action={submitAction}>
      <input type="text" name="name" />
      <button type="submit" disabled={isPending}>Update</button>
      {error && <p>{error}</p>}
    </form>
  );
}

 

  • useFormStatus: 폼의 상태를 추적하고 관리하는 데 도움을 준다. (추가로 하위 폼에서 상위 폼의 상태를 읽을 수 있음)
import {useFormStatus} from 'react-dom';

function DesignButton() {
  const {pending} = useFormStatus();
  return <button type="submit" disabled={pending} />
}

 

 

  • useOptimistic: 낙관적 UI 업데이트를 쉽게 구현할 수 있도록 지원. (API 요청 후 응답이 오기 전 응답이 완료된 것처럼 UI를 개선할 수 있음)
function ChangeName({currentName, onUpdateName}) {
  const [optimisticName, setOptimisticName] = useOptimistic(currentName);

  const submitAction = async formData => {
    const newName = formData.get("name");
    setOptimisticName(newName);
    const updatedName = await updateName(newName);
    onUpdateName(updatedName);
  };

  return (
    <form action={submitAction}>
      <p>Your name is: {optimisticName}</p>
      <p>
        <label>Change Name:</label>
        <input
          type="text"
          name="name"
          disabled={currentName !== optimisticName}
        />
      </p>
    </form>
  );
}

 

 

  • use : use API 를 사용하여 Promise를 읽을 수 있으며 그전 까지는 중단함.
    • React 19 이전은 Hook을 컴포넌트 최상위에서만 사용했고, 반복문, 조건문, 중첩된 함수 내에서는 사용할 수 없었다. use는 이런 제약 없이 사용할 수 있음.
import {use} from 'react';
import ThemeContext from './ThemeContext'

function Heading({children}) {
  if (children == null) {
    return null;
  }
  
  // This would not work with useContext
  // because of the early return.
  const theme = use(ThemeContext);
  return (
    <h1 style={{color: theme.color}}>
      {children}
    </h1>
  );
}

 

  • 서버 컴포넌트 및 서버 액션 지원: 서버 측에서 컴포넌트를 렌더링 하고 상태를 관리할 수 있는 기능이 추가됨.

2 개선사항

  • ref
    • 이전 하위 컴포넌트에 ref 전달 시 forwardRef를 사용해야 했지만, 이제는 사용하지 않고도 하위 컴포넌트에 ref 전달 가능
    • ref 콜백 cleanup 함수 반환 기능 추가. (cleanup함수를 이용해 ref current 속성을 유연하게 해제 가능)
function MyInput({placeholder, ref}) {
  return <input placeholder={placeholder} ref={ref} />
}

//...
<MyInput ref={ref} />

 

  • Context
    • <Context.Provider> 대신 <Context>를 Provider로 직접 사용 가능
<input
  ref={(ref) => {
    // ref created

    // NEW: return a cleanup function to reset
    // the ref when element is removed from DOM.
    return () => {
      // ref cleanup
    };
  }}
/>

 

 

  • Hydration 불일치에 대한 에러 개선
    • react-dom의 Hytdration 에러 불일치 리포팅 및 진단을 명확하게 하여, 빠른 문제 파악 가능
  • 메타 데이터 지원
    • 아래와 같이 코드를 작성시, 메타데이터가 자동으로 <head>로 끌어올려짐
function BlogPost({post}) {
  return (
    <article>
      <h1>{post.title}</h1>
      <title>{post.title}</title>
      <meta name="author" content="Josh" />
      <link rel="author" href="https://twitter.com/joshcstory/" />
      <meta name="keywords" content={post.keywords} />
      <p>
        Eee equals em-see-squared...
      </p>
    </article>
  );
}

 

  • Stylesheet precedence 속성
    • precedence 속성으로 스타일 시트의 삽입 순서를 DOM 내에서 관리가 가능함. 외부 스타일 시트 로드 후 해당 설정에 맞게 콘텐츠 표시 가능
    • 예시
      • bar 는 foo 보다 우선적으로 로드되고 DOM 상에도 앞에 위치하게 됨.
      • baz는 foo와 동일한 우선순위를 가지므로 foo와 bar 사이에 추가된다.
function ComponentOne() {
  return (
    <Suspense fallback="loading...">
      <link rel="stylesheet" href="foo" precedence="default" />
      <link rel="stylesheet" href="bar" precedence="high" />
      <article class="foo-class bar-class">
        {...}
      </article>
    </Suspense>
  )
}

function ComponentTwo() {
  return (
    <div>
      <p>{...}</p>
      <link rel="stylesheet" href="baz" precedence="default" />  <-- will be inserted between foo & bar
    </div>
  )
}

 

  • Resouce Preloading
    • 브라우저 리소스를 사전 로드하기 위한 API 추가
import { prefetchDNS, preconnect, preload, preinit } from 'react-dom'
function MyComponent() {
  preinit('https://.../path/to/some/script.js', {as: 'script' }) // loads and executes this script eagerly
  preload('https://.../path/to/font.woff', { as: 'font' }) // preloads this font
  preload('https://.../path/to/stylesheet.css', { as: 'style' }) // preloads this stylesheet
  prefetchDNS('https://...') // when you may not actually request anything from this host
  preconnect('https://...') // when you will request something but aren't sure what
}

<!-- the above would result in the following DOM/HTML -->
<html>
  <head>
    <!-- links/scripts are prioritized by their utility to early loading, not call order -->
    <link rel="prefetch-dns" href="https://...">
    <link rel="preconnect" href="https://...">
    <link rel="preload" as="font" href="https://.../path/to/font.woff">
    <link rel="preload" as="style" href="https://.../path/to/stylesheet.css">
    <script async="" src="https://.../path/to/some/script.js"></script>
  </head>
  <body>
    ...
  </body>
</html>

 

 

React 19 Next 15 업데이트 방법

1.3 React 19로 업데이트 방법

https://react.dev/blog/2024/04/25/react-19-upgrade-guide

 

 

React 19 설치

npm install --save-exact react@^19.0.0 react-dom@^19.0.0
yarn add react@^19.0.0 react-dom@^19.0.0

 

 

typescript

npm install --save-exact @types/react@^19.0.0 @types/react-dom@^19.0.0
yarn add --exact @types/react@^19.0.0 @types/react-dom@^19.0.0

 

 

마이그레이션 팁, React 18.x버전이면 해당 버전을 유지한 채 타 서드파트 라이브러리들을 먼저 업데이트 후 react, react-dom을 19 버전으로 올리면서 확인한다. 그리고 충돌이 나면 다시 18 버전대로 돌아가서 충돌난 라이브러리등을 업데이트한다.

 

 

기존 프로젝트에 React 19 버전을 적용해 보려고 업데이트를 해보니, 기본 react, react-dom19는 설치가 잘 되었지만, @type/react를 설치하면서 타 라이브러리 간의 호환성 충돌이 많이 일어났다.

codemod를 사용해보는것도 또하나의 방법이다.

https://react.dev/blog/2024/04/25/react-19-upgrade-guide#run-all-react-19-codemods

 

아직 정식 출시한지 얼마 되지 않아 라이브러리들이 React 19 버전과 호환되는지도 잘 확인해봐야한다.

많이 사용되고 업데이트되는 라이브러리들은 React 19 버전을 빠르게 호환시켜 최신버전으로 업데이트하여서 웬만한 것들은 호환이 되지만, 호환성문제가 해결되지 않은 라이브러리들도 있을 것이다.

 

 

 

빠르게 새로운 기술을 도입하는 것도 좋지만, 안정적인 버전을 사용하고 기술지원이 다 된 이후에 도입하는 것도 하나의 방법이다.

 

반응형

댓글