inblog logo
|
indietools
    frontend

    복붙으로 완성되는 UI: Shadcn UI

    최근에 여러 사이드 프로젝트(파크골프가자, nomorebg) 를 하면서 하면서 해외에서 핫한 shadcn을 접하게 되었고, 기존의 어떤 프로젝트보다 빠르게 웹 UI를 구성할 수 있었습니다. shadcn이 갖고 있는 몇가지 특징과 그리고 한계에 대해서 알아보도록 하겠습니다.
    Nov 06, 2023
    복붙으로 완성되는 UI: Shadcn UI
    Contents
    Shadcn UI의 주요 특징사용 방법필요한 패키지 설치하기CLI 실행하기components.json 생성하기생성된 directory 구조 분석컴포넌트 설치하기컴포넌트 사용하기장단점 분석shadcn으로 진행하고 있는 사이드 프로젝트결론
    최근에 여러 사이드 프로젝트(파크골프가자, nomorebg) 를 하면서 하면서 해외에서 핫한 shadcn을 접하게 되었고, 기존의 어떤 프로젝트보다 빠르게 웹 UI를 구성할 수 있었습니다. shadcn이 갖고 있는 몇가지 특징과 그리고 한계에 대해서 알아보도록 하겠습니다.

    Shadcn UI의 주요 특징

    • tailwind 기반의 UI
      • shadcn은 tailwind 라이브러리와 Next.js에서 유지보수하고 있는 Radix UI를 결합하여 만들었습니다. 그래서 UI를 수정하거나 사용하려면 기본적인 tailwind 지식이 필수로 필요합니다.
    • 사전 제작된 많은 UI 컴포넌트
      • radix UI를 기초로 한 40종에 가까운 컴포넌트를 제공하며, 필요에 따라 추가적인 스타일링 없이 사용이 가능합니다.
    • 기존의 UI 라이브러리와 차별화된 개발 경험
      • Shadcn은 CLI를 통해서 컴포넌트를 나의 프로젝트에 붙어넣기를 하고, 내가 원하는 형태로 변경하여 사용할 수 있습니다.
    • theming 및 다크모드 지원
      • tailwind theme를 기반으로 손쉽게 전체 프로젝트의 theme를 변경할 수 있으며 또한 dark mode 지원이 가능합니다.

    사용 방법

    아래의 내용은 Next.js를 기반으로 하며, shadcn은 Next.js 뿐만 아니라 Remix, React, Gatby등을 지원하며 자세한 정보는 링크에서 확인 하실 수 있습니다.

    필요한 패키지 설치하기

    기본적으로 shadcn이 구동하는데 필요한 라이브러리들을 설치합니다.
    npx create-next-app@latest my-app --typescript --tailwind --eslint

    CLI 실행하기

    shadcn의 최초 설정을 진행합니다.
    npx shadcn-ui@latest init

    components.json 생성하기

    init을 진행하면 아래와 프로젝트 내에서 shadcn을 어떻게 사용할지 설정 할 수 있습니다.
    Would you like to use TypeScript (recommended)? no / yes Which style would you like to use? › Default Which color would you like to use as base color? › Slate Where is your global CSS file? › › app/globals.css Do you want to use CSS variables for colors? › no / yes Where is your tailwind.config.js located? › tailwind.config.js Configure the import alias for components: › @/components Configure the import alias for utils: › @/lib/utils Are you using React Server Components? › no / yes
    위에서 설정된 내용들은 언제든이 component.json 파일에서 바꿀 수 있으니, 내용이 이해되지 않더라도 큰 걱정하지 않으셔도 됩니다. style과 color의 차이는 링크에서 확인 하실 수 있습니다.

    생성된 directory 구조 분석

    . ├── app │ ├── layout.tsx │ └── page.tsx ├── components │ ├── ui │ │ ├── button.tsx ├── lib │ └── utils.ts ├── styles │ └── globals.css ├── next.config.js ├── package.json ├── postcss.config.js ├── tailwind.config.js └── tsconfig.json
    • CLI를 통해서 설치되는 컴포넌트는 components/ui 아래에 위치 하게 됩니다.
    • lib 폴더에는 tailwind 스타일을 관리할 때 사용되는 util함수가 생성됩니다.
    • styles/globals.css 에는 shadcn을 사용하기 위한 글로벌 스타일들이 저장 됩니다.

    컴포넌트 설치하기

    npx shadcn-ui@latest add button
    위 명령어를 실행하면 아래와 같이 components/ui 폴더에 button 컴포넌트가 생성됩니다.
    . ├── app │ ├── layout.tsx │ └── page.tsx ├── components │ ├── ui │ │ ├── button.tsx ├── lib │ └── utils.ts ├── styles │ └── globals.css ├── next.config.js ├── package.json ├── postcss.config.js ├── tailwind.config.js └── tsconfig.json
    정확하게 이야기하면, 컴포넌트를 설치한다기 보단 컴포넌트를 복사 붙여넣기에 가깝습니다. 즉, 실제 코드가 button 파일의 이름으로 아래와 같은 코드가 생성이 됩니다.
    // button 컴포넌트 상세 코드 import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ) export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { asChild?: boolean } const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button" return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ) } ) Button.displayName = "Button" export { Button, buttonVariants }
    이 코드는 처음에 component.json 을 어떻게 구성했느냐에 따라 달라지기 때문에, 위와 100% 같지 않을 수 있습니다.

    컴포넌트 사용하기

    import { Button } from "@/components/ui/button" export default function Home() { return ( <div> <Button>Click me</Button> </div> ) }
    사용하는 방법은 간단합니다. 다른 컴퍼넌트들처럼 Import하여 쉽게 사용할 수 있습니다.

    장단점 분석

    3달간 써보면서 느꼈던 장단점을 정리해보겠습니다.

    장점

    • 컴포넌트 전체가 내 소스코드에 복사되기 때문에, Props를 추가하거나, 스타일 변경을 쉽게 할 수 있습니다. 추가적인 랩핑 컴포넌트가 필요 없습니다.
    • 40여개의 사전 제작된 컴포넌트를 통해서 빠른 속도로 프로토타이핑을 할 수 있습니다
    • 테마가 제공되어 내가 원하는 무드로 변경이 가능합니다.

    단점

    • 모든 스타일링이 tailwind를 통해서 이뤄지므로 tailwind에 대한 사전지식이 필요합니다.
    • 빠른 속도로 성장하고 있는 것은 맞으나, 타 UI 라이브러리 대비해서 자료가 많이 부족합니다.
     

    shadcn으로 진행하고 있는 사이드 프로젝트

    플러그 파인더
    플러그 파인더와 함께 전국의 전기차 충전소를 쉽고 빠르게 찾아보세요. 대한민국 전역의 충전소 위치, 이용 가능 시간, 서비스 상세 정보를 한눈에 확인 하실 수 있습니다. 여러분의 전기차 여정을 더욱 편리하고, 빠르게 만들어 드리겠습니다.
    플러그 파인더
    https://www.plugfinder.app/
    플러그 파인더
    파크골프가자
    대한파크골프협회에서 인증받은 전국 파크골프장 이용정보를 한 곳에서 찾아보세요. 가장 빠르게 성장하는 파크골프 커뮤니티 파크골프가자
    파크골프가자
    https://www.goparkgolf.app/
    파크골프가자

    결론

    • MUI를 사용한 다른 프로젝트와 대비해서 shadcn을 활용하면 커스텀이 쉽고, 직관적인 이해가 되기 때문에 정말 빠르게 만들 수 있습니다. MUI는 각 API Spec을 이해하는데 시간이 많이 소요되었었습니다.
    • t3 stack(next.js, tailwind, typescript)를 사용한다면, 강력하게 추천드립니다.
     
    최근에 패스트 캠퍼스에서 NextJS 14, Supabase, Shadcn을 바탕으로 강의를 하게 되었습니다. 블로그에서 언급한 내용들을 대부분 다루고 있고, 제가 가진 모든 노하우를 집약해서 만들고 있습니다. 아래 링크를 통해서 등록하시면 20% 할인 가능하오니, 많은 관심 부탁드려요 https://abit.ly/vbqkjk
    Share article

    indietools

    RSS·Powered by Inblog