Next.js 프로젝트 시작하기, 최적화

Minboy·2024년 3월 4일
1
post-thumbnail

Chapter 1

Creating a new project

npx create-next-app@latest nextjs-dashboard --use-npm --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example"

Folder structure

  • /app : routes, components, 앱의 로직 등 포함. 대부분의 시간을 여기서 보낼 것
  • /app/lib : 재사용 가능한 함수들 - 유틸성 함수, 데이터 fetching 함수 등
  • /app/ui : UI components - 카드, 테이블, 폼 등등
  • /public : 이미지와 같은 정적 파일들
  • /scripts : 차후에 db를 만들 때 사용할 스크립트

Running the development server

npm run dev

Chapter 2

Global styles

/app/ui 폴더 내부의 global.css 파일에서 모든 routes에 적용될 CSS 규칙 - CSS reset, 링크스타일 등을 정의

어느 컴포넌트에서도 import 하여 사용할 수 있지만, 최상위 컴포넌트에서 적용하는 것이 좋은 관습이다. Next.js에서는 이를 root layout 이라한다.

/app/layout.tsx 에서 import 하여 글로벌 스타일을 적용하자.

Tailwind

클래스명을 통해 스타일링을 하는 Tailwind 프레임워크를 사용할 것을 권장하고 있다. create-next-app 을 이용해 프로젝트를 셋업할 때 Tailwind를 사용할 것인지 묻는데, 이때 yes를 선택하면 자동으로 필요한 패키지와 설정을 완료해준다.

일전에 Tailwind를 사용해본 경험이 있고, 빠른 개발 프로세스라는 장점에 정말 좋게 생각하고 있던 프레임워크여서 굉장히 반가웠다.

Installation - Tailwind CSS

Tailwind의 공식문서도 굉장히 친절하게 설명하고 있고, 원하는 스타일의 클래스명도 검색을 통해 쉽게 찾을 수 있다.

Using the clsx library to toggle class names

조건적으로 클래스명을 주기 위해 clsx 라이브러리를 사용할 것을 추천하고 있다.

import clsx from 'clsx';

export default function InvoiceStatus({ status }: { status: string }) {
  return (
    <span
      className={clsx(
        'inline-flex items-center rounded-full px-2 py-1 text-sm',
        {
          'bg-gray-100 text-gray-500': status === 'pending',
          'bg-green-500 text-white': status === 'paid',
        },
      )}
    >
    // ...
)}

이런식으로 클래스명에 clsx({”class-name” : boolean}) 와 같이 사용하여 조건부 클래스명을 전달할 수 있다.

Chapter 3

Why optimize fonts?

폰트는 웹 디자인에서 큰 역할을 담당하지만, 커스텀 폰트를 이용하는 것은 폰트를 fetch하고 load하는 과정이 필요하다면 퍼포먼스에 영향을 줄 수도 있다.

폰트가 로드되면서 텍스트 크기, 여백, 레이아웃 등에 영향을 미칠 수 있고, 이는 나쁜 사용자 경험을 가져올 수 있다. 이러한 사용자 경험 퍼포먼스를 측정하는 [Cumulative Layout Shift](https://web.dev/articles/cls?hl=ko) 라는 구글에서 사용되는 척도도 있다.

Next.js는 next/font 모듈을 이용하면 자동으로 폰트를 최적화 해준다. 폰트파일을 빌드 타임에 다운로드 받고 정적파일들과 함께 호스팅 해주는데, 이를 통해 사용자가 어플리케이션에 접근했을 때 추가적인 폰트 요청을 하지 않아도 되게 함으로써 사용자 경험 퍼포먼스 문제를 해결한다.

import { Inter } from 'next/font/google';

export const inter = Inter({ subsets: ['latin'] });

fonts.ts 파일에서 폰트를 정의해주고,

import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

원하는 곳에서 위처럼 사용하면 된다.

Why optimize images?

일반적인 HTML의 img 태그를 사용하면 다음을 수동적으로 처리해주어야한다.

  • 다양한 스크린 사이즈에서의 반응형 보장
  • 다양한 장치에서의 이미지 크기 명시
  • 이미지 로드 시 레이아웃 밀림 방지
  • 사용자의 시점 밖의 이미지 지연 로딩

이러한 이미지 최적화를 하나하나 구현하는 대신, next/image 컴포넌트를 활용하면 쉽게 처리할 수 있다.

The <Image> component

<Image> 컴포넌트는 HTML의 img 태그를 확장한 것으로, 상기한 이미지 최적화를 자동으로 처리해준다.

import Image from 'next/image';

...
	<Image
    src="/hero-desktop.png"
    width={1000}
    height={760}
    className="hidden md:block"
    alt="Screenshots of the dashboard project showing desktop version"
  />
  <Image
    src="/hero-mobile.png"
    width={560}
    height={620}
    className="block md:hidden"
    alt="Screenshots of the dashboard project showing mobile version"
  />
...

위와 같이 사용하면 된다. md:block 클래스명은 다음과 같은 CSS 효과를 준다.

@media (min-width: 768px) {
  .md\:block {
    display: block;
  }
}

이를 활용해 hidden md:blockblock md:hidden 클래스명을 통해 데스크탑과 모바일에서의 조건을 걸어줄 수 있다.

profile
🐧

0개의 댓글

관련 채용 정보