[Hook] useId

OlMinJe·2025년 9월 2일

React

목록 보기
8/19

리액트 공식 문서를 참고한 정리 내용 (25.08 기준)

접근성 어튜리뷰에 전달할 수 있는 고유 ID를 생성하기 위한 Hook이다.

const id = useId()

useId를 컴포넌트의 최상위에서 호출하여 고유 ID를 생성한다.

import { useId } from 'react';

function PasswordField() {
  const passwordHintId = useId();
  // ...

매개변수

useId는 어떤 매개변수도 받지 않는다


반환값

useId를 호출한 특정 컴포넌트와 특정 useId에 관련된 고유 ID 문자열을 반환한다.


주의사항

  • Hook 임을 잊지 말아야 하며, 로직 내에서 필요한 경우 새로운 컴포넌트를 추출하고 해당 컴포넌트로 state를 이동하는 방식으로 사용해야 한다.
  • useId는 리스트의 key를 생성하기 위해 사용하면 안된다
  • useId는 비동기 서버 컴포넌트에서는 사용할 수 없다.

사용법

useId를 사용하는 것이 카운터를 증가하는 것보다 나은 이유는 무엇일까?

서버 렌더링(SSR)에서는 서버에서 HTML을 만들고, 클라이언트가 그 HTML을 이어받아(hydration) 이벤트를 붙이는 과정이 있다.
이때 서버에서 만든 HTML과 클라이언트에서 만든 HTML과 클라이언트에서 만든 HTML이 100% 똑같아야 제대로 동작한다.

그런데 말입니다. 단순히 nextId++ 같이 전역 카운터로 ID를 만들면,

  • 컴포넌트 렌더 순서가 서버와 클라이언트에서 다를 수 있어서
  • 서버에서 만든 ID와 클라이언트에서 만든 ID가 달라질 위험이 있다. ⇒ 와장창 무너진 hydration

클라이언트와 서버에서 동일한 ID 접두사 사용하기

같은 페이지에 React 앱이 여러 개 올라갈 수 있는데, 이때 각 앱이 생성하는 useId 값이 서버와 클라이언트에서 달라지면 문제가 생긴다. 왜냐하면 hydration(서버에서 만든 HTML과 클라이언트를 이어붙이는 과정)에서는 ID가 반드시 동일해야 하기 때문!

이 문제를 해결하기 위해 React에서 제공하는 identifierPrefix라는 옵션을 사용한다.

  • 서버에서 renderToPipeableStream을 호출할 때 identifierPrefix: 'react-app1' 같이 지정
  • 클라이언트에서도 hydrateRoot 호출 시 같은 identifierPrefix를 지정

👉 이렇게 하면 서버와 클라이언트가 같은 규칙으로 ID를 만들기 때문에 충돌이 발생하지 않는다.

// server
const { pipe } = renderToPipeableStream(<App />, {
  identifierPrefix: 'react-app1'
});

// client
const root = hydrateRoot(domNode, reactNode, {
  identifierPrefix: 'react-app1'
});

👉 요약하자면,identifierPrefix는 서버와 클라이언트가 같은 ID를 쓰도록 맞춰주는 옵션이고, 여러 React 앱을 같은 페이지에 띄울 때 꼭 필요하다.

profile
큐트걸

0개의 댓글