[번역] React 19에서 새롭게 등장하는 클라이언트 사이드 훅

Saetbyeol·2024년 3월 17일
64

translations.zip

목록 보기
12/23
post-thumbnail

이 글은 원저자의 허락을 맡아 <New client-side hooks coming to React 19>을 한국어로 번역한 글입니다.

일반적인 생각과는 달리, React 코어 팀은 React 서버 컴포넌트와 Next.js에만 집중하는 건 아닙니다. 새로운 클라이언트 사이드 훅은 다음 메이저 버전인 React 19에서 제공될 예정입니다. 이 훅은 데이터 페칭이라는 React의 두 가지 주요 문제점에 초점을 맞추고 있습니다. 새롭게 등장할 훅은 SPA 개발자를 포함한 모든 React 개발자의 생산성을 향상시킬 것입니다.

각설하고 새로운 훅에 대해 알아보겠습니다.

주의: 이 훅들은 React 카나리 및 실험 버전에서만 사용 가능합니다. React 19에서 추가될 예정이지만 최종 릴리즈 전에 API가 변경될 수 있습니다.

use(Promise)

이 새로운 훅은 클라이언트에서 "중단(suspending)"하는 공식 API입니다. 프로미스를 전달하면 해당 프로미스가 해결될 때까지 React는 중단됩니다. React use 문서에서 가져온 기본 구문은 다음과 같습니다.

import { use } from 'react';

function MessageComponent({ messagePromise }) {
  const message = use(messagePromise);
  // ...
}

좋은 소식은 이 훅을 데이터 페칭에 사용할 수 있다는 것입니다. 다음은 마운트 및 버튼 클릭 시 데이터를 가져오는 구체적인 예제입니다. 이 코드는 useEffect를 전혀 사용하지 않습니다.

코드 예제 링크

<Suspense> 문서에 있던 이 경고를 기억하시나요?

강제성이 있는 프레임워크를 사용하지 않고는 아직 suspense을 지원하는 데이터 페칭이 지원되지 않습니다.

그러나 React 19에서는 더 이상 그렇지 않습니다.

새로운 use 훅에는 숨겨진 기능이 있습니다. 다른 React 훅과 달리 useif와 같은 루프 및 조건문 내에서 호출될 수 있다는 점입니다.

우리가 이제 클라이언트 사이드에서 데이터를 가져오기 위해 TanStack Query와 같은 서드파티 라이브러리를 더 이상 필요로 하지 않다는 것일까요? 글쎄요, Tanstack Query는 Promise를 해결하는 것 이상의 일을 수행하고 있기 때문에 아직은 좀 더 지켜봐야 할 것 같습니다.

어쨌든 이는 올바른 방향으로 나아가는 큰 발걸음이며, REST 또는 GraphQL API를 기반으로 SPA를 더 쉽게 구축할 수 있을 것입니다. 저는 이 새로운 훅이 아주 반갑습니다!

React 문서에서 use(Promise)에 대해 더 자세히 알아보세요.

use(Context)

동일한 use 훅을 사용하여 React 컨텍스트를 읽을 수 있습니다. if와 같은 조건문과 루프 내에서 호출할 수 있다는 점을 제외하면 useContext와 완전히 동일합니다.

import { use } from 'react';

function HorizontalRule({ show }) {
  if (show) {
    const theme = use(ThemeContext);
    return <hr className={theme} />;
  }
  return false;
}

루프나 조건문에서 컨텍스트를 읽는 유일한 방법은 컴포넌트를 두 개로 나누는 것이었기 때문에, 특정 경우에서는 컴포넌트 계층 구조가 더 단순해집니다.

컨텍스트가 변경되었더라도 조건에 따라 컴포넌트의 리렌더링을 생략할 수 있으므로 성능 측면에서도 큰 발전입니다.

React 문서에서 use(Context)에 대해 더 자세히 알아보세요.

Form Action

이 기능을 사용하면 <form>action 프로퍼티에 함수를 전달할 수 있습니다. React는 폼이 제출될 때 이 함수를 호출합니다.

<form action={handleSubmit} />

React 18에서 <form action> 속성을 추가하면 다음과 같은 경고가 발생합니다.

경고: <form> 태그의 action 프로퍼티에 대한 잘못된 값입니다. 요소에서 값을 제거하거나, 해당 요소에 문자열 또는 숫자 값을 전달하여 DOM에 유지하세요.

React 19에서는 해당 경고가 발생하지 않으며, 이제 다음과 같이 폼을 작성할 수 있습니다.

코드 예제 링크

addToCart 함수는 서버 액션(Server Action)이 아닙니다. 클라이언트 사이드에서 호출되며 비동기 함수가 될 수 있습니다.

이는 React에서 검색 폼과 같은 AJAX 폼 처리를 크게 간소화할 것입니다. 그러나 이것만으로는 React Hook Form과 같은 서드파티 라이브러리를 완전히 대체할 순 없을 것입니다. React Hook Form은 폼 제출뿐만 아니라 유효성 검사, 부수 효과 등 다양한 작업을 처리하기 때문입니다.

: 위의 예제에서 몇 가지 사용성 문제를 발견할 수 있습니다.(제출 중에 제출 버튼이 비활성화되지 않음, 확인 메시지 미노출, 장바구니의 업데이트 지연). 다행히도 이러한 경우에 도움이 될 만한 훅이 더 많이 나오고 있습니다. 계속 읽어보세요!

React 문서에서 <form action> 프로퍼티에 대해 더 자세히 읽을 수 있습니다.

useFormState

이 새로운 훅은 위에서 설명한 비동기 폼 액션 기능을 지원하는 데 목적을 두고 있습니다. useFormState를 호출하여, 폼이 마지막으로 제출됐을 때 액션의 반환 값에 접근할 수 있습니다.

import { useFormState } from 'react-dom';
import { action } from './action';

function MyComponent() {
    const [state, formAction] = useFormState(action, null);
    // ...
    return <form action={formAction}>{/* ... */}</form>;
}

예를 들어, 폼 액션에서 반환된 확인 또는 오류 메시지를 표시할 수 있습니다.

코드 예제 링크

주의: useFormStatereact가 아니라 react-dom에서 가져와야 합니다.

React 문서에서 useFormstate에 대해 더 자세히 알아볼 수 있습니다.

useFormStatus

useFormStatus는 상위에 있는 <form>이 현재 제출 중인지 또는 성공적으로 제출되었는지를 알려줍니다. 폼의 하위에서 호출할 수 있으며 다음과 같은 속성을 반환하는 객체를 제공합니다.

const { pending, data, method, action } = useFormStatus();

data 속성을 사용하여 사용자가 제출하는 데이터를 표시할 수 있습니다. 또한 다음 예제처럼 폼이 제출 중일 때 버튼을 비활성화하는 등의 대기 상태를 나타낼 수 있습니다.

코드 예제 링크

주의: useFormStatereact가 아니라 react-dom에서 가져와야 합니다. 또한 상위의 폼이 위에서 설명한 action 속성을 사용할 때만 작동합니다.

useFormState와 함께 이 훅을 사용하면 컴포넌트를 불필요한 컨텍스트나 이펙트로 복잡하게 만들지 않으면서도 클라이언트 사이드 폼의 사용자 경험을 향상시킬 수 있습니다. React 문서에서 useFormStatus에 대해 더 자세히 읽을 수 있습니다.

useOptimistic

액션이 제출되는 동안 사용자 인터페이스를 낙관적으로(optimistically) 업데이트할 수 있는 새로운 훅입니다.

import { useOptimistic } from 'react';

function AppContainer() {
  const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // 업데이트 함수
    (currentState, optimisticValue) => {
        // 현재 상태에 낙관적인 값을 합치고 새로운 상태를 반환
    },
  );
}

위의 장바구니 예제에서는 이 훅을 사용하여 AJAX 호출이 완료되기 전에 새 항목이 추가된 장바구니를 보여줄 수 있습니다.

코드 예제 링크

UI를 낙관적으로 업데이트하는 것은 웹 앱의 사용자 경험을 향상시키는 좋은 방법입니다. 이 훅은 이러한 경우에 많은 도움이 됩니다. useOptimistic에 대한 자세한 내용은 React 문서에서 확인할 수 있습니다.

보너스: 비동기 트랜지션

React 트랜지션 API를 사용하면 UI를 차단하지 않으면서 상태를 업데이트할 수 있습니다. 예를 들어, 사용자가 마음이 바뀌면 이전의 상태 변경을 취소할 수 있게 합니다.

이 아이디어는 startTransition 호출로 상태 변경을 감싸는 것입니다.

function TabContainer() {
  const [isPending, startTransition] = useTransition();
  const [tab, setTab] = useState('about');

  function selectTab(nextTab) {
    // setTab(nextTab) 대신에 트랜지션에 상태 변경을 넣음
    startTransition(() => {
        setTab(nextTab);
    });
  }
  // ...
}

다음 예제는 이 Transitions API를 사용한 탭 탐색을 보여줍니다. "Posts"를 클릭한 다음 즉시 "Contact"를 클릭하세요. 이때 "Posts"의 느린 렌더링이 중단되는 것을 주목하세요. "Contact" 탭이 바로 보입니다. 이 상태 업데이트가 트랜지션으로 표시되었기 때문에 느린 리렌더링이 사용자 인터페이스를 멈추지 않았습니다.

코드 예제 링크

useTransition 훅은 이미 React 18.2에서 사용 가능합니다. React 19에서 새롭게 추가된 기능은 이제 startTransition에 비동기 함수를 전달할 수 있다는 것입니다. 이 함수는 React에 의해 대기되어 트랜지션을 시작합니다.

이는 AJAX 호출을 통해 데이터를 제출하고 결과를 트랜지션으로 렌더링하는 데 유용합니다. 트랜지션 대기 상태는 비동기 데이터 제출과 함께 시작됩니다. 이미 위에서 설명한 폼 액션 기능에서 사용되고 있습니다. React가 startTransition으로 감싸진 <form action> 핸들러를 호출하여 현재 페이지를 차단하지 않도록 하기 때문입니다.

이 기능은 아직 React 문서에 작성되지 않았지만, 관련 풀 리퀘스트에서 더 자세히 읽을 수 있습니다.

마무리

위에서 설명한 모든 기능은 클라이언트 전용 React 앱에서 작동합니다. Vite로 번들링된 앱에서도 사용할 수 있다는 의미입니다. 새로운 기능을 사용하기 위해 Next나 Remix와 같은 SSR 프레임워크가 필요한 건 아니지만 서버 통합형 React 앱에서도 작동합니다.

새로운 기능의 등장으로 React에서 데이터 페칭과 폼 처리가 상당히 쉬워집니다. 그러나 훅을 통합하여 훌륭한 사용자 경험을 만드는 것은 복잡할 수 있습니다. 대안으로 react-admin과 같은 프레임워크를 사용할 수 있으며, 낙관적 업데이트가 내장된 사용자 친화적인 폼을 제공합니다.

이 기능들이 React 19 대신 React 18.3에 나오지 않는 이유는 몇 가지 작은 변경사항이 포함되어 있기 때문으로 보입니다.

React 19는 언제 출시될까요? 아직 정확한 출시일은 없지만 이 게시물에서 언급된 모든 기능이 이미 작동하고 있습니다. 그러나 아직 canary 릴리즈를 프로덕션 환경에서 사용하는 것은 좋은 생각은 아닌 것 같습니다(Next.js가 사용하고 있다 하더라도).

React 코어 팀이 SSR 앱에서 작업하는 개발자뿐만 아니라 모든 React 개발자의 개발 경험을 향상시키기 위해 노력하고 있는 것을 보니 정말 좋습니다. 또한 데이터 페칭과 폼 처리는 아주 일반적인 문제들이었는데, 새로운 기능을 보니 커뮤니티 피드백을 듣고 있는 것으로 보입니다.

이러한 기능이 React의 안정적인 릴리즈에서 제공되기를 기대합니다!

0개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN