Project-hongsta(2)

강홍규(カンホンギュ)·2026년 1월 20일

Project

목록 보기
2/9
post-thumbnail

Shadcn/ui + React Router - UIコンポーネントとルーティング

🎨 Shadcn/uiとは?

概要(がいよう)

必須(ひっす)的(てき)なUIコンポーネントを提供(ていきょう)します。
デザイン分野(ぶんや)で1位(い)を記録(きろく)し、Tailwind CSSベースで制作(せいさく)されました。

필수적인 UI 컴포넌트를 제공합니다.
디자인 분야에서 1위를 기록했으며, Tailwind CSS 기반으로 제작되었습니다.

공식 사이트: ui.shadcn.com


⚙️ Shadcn/ui 設定(せってい)

初期(しょき)セットアップ

まず、設定(せってい)ファイルにパスエイリアスを追加(ついか)します。
プロジェクトのsrc/フォルダーを@で参照(さんしょう)できるようにします。

먼저 설정 파일에 경로 별칭을 추가합니다.
프로젝트의 src/ 폴더를 @로 참조할 수 있게 합니다.

tsconfig.json

"compilerOptions": {
  "baseUrl": ".",
  "paths": {
    "@/*": ["./src/*"]
  }
}

tsconfig.app.json

"baseUrl": ".",
"paths": {
  "@/*": ["./src/*"]
}

vite.config.ts

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import path from "path";

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
});

세팅 완료: 이제 필요한 컴포넌트를 개별적으로 설치할 수 있습니다


🔘 主要(しゅよう)コンポーネント

1. Button (ボタン)

ボタンコンポーネントをインストールします。
様々(さまざま)なバリアント(variant)で使(つか)い分(わ)けができます。

버튼 컴포넌트를 설치합니다.
다양한 variant로 구분해서 사용할 수 있습니다.

npx shadcn@latest add button

자동 생성되는 유틸리티 함수

import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

cn 함수 활용 예시

<div
  className={cn(
    "w-10 text-sm",
    isActive ? "text-green-500" : "text-red-500",
  )}
>
  isActive
</div>

cn 함수: 삼항 연산자를 사용해 조건부 스타일링을 쉽게 구현

Button Variants

<Button variant={"destructive"}>버튼</Button>
<Button variant={"ghost"}>버튼</Button>
<Button variant={"link"}>버튼</Button>
<Button variant={"outline"}>버튼</Button>
<Button variant={"secondary"}>버튼</Button>
Variant説明(せつめい)
destructive삭제, 위험한 작업용 (빨간색)
ghost배경 없는 투명 버튼
link링크 스타일 버튼
outline테두리만 있는 버튼
secondary보조 버튼 (회색)

2. Input (入力(にゅうりょく))

テキスト入力(にゅうりょく)フィールドです。
プレースホルダーを設定(せってい)できます。

텍스트 입력 필드입니다.
플레이스홀더를 설정할 수 있습니다.

npx shadcn@latest add input
<Input placeholder="입력 ..." />

3. Textarea (テキストエリア)

複数(ふくすう)行(ぎょう)のテキスト入力(にゅうりょく)です。
長(なが)い文章(ぶんしょう)の入力(にゅうりょく)に使(つか)います。

여러 줄의 텍스트 입력입니다.
긴 문장 입력에 사용합니다.

npx shadcn@latest add textarea
<Textarea />

4. Toast (トースト) - Sonner

画面(がめん)上部(じょうぶ)にメッセージを表示(ひょうじ)します。
一時的(いちじてき)な通知(つうち)に便利(べんり)です。

화면 상단에 메시지를 표시합니다.
일시적인 알림에 편리합니다.

npx shadcn@latest add sonner
import { Toaster } from "@/components/ui/sonner";
import { toast } from "sonner";

<Toaster />

<Button
  onClick={() => {
    toast("토스트 메시지", {
      position: "top-center",
    });
  }}
>
  버튼!
</Button>

Toaster 컴포넌트: 반드시 최상위에 추가해야 toast가 작동합니다

画像(がぞう)スライドに使(つか)われます。
複数(ふくすう)のアイテムを一度(いちど)に表示(ひょうじ)できます。

이미지 슬라이드에 사용됩니다.
여러 아이템을 한 번에 표시할 수 있습니다.

npx shadcn@latest add carousel
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/ui/carousel";

<Carousel className="mx-10">
  <CarouselContent>
    <CarouselItem className="basis-1/3">1</CarouselItem>
    <CarouselItem className="basis-1/3">2</CarouselItem>
    <CarouselItem className="basis-1/3">3</CarouselItem>
    <CarouselItem className="basis-1/3">4</CarouselItem>
    <CarouselItem className="basis-1/3">5</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

핵심: mx-10으로 마진을 줘서 양옆 아이템이 보이게 하고, basis-1/3으로 한 번에 3개씩 표시

6. Popover (ポップオーバー)

ボタンの下部(かぶ)に小(ちい)さなウィンドウが表示(ひょうじ)されます。
ユーザークリック、ログアウトなどに使(つか)います。

버튼 하단에 작은 창이 표시됩니다.
사용자 메뉴, 로그아웃 등에 사용합니다.

npx shadcn@latest add popover
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover";

<Popover>
  <PopoverTrigger asChild>
    <Button>Open</Button>
  </PopoverTrigger>
  <PopoverContent>Content!</PopoverContent>
</Popover>

중요: @/components/ui에서 가져오는 것을 반드시 확인!

7. Dialog (ダイアログ)

クリックするとモーダルウィンドウが表示(ひょうじ)されます。
重要(じゅうよう)な情報(じょうほう)を表示(ひょうじ)するときに使(つか)います。

클릭하면 모달 창이 표시됩니다.
중요한 정보를 표시할 때 사용합니다.

npx shadcn@latest add dialog
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";

<Dialog>
  <DialogTrigger>Open Dialog</DialogTrigger>
  <DialogContent>
    <DialogTitle>Title</DialogTitle>
    <div>Body</div>
  </DialogContent>
</Dialog>

8. Alert Dialog (アラートダイアログ)

ユーザーの確実(かくじつ)な反応(はんのう)を確認(かくにん)する必要(ひつよう)があるときに使(つか)います。
肯定(こうてい)ボタンと否定(ひてい)ボタンが追加(ついか)されます。

사용자의 확실한 반응을 확인해야 할 때 사용합니다.
긍정 버튼과 부정 버튼이 추가됩니다.

npx shadcn@latest add alert-dialog
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";

<AlertDialog>
  <AlertDialogTrigger>Open Alert Dialog</AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogTitle>Title</AlertDialogTitle>
    <AlertDialogDescription>Description</AlertDialogDescription>
    <div>body</div>
    <div>
      <AlertDialogAction
        onClick={() => {
          console.log("Action!");
        }}
      >
        Action
      </AlertDialogAction>
      <AlertDialogCancel onClick={() => console.log("Cancel")}>
        Cancel
      </AlertDialogCancel>
    </div>
  </AlertDialogContent>
</AlertDialog>
コンポーネント用途(ようと)
Dialog일반적인 정보 표시
Alert Dialog사용자 확인이 필요한 중요한 작업

권장: Alert Dialog 사용 시 Description 컴포넌트도 함께 사용하기


🎨 Icon (アイコン)

Lucide React

Lucide Reactからアイコンをインポートして使(つか)えます。
サイズや色(いろ)をTailwindで簡単(かんたん)に変更(へんこう)できます。

Lucide React에서 아이콘을 가져와 사용할 수 있습니다.
크기와 색상을 Tailwind로 쉽게 변경할 수 있습니다.

import { ChefHat } from "lucide-react";

<ChefHat className="h-10 w-10 fill-red-500" />

🛣️ React Router 核心(かくしん)정리

インストールと基本(きほん)設定(せってい)

React Routerをインストールしてルーティングを設定(せってい)します。
ブラウザのアドレスをUIが感知(かんち)してレンダリングできるようにします。

React Router를 설치하고 라우팅을 설정합니다.
브라우저 주소를 UI가 감지해서 렌더링할 수 있게 합니다.

npm i react-router@7
npm run dev

main.tsx

import { BrowserRouter } from "react-router";

createRoot(document.getElementById("root")!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
);

ルーティング設定(せってい)

Routes、Route、Outletを使(つか)ってページを構成(こうせい)します。
パスに応(おう)じてコンポーネントがレンダリングされます。

Routes, Route, Outlet을 사용해서 페이지를 구성합니다.
경로에 따라 컴포넌트가 렌더링됩니다.

App.tsx

import { Outlet, Route, Routes } from "react-router";
import "./App.css";
import IndexPage from "@/pages/index-page";
import SignInPage from "@/pages/sign-in-page";
import SignUpPage from "@/pages/sign-up-page";

function AuthLayout() {
  return (
    <div>
      <header>Auth!</header>
      <Outlet />
    </div>
  );
}

function App() {
  return (
    <Routes>
      <Route path="/" element={<IndexPage />} />

      <Route element={<AuthLayout />}>
        <Route path="/sign-in" element={<SignInPage />} />
        <Route path="/sign-up" element={<SignUpPage />} />
      </Route>
    </Routes>
  );
}

export default App;

ページコンポーネント

pages/index-page.tsx

export default function IndexPage() {
  return <div>Index</div>;
}

pages/sign-in-page.tsx

export default function SignInPage() {
  return <div>SignInPage</div>;
}

pages/sign-up-page.tsx

export default function SignUpPage() {
  return <div>SignUpPage</div>;
}
パスコンポーネント설명
/IndexPage홈 페이지
/sign-inSignInPage로그인 페이지
/sign-upSignUpPage회원가입 페이지

Outlet: 중첩된 라우트의 자식 컴포넌트가 렌더링될 위치를 지정

レイアウト共有(きょうゆう)

同(おな)じRoute内(ない)にネストされたページは同(おな)じレイアウトを共有(きょうゆう)します。
AuthLayoutでラップされた/sign-in/sign-upは同(おな)じヘッダーを表示(ひょうじ)します。

같은 Route 내에 중첩된 페이지는 같은 레이아웃을 공유합니다.
AuthLayout으로 감싼 /sign-in/sign-up은 같은 헤더를 표시합니다.

/ → IndexPage만 표시
/sign-in → Auth! 헤더 + SignInPage
/sign-up → Auth! 헤더 + SignUpPage

📋 まとめ

Shadcn/uiで高品質(こうひんしつ)なUIコンポーネントを簡単(かんたん)に導入(どうにゅう)できます。
React Routerでページルーティングとレイアウト管理(かんり)が効率的(こうりつてき)になります。

Shadcn/ui로 고품질 UI 컴포넌트를 쉽게 도입할 수 있습니다.
React Router로 페이지 라우팅과 레이아웃 관리가 효율적으로 됩니다.

핵심: Shadcn/ui (디자인) + React Router (라우팅) = 완벽한 프론트엔드 구성

profile
日本での就職を目指している26歳の韓国人開発者です。 アプリとweb開発、両方準備中で、日本語で技術概念を整理しながら日本語も一緒に勉強する予定です。 コツコツ続けるのが好きな開発者の成長記録を、一緒に見守っていただけると嬉しいです! 일본에서의 취업을 목표로 하고 있는 26살의 한국인 개발자입니다. 앱과 웹 개발, 둘 다 준비 중이며, 일본어로 기술 개념을 정리하면서 일본어도 함께 공부할 예정입니다. 꾸준히 계속하는 것을 좋아하는 개발자의 성장 기록을, 함께 지켜봐

0개의 댓글