tabs.gif

본 컴포넌트는 Next.js 환경에서 URL 쿼리 스트링을 상태로 활용하여, 새로고침이나 페이지 공유 시에도 유지되는 “서버 컴포넌트 친화적 탭”을 제공하도록 설계되었다.

✅ 컴포넌트 구조

파일명 유형 주요 역할
tabs.tsx client Context API와 URL 상태를 결합하여 Tabs의 전체 로직을 관리하는 통합 파일
TabsRoot client useSearchParams를 통해 현재 탭 상태를 구독하고 Context를 제공하는 최상위 컨테이너
TabsTrigger client 클릭 시 URL을 업데이트하여 탭을 전환하는 버튼 요소
TabsContent client 현재 URL의 파라미터와 일치할 때만 콘텐츠를 노출하는 래퍼 요소

✅ 주요 속성

모든 탭 구성 요소는 아래의 타입을 기반으로 한다.

⚠️ 주의: 한 페이지 내에서 여러 개의 탭을 사용할 경우, 서로 간섭하지 않도록 반드시 서로 다른 searchParamKey를 명시해야 합니다.


✅ 사용 예시

1. 기본적인 사용 (URL 동기화)

클릭 시 URL이 ?tab=account 등으로 변경되며 상태가 보존된다.

import { TabsRoot, TabsList, TabsTrigger, TabsContent } from "@/src/shared/ui/tabs";

export default function ProfilePage() {
  return (
    <TabsRoot defaultValue="account" className="w-full">
      <TabsList className="bg-slate-100 p-1">
        <TabsTrigger value="account">계정</TabsTrigger>
        <TabsTrigger value="password">비밀번호</TabsTrigger>
      </TabsList>
      
      <div className="mt-4">
        <TabsContent value="account">계정 설정 화면입니다.</TabsContent>
        <TabsContent value="password">비밀번호 변경 화면입니다.</TabsContent>
      </div>
    </TabsRoot>
  );
}

2. 서버 컴포넌트와 함께 사용하는 경우

TabsContent 내부에 서버 컴포넌트를 배치하여 서버 데이터를 안전하게 불러올 수 있다.

// 이 예시는 서버 컴포넌트 내에서 데이터를 직접 다루는 구조입니다.
export default function Page() {
  return (
    <TabsRoot defaultValue="info">
      <TabsList>
        <TabsTrigger value="info">상세 정보</TabsTrigger>
      </TabsList>
      
      <TabsContent value="info">
        {/* 서버 컴포넌트 호출 가능 */}
        <ServerSideDetailComponent />
      </TabsContent>
    </TabsRoot>
  );
}

3. 다중 탭 처리