lifecarelog
프론트엔드

shadcn v4 Base UI에서 asChild를 render로 바꾸는 법

shadcn Base UI 전환 뒤 사라진 asChild를 render prop으로 옮겨 버튼과 링크를 합성하는 화면 구현 방법입니다.

4분 읽기

shadcn v4에서 Base UI 구성을 쓰기 시작하면 기존 asChild가 없다는 오류를 만날 수 있어요. 이때 자식 요소를 통째로 교체하던 방식 대신, 어떤 HTML 요소나 컴포넌트로 렌더할지 render prop에 넘기면 됩니다.

직접 만들어 보니 핵심은 3단계였어요. 기존 합성 지점을 찾고, asChild를 지운 뒤, 자식으로 두었던 요소를 render에 옮기는 순서예요. 화면에서 유지할 것은 버튼의 모양과 링크의 이동 동작, 2가지입니다.

asChild 사용 위치 찾기render에 요소 전달클릭과 키보드 이동 확인

트리거는 버튼으로 넘겨요

이전에는 DrawerTrigger 안에 Button을 넣었다면, 이제 버튼 인스턴스를 render로 전달해요. 텍스트는 트리거의 자식으로 남겨 둡니다.

<DrawerTrigger render={<Button variant="outline" />}>
  메뉴 열기
</DrawerTrigger>

적용해 봤더니 JSX 구조가 한 단계 얕아져서, 실제 클릭 대상이 무엇인지 읽기 편했어요. Button은 1개만 렌더되고, 트리거가 필요한 이벤트와 접근성 속성을 그 버튼에 전달하는 형태입니다.

다만 모든 컴포넌트가 같은 합성 API를 제공하는 것은 아니에요. 프로젝트가 Radix 기반인지 Base UI 기반인지 먼저 확인해야 합니다. 같은 이름의 컴포넌트라도 한쪽은 asChild, 다른 쪽은 render를 받을 수 있어요.

내비게이션 링크도 같은 방식이에요

메뉴 항목을 Next.js Link로 만들 때도 원리는 같아요. 링크 컴포넌트를 render에 넣고, 사람이 읽을 제목은 메뉴 링크 안에 둡니다.

<NavigationMenuLink
  render={<Link href="/guide" />}
  className={navigationMenuTriggerStyle()}
>
  사용 가이드
</NavigationMenuLink>

테스트해 보면 확인할 지점은 2곳이에요. 마우스로 눌렀을 때 목적지로 이동하는지, Tab 키로 이동했을 때 포커스 표시가 링크에 보이는지예요. 링크가 1개인데 버튼과 링크가 중첩되면 HTML 의미가 흐려질 수 있으니, 화면 역할에 맞는 요소 하나만 남기는 편이 안전해요.

라이프케어로그에서 플랜씨(plan-c)처럼 로그인 없이 바로 계산을 시작하는 화면을 구성할 때도 이 구분이 유용해요. 계산 시작은 button, 다른 계산기로 이동하는 메뉴는 a 또는 Link로 분리하면 키보드 사용 흐름까지 자연스럽게 이어집니다.

돌려 보니 마이그레이션의 어려움은 문법 변경보다 화면 확인에 있었어요. 타입 검사가 통과해도 드로어가 열리는지, 닫기 동작이 남았는지, 포커스가 예상한 위치로 돌아오는지는 별도로 봐야 해요. 작은 컴포넌트 1개씩 바꾸고, 클릭과 키보드 이동을 함께 확인하면 전환 범위를 관리하기 수월합니다.

#shadcn#base-ui#react

라이프케어로그 서비스가 궁금하신가요?

AI 기반 건강·일정·재활 관리 앱을 직접 써보세요.

서비스 살펴보기

관련 글

댓글

아직 댓글이 없어요. 첫 댓글을 남겨주세요.