React 19 완벽 가이드 2편 - Document Metadata Support, use Hook, Ref Callback Clenup, useDeferredValue Initial Value, 하이드레이션 오류 디프, ref as a Prop 등

안녕하세요?

React 19의 배포가 얼마 안 남은 상황에서 Kent C. Dodds 님이 제공해 주신 React Cheat Sheet에 대해 공부하려고 준비한 React 19 완벽 가이드 2편입니다.

먼저, Kent C. Dodds님이 제공해주시는 React 19 치트시트는 아래 링크에서 받으실 수 있는데요.

PDF 다운로드

지금부터 2편 시작하겠습니다.

목차


Document Metadata Support, Stylesheets with Precedence, Resource Preloading APIs, Custom Element Support

1. Document Metadata Support (문서 메타데이터 지원)

Automatically hoists <title>, <meta>, and <link> tags to the <head>.

<title>My Blog</title>
<meta name="author" content="Kent" />

웹 페이지의 메타데이터는 페이지를 설명하거나 SEO(검색엔진 최적화) 등의 목적으로 사용됩니다.

일반적으로 <title>, <meta> 태그를 <head> 안에 넣어 페이지의 제목, 저자 정보, 설명 등을 정의합니다.

React 19에서는 이러한 메타데이터를 자동으로 <head>에 올려주는 기능이 추가되었습니다.

왜 중요한가요?

기존의 React 애플리케이션에서는 <head> 태그에 메타 정보를 수동으로 넣어야 했습니다.

하지만 React 19에서는 이러한 작업을 더 쉽게 처리할 수 있습니다.

아래와 같이 메타데이터를 추가하면, 자동으로 해당 정보가 페이지의 <head>에 삽입됩니다.

<title>My Blog</title>
<meta name="author" content="Kent" />

2. Stylesheets with Precedence (우선순위가 있는 스타일시트)

Support for inserting stylesheets with precedence in concurrent rendering environments.

<link rel="stylesheet" href="foo.css" precedence="default" />
{/* this will get placed "higher" in the document */}
<link rel="stylesheet" href="bar.css" precedence="high" />

React 19에서는 스타일시트를 삽입할 때 우선순위를 지정할 수 있습니다.

이 기능은 동시 렌더링 환경에서 스타일시트의 적용 순서를 조정하는 데 사용됩니다.

우선순위가 높은 스타일시트는 문서 내에서 더 먼저 적용되도록 설정할 수 있습니다.

사용 방법

  • <link> 태그에 precedence 속성을 추가하여 스타일시트의 우선순위를 설정합니다.
  • 우선순위가 높은 스타일시트가 더 먼저 적용되며, 스타일 충돌을 방지할 수 있습니다.
<link rel="stylesheet" href="foo.css" precedence="default" />
<link rel="stylesheet" href="bar.css" precedence="high" />

왜 중요한가요?

다양한 스타일시트가 사용되는 복잡한 애플리케이션에서 스타일의 우선순위를 관리하는 것은 중요합니다.

특히 동시 렌더링에서 스타일이 잘못 적용되는 문제를 예방할 수 있습니다.

3. Resource Preloading APIs (리소스 프리로딩 API)

Preload resources like fonts, scripts, and styles to optimize performance.

preload('https://example.com/font.woff', { as: 'font' })
preconnect('https://example.com')

리소스를 미리 로딩하여 성능을 최적화하는 API입니다.

브라우저가 웹 페이지를 로딩할 때 중요한 리소스(폰트, 스크립트, 스타일)를 미리 가져올 수 있도록 하여 페이지 로딩 시간을 단축할 수 있습니다.

React 19에서는 이러한 리소스를 더욱 쉽게 미리 로딩할 수 있도록 지원합니다.

사용 예시

  • preload: 웹 폰트나 중요한 리소스를 페이지 로딩 전에 미리 로딩합니다.
  • preconnect: 특정 리소스를 가져오기 전에 해당 서버와의 연결을 미리 설정하여 리소스 요청 시간을 단축합니다.
preload('https://example.com/font.woff', { as: 'font' })
preconnect('https://example.com')

왜 중요한가요?

대규모 애플리케이션에서는 리소스 로딩 시간에 따라 사용자 경험이 크게 달라질 수 있습니다.

리소스를 미리 로딩하여 성능을 최적화하면 페이지 로딩 시간을 줄여 사용자 만족도를 높일 수 있습니다.

4. Custom Element Support (커스텀 엘리먼트 지원)

React now fully supports custom elements and handles properties/attributes consistently.

<custom-element prop1="value" />

React 19는 커스텀 엘리먼트를 완벽하게 지원합니다.

커스텀 엘리먼트는 HTML의 표준 태그가 아니라 개발자가 직접 정의한 태그로, 웹 컴포넌트를 만들 때 자주 사용됩니다.

이제 React에서 커스텀 엘리먼트의 속성 및 특성을 일관되게 처리할 수 있습니다.

사용 예시

React 19에서는 커스텀 엘리먼트를 쉽게 정의하고 사용할 수 있으며, 속성과 특성을 HTML 태그처럼 다룰 수 있습니다.

<custom-element prop1="value" />

왜 중요한가요?

커스텀 엘리먼트를 사용하면 애플리케이션에서 재사용 가능한 웹 컴포넌트를 만들 수 있습니다.

이 기능을 통해 React와 커스텀 엘리먼트를 더 쉽게 통합할 수 있게 되어 개발 유연성이 높아집니다.

요약

React 19에서 새롭게 도입된 이 기능들은 웹 애플리케이션의 성능과 개발 편의성을 크게 향상시키는 요소들입니다.

  1. Document Metadata Support: 메타데이터를 자동으로 처리하여 SEO 및 페이지 설명을 더 쉽게 관리할 수 있습니다.
  2. Stylesheets with Precedence: 동시 렌더링 환경에서 스타일 적용 순서를 쉽게 조정할 수 있습니다.
  3. Resource Preloading APIs: 중요한 리소스를 미리 로딩하여 성능을 최적화합니다.
  4. Custom Element Support: 커스텀 엘리먼트를 더욱 쉽게 다룰 수 있어 개발 유연성이 증가합니다.

이 기능들을 잘 활용하면 React 19에서 더욱 효율적이고 최적화된 애플리케이션을 개발할 수 있을 것입니다.


Better Error Reporting, use Hook

1. 더 나은 에러 보고 (Better Error Reporting)

This feature enhances error handling by de-duplicating errors and introducing two new handlers for root components: onCaughtError and onUncaughtError. Here’s the code from the image:

createRoot(container, {
  onCaughtError: (error, errorInfo) => {
    console.error(
      'Caught error',
      error,
      errorInfo.componentStack
    );
  },
  onUncaughtError: (error, errorInfo) => {
    console.error(
      'Uncaught error',
      error,
      errorInfo.componentStack
    );
  },
});
  • onCaughtError handles errors that occur in the root component.
  • onUncaughtError catches errors that aren't handled elsewhere.

애플리케이션 개발 시 에러는 불가피하게 발생할 수 있습니다.

React 19에서는 에러 처리를 더욱 효과적으로 관리할 수 있는 기능이 추가되었습니다.

에러를 중복으로 보고하지 않고, 루트 컴포넌트에서 에러를 핸들링할 수 있는 두 가지 새로운 핸들러인 onCaughtErroronUncaughtError가 도입되었습니다.

주요 기능:
  • onCaughtError: 루트 컴포넌트 내에서 발생한 에러를 처리합니다.
  • onUncaughtError: 다른 곳에서 처리되지 않은 에러를 잡아냅니다.
예제 코드:
createRoot(container, {
  onCaughtError: (error, errorInfo) => {
    console.error(
      'Caught error',
      error,
      errorInfo.componentStack
    );
  },
  onUncaughtError: (error, errorInfo) => {
    console.error(
      'Uncaught error',
      error,
      errorInfo.componentStack
    );
  },
});
설명:
  • 에러 중복 제거: 동일한 에러가 여러 번 보고되는 것을 방지하여 로그를 깔끔하게 유지할 수 있습니다.
  • 구체적인 에러 핸들링: onCaughtError는 컴포넌트 내부에서 발생한 에러를 잡아내어 특정 로직을 추가로 실행할 수 있게 합니다. 반면, onUncaughtError는 예상치 못한 에러를 전체 애플리케이션 수준에서 포착하여 보다 안전한 에러 관리를 가능하게 합니다.

2. use

This new hook reads resources, such as promises or context, during render, allowing for conditional usage. Here's the code from the image:

const comments = use(commentsPromise);
const theme = use(ThemeContext);

This hook can streamline the process of fetching data or utilizing context during render without the need for explicit useEffect calls or async handling.

React 19에서는 새로운 use 훅이 도입되어, 렌더링 중에 프로미스나 컨텍스트와 같은 리소스를 직접 읽어올 수 있게 되었습니다.

이를 통해 데이터 페칭이나 컨텍스트 활용 시 useEffect 호출이나 비동기 처리를 명시적으로 할 필요 없이 간편하게 사용할 수 있습니다.

주요 기능:
  • 리소스 읽기: 프로미스나 컨텍스트와 같은 리소스를 렌더링 중에 직접 읽어들일 수 있습니다.
  • 조건부 사용: 조건에 따라 훅을 사용할 수 있어 코드의 유연성을 높입니다.
예제 코드:
const comments = use(commentsPromise);
const theme = use(ThemeContext);
설명:
  • 데이터 페칭 간소화: 기존에는 데이터 페칭을 위해 useEffect와 상태 관리를 사용해야 했지만, use 훅을 통해 더 직관적으로 데이터를 가져올 수 있습니다.
  • 컨텍스트 활용 편의성: use 훅을 사용하면 컨텍스트를 더욱 쉽게 활용할 수 있어, 컴포넌트 간의 데이터 공유가 용이해집니다.
  • 코드 가독성 향상: 비동기 처리나 컨텍스트 활용 시 코드가 더욱 명확하고 간결해져 유지보수가 쉬워집니다.
활용 예시:
function CommentsSection() {
  const comments = use(fetchComments());
  const theme = use(ThemeContext);

  return (
    <div style={{ background: theme.background, color: theme.color }}>
      {comments.map(comment => (
        <Comment key={comment.id} data={comment} />
      ))}
    </div>
  );
}

Ref Callback Cleanup, Streamlined Context API, useDeferredValue Initial Value, Hydration Error Diffs, ref as a Prop

Ref 콜백 클린업 (Ref Callback Cleanup)

Ref callbacks can now return a cleanup function, making it easier to manage resources tied to a ref. Here’s the code from the image:

<input ref={(ref) => () => console.log('cleanup')} />

This allows you to handle any necessary cleanup when a ref is unmounted.

React 19에서는 Ref 콜백이 클린업 함수를 반환할 수 있게 되어, Ref에 연결된 리소스를 더 쉽게 관리할 수 있습니다.

이를 통해 Ref가 언마운트될 때 필요한 정리 작업을 간편하게 수행할 수 있습니다.

주요 기능:

  • 클린업 함수 반환: Ref 콜백 내에서 클린업 함수를 반환하여 리소스 정리를 자동으로 처리할 수 있습니다.

예제 코드:

<input ref={(ref) => () => console.log('cleanup')} />

설명:

  • 리소스 관리 용이성: Ref가 언마운트될 때 자동으로 클린업 함수가 호출되어, 예를 들어 이벤트 리스너 제거나 타이머 정리 등을 손쉽게 처리할 수 있습니다.
  • 메모리 누수 방지: 리소스 정리가 자동으로 이루어지므로 메모리 누수를 방지할 수 있습니다.

활용 예시:

function CustomInput() {
  const inputRef = React.useRef();

  React.useEffect(() => {
    const handleFocus = () => console.log('Input focused');
    inputRef.current.addEventListener('focus', handleFocus);
    
    return () => {
      inputRef.current.removeEventListener('focus', handleFocus);
      console.log('cleanup');
    };
  }, []);
  
  return <input ref={(ref) => { inputRef.current = ref; return () => console.log('cleanup'); }} />;
}

간소화된 컨텍스트 API (Streamlined Context API)

Instead of using <Context.Provider>, you can now use <Context> directly. The example from the image:

<LanguageContext value="pl-PL">{children}</LanguageContext>

This simplifies context management by reducing verbosity.

React 19에서는 <Context.Provider>를 사용하는 대신 <Context>를 직접 사용할 수 있게 되어, 컨텍스트 관리를 더욱 간편하게 할 수 있습니다.

이를 통해 코드의 중복을 줄이고 가독성을 향상시킬 수 있습니다.

주요 기능:

  • 직접 사용 가능한 컨텍스트: <Context>를 직접 사용하여 컨텍스트 관리를 단순화합니다.

예제 코드:

<LanguageContext value="pl-PL">{children}</LanguageContext>

설명:

  • 코드 간결화: <Context.Provider>를 생략하고 <Context> 자체를 사용할 수 있어, 코드가 더욱 간결해집니다.
  • 가독성 향상: 컨텍스트 설정이 직관적으로 이루어져, 코드의 가독성이 향상됩니다.

활용 예시:

const LanguageContext = React.createContext('en-US');

function App() {
  return (
    <LanguageContext value="pl-PL">
      <Header />
      <MainContent />
    </LanguageContext>
  );
}

useDeferredValue 초기값 설정 (useDeferredValue Initial Value)

The useDeferredValue hook now supports setting an initial value. Here's how it's used:

const deferredValue = useDeferredValue(value, 'initial');

This feature enhances performance by deferring updates while allowing you to provide a default initial value.

useDeferredValue 훅은 이제 초기값을 설정할 수 있게 되어, 성능을 향상시키면서도 기본값을 제공할 수 있습니다.

이를 통해 업데이트를 지연시키면서도 사용자 경험을 개선할 수 있습니다.

주요 기능:

  • 초기값 설정: useDeferredValue 훅에 초기값을 설정하여, 지연된 업데이트에서도 기본값이 적용되도록 합니다.
  • 성능 향상: 업데이트를 지연시켜 렌더링 성능을 최적화합니다.

예제 코드:

const deferredValue = useDeferredValue(value, 'initial');

설명:

  • 성능 최적화: 대규모 데이터나 복잡한 계산이 필요한 경우, useDeferredValue를 사용하여 렌더링 성능을 향상시킬 수 있습니다.
  • 유연한 사용: 초기값을 설정함으로써, 비동기 데이터 로딩 시에도 사용자에게 일관된 경험을 제공할 수 있습니다.
  • 코드 가독성 향상: 성능 최적화와 함께 코드의 명확성과 간결성을 유지할 수 있습니다.

활용 예시:

function SearchResults({ query }) {
  const deferredQuery = useDeferredValue(query, 'searching...');
  
  const results = use(searchResultsPromise(deferredQuery));
  
  return (
    <div>
      <h2>Results for: {deferredQuery}</h2>
      <ul>
        {results.map(result => (
          <li key={result.id}>{result.name}</li>
        ))}
      </ul>
    </div>
  );
}

하이드레이션 오류 디프 (Hydration Error Diffs)

When hydration errors occur (such as mismatches between server and client content), React now provides detailed diffs to make troubleshooting easier. The error diff looks like this:

Uncaught Error: Hydration failed
  <App>
    <span>
    +  Client
    -  Server

This helps identify where the mismatch is between server-rendered and client-rendered content.

서버와 클라이언트 간의 콘텐츠 불일치로 인해 발생하는 하이드레이션 오류 시, React 19에서는 상세한 디프(diff)를 제공하여 문제 해결을 용이하게 합니다.

이를 통해 개발자들은 어디에서 불일치가 발생했는지 정확히 파악할 수 있습니다.

주요 기능:

  • 상세한 오류 디프 제공: 하이드레이션 오류 발생 시, 서버와 클라이언트 간의 차이를 명확하게 보여줍니다.

예제 오류 메시지:

Uncaught Error: Hydration failed
  <App>
    <span>
    +  Client
    -  Server

설명:

  • 문제 파악 용이성: 오류 메시지를 통해 서버와 클라이언트 간의 구체적인 불일치 지점을 확인할 수 있습니다.
  • 빠른 디버깅: 상세한 디프는 개발자가 빠르게 문제를 식별하고 수정할 수 있게 도와줍니다.

활용 예시:

function App() {
  return (
    <div>
      <span>Server

Content</span>
      <span>Client Content</span>
    </div>
  );
}

만약 서버와 클라이언트에서 <span>의 내용이 다르면, 위와 같은 디프 메시지가 나타나게 됩니다.


ref를 프로퍼티로 전달 (Ref as a Prop)

You can now pass refs directly as props to function components. For example:

<MyInput ref={inputRef} />

This allows for more flexibility in handling refs within function components.

React 19에서는 함수형 컴포넌트에 ref를 직접 프로퍼티로 전달할 수 있게 되어, Ref 사용이 더욱 유연해졌습니다.

이를 통해 함수형 컴포넌트 내에서 Ref를 쉽게 관리하고 사용할 수 있습니다.

주요 기능:

  • 프로퍼티로 Ref 전달: 함수형 컴포넌트에 ref를 직접 전달하여, 내부에서 Ref를 활용할 수 있습니다.

예제 코드:

<MyInput ref={inputRef} />

설명:

  • 유연한 Ref 관리: 함수형 컴포넌트 내에서 Ref를 직접 사용할 수 있어, 클래스형 컴포넌트와 유사한 방식으로 Ref를 관리할 수 있습니다.
  • 코드 일관성: 클래스형과 함수형 컴포넌트 간의 코드 일관성을 유지하면서 Ref를 사용할 수 있습니다.

활용 예시:

const inputRef = React.createRef();

function MyInput(props, ref) {
  return <input ref={ref} {...props} />;
}

const ForwardedInput = React.forwardRef(MyInput);

function ParentComponent() {
  return (
    <div>
      <ForwardedInput ref={inputRef} />
      <button onClick={() => inputRef.current.focus()}>
        Focus Input
      </button>
    </div>
  );
}

결론

React 19의 새로운 기능들은 개발자들에게 더욱 강력하고 유연한 도구들을 제공하며, 애플리케이션의 안정성과 성능을 크게 향상시킵니다.

더 나은 에러 보고, use, Ref 콜백 클린업, 간소화된 컨텍스트 API, useDeferredValue 초기값 설정, 하이드레이션 오류 디프, 그리고 ref를 프로퍼티로 전달하는 기능들은 모두 개발 과정을 간소화하고, 코드의 가독성과 유지보수성을 높이는 데 큰 도움이 될 것입니다.

React 19의 최신 기능들을 적극적으로 활용하여 더욱 효율적이고 안정적인 애플리케이션을 개발해보시기 바랍니다.

React 19의 새로운 기능들을 통해 더욱 생산적이고 안정적인 개발 경험을 누리시길 바랍니다.

2편 끝.