티스토리 뷰

728x90

NextJS와 NextUI에 대한 단상

이미 완성된 디자인 시스템을 보유한 팀이거나, 

디자인에 대한 절대적인 약속(퍼블리싱 팀 존재함, 디자이너가 만든 1px의 오차도 용서할 수 없음)이 있는 상황이 아니라면...

절대적으로 공개된 디자인 라이브러리들을 활용해야 한다고 생각한다.

모든 컴포넌트를 언제 다 손수 만들고 있겠는가. 우리의 시간은 개발사의 비용이다.

 

특히 구스피크와 같이 디자인에 대한 역량이 전혀 없는 개발팀에게는 UI/UX 개발 시 더욱 필수적이다.

 

과거에 내가 PHP, JSP, JQuery로 웹을 만들때는 Bootstrap이 절대적인 템플릿이었다.

거의 모든 회사가 Bootstrap을 쓰고 있는 것처럼 느껴졌다.

 

그러나 모바일이 등장하고 프론트엔드 개발시장이 빠르게 성장했다. 다양해진 개발언어와 프레임워크에 발맞춰 디자인을 더 쉽게 해줄 수 있는 무언가도 그 속성을 더 다양화했다. 세상에 템플릿이 너무 많다. 이번 프로젝트에서는 NextUI를 적용해봤다. Ant Desing만큼은 아니지만 컴포넌트가 풍부해보였고, 개발자가 보기에 상당히 이뻤다.

 

아래 과정으로 프로젝트를 셋팅하는데에는 10분 남짓의 시간이 걸릴 것이다.

 

1. NextJS 프로젝트를 생성한다.

npx create-next-app@latest

TypeScript를 쓸건지, EsLint를 쓸건지, TailwindCSS를 쓸건지 등 프로젝트 셋팅을 위해 확인사항 질문이 들어온다. 나는 App Router를 쓸 것이고 src 디렉터리도 사용할 것이니, 다 Yes라고 대답하지만, 보고 따라하는 사람은 본인의 취향에 맞게 선택지를 고르자. 다만 NextUI는 TailwindCSS 기반으로 동작하므로 반드시 TailwindCSS는 yes로 응답해야한다.

 

 

2. 라이브러리들과, NextUI/react를 설치한다.

cd ./{project-name}
npm i
npm i @nextui-org/react framer-motion next-themes

 

설치가 진행되면서 node_modules 폴더가 생성된다.

 

 

 

3. RootLayout, tailwind.confg 파일을 수정하고, Provider를 생성한다.

/src/app/layout.tsx

import type { Metadata } from "next";
import "./globals.css";
import Providers from './providers'

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html>
      <body>
        <Providers>
          {children}
        </Providers>
      </body>
    </html>
  );
}

달라진점은 Provider를 추가한 것, 사용하지 않을 Inter 라이브러리의 import 문을 삭제한 것 밖에 없다.

 

/tailwind.config.ts

import type { Config } from 'tailwindcss'
const {nextui} = require("@nextui-org/react");

const config: Config = {
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
    "./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {
      backgroundImage: {
        'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
        'gradient-conic':
          'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
      },
    },
  },
  darkMode: "class",
  plugins: [nextui({
    prefix: "nextui", // prefix for themes variables
    addCommonColors: false, // override common colors (e.g. "blue", "green", "pink").
    defaultTheme: "light", // default theme from the themes object
    defaultExtendTheme: "light", // default theme to extend on custom themes
    layout: {}, // common layout tokens (applied to all themes)
    themes: {
      light: {
        layout: {}, // light theme layout tokens
        colors: {}, // light theme colors
      },
      dark: {
        layout: {}, // dark theme layout tokens
        colors: {}, // dark theme colors
      },
      // ... custom themes
    },
  })],
}
export default config

 

/src/app/providers.tsx

'use client'

import { NextUIProvider } from "@nextui-org/react"
import { ThemeProvider as NextThemesProvider } from "next-themes" 

export default function Providers({
    children
}: {
    children: React.ReactNode
}) {
    return (
        <NextUIProvider>
            <NextThemesProvider
                attribute='class'
                defaultTheme="light"
                themes={['dark', 'light', 'modern']}  
            >
                {children}
            </NextThemesProvider>
        </NextUIProvider>
    )
}

Provider NextUI를 사용하기 위한 Provider를 root 에 추가하는 과정이다

 

 

4. NextUI를 사용한다.

NextUI document를 확인하여 원하는 컴포넌트를 Page에 붙여보자. 예시로 Modal 컴포넌트를 붙여봤다.

 

/src/app/page.tsx

import React from "react";
import {Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, useDisclosure, Checkbox, Input, Link} from "@nextui-org/react";

export default function App() {
  const {isOpen, onOpen, onOpenChange} = useDisclosure();

  return (
    <>
      <Button onPress={onOpen} color="primary">Open Modal</Button>
      <Modal 
        isOpen={isOpen} 
        onOpenChange={onOpenChange}
        placement="top-center"
      >
        <ModalContent>
          {(onClose) => (
            <>
              <ModalHeader className="flex flex-col gap-1">Log in</ModalHeader>
              <ModalBody>
                <Input
                  autoFocus
                  label="Email"
                  placeholder="Enter your email"
                  variant="bordered"
                />
                <Input
                  label="Password"
                  placeholder="Enter your password"
                  type="password"
                  variant="bordered"
                />
                <div className="flex py-2 px-1 justify-between">
                  <Checkbox
                    classNames={{
                      label: "text-small",
                    }}
                  >
                    Remember me
                  </Checkbox>
                  <Link color="primary" href="#" size="sm">
                    Forgot password?
                  </Link>
                </div>
              </ModalBody>
              <ModalFooter>
                <Button color="danger" variant="flat" onPress={onClose}>
                  Close
                </Button>
                <Button color="primary" onPress={onClose}>
                  Sign in
                </Button>
              </ModalFooter>
            </>
          )}
        </ModalContent>
      </Modal>
    </>
  );
}

 

 

localhost 서버 실행

npm run dev

 

 

디자인은 NextUI에 맡겨놓고 로직개발에 집중하자

728x90