Optimizing Fonts and Images

이전 장에서는 Next.js 애플리케이션의 스타일을 지정하는 방법을 배웠습니다. 사용자 정의 글꼴과 영웅 이미지를 추가하여 홈페이지 작업을 계속해 보겠습니다.

이 장에서는 우리가 다룰 주제는 다음과 같습니다

  • next/font를 사용하여 사용자 정의 글꼴을 추가하는 방법.
  • next/image로 이미지를 추가하는 방법.
  • Next.js에서 글꼴과 이미지를 최적화하는 방법

Why optimize fonts?

글꼴은 웹 사이트 디자인에서 중요한 역할을 하지만 프로젝트에서 사용자 정의 글꼴을 사용하면 글꼴 파일을 가져오고 로드해야 하는 경우 성능에 영향을 줄 수 있습니다.

Cumulative Layout Shift는 Google에서 웹사이트의 성능과 사용자 경험을 평가하는 데 사용하는 측정항목입니다. 글꼴을 사용하면 브라우저가 처음에 텍스트를 대체 또는 시스템 글꼴로 렌더링한 다음 로드된 후 사용자 지정 글꼴로 교체할 때 레이아웃 이동이 발생합니다. 이 교체로 인해 텍스트 크기, 간격 또는 레이아웃이 변경되어 주변 요소가 이동될 수 있습니다.

Next.js next/font 모듈을 사용할 때 응용 프로그램의 글꼴을 자동으로 최적화합니다. 빌드 시간에 글꼴 파일을 다운로드하고 다른 정적 자산과 함께 호스팅합니다. 즉, 사용자가 애플리케이션을 방문할 때 성능에 영향을 줄 수 있는 글꼴에 대한 추가 네트워크 요청이 없습니다.

퀴즈를 풀 시간입니다!

지식을 테스트하고 방금 배운 내용을 확인하세요. True or False: Images without dimensions and web fonts are common causes of layout shift.

Adding a primary font

애플리케이션에 사용자 지정 Google 글꼴을 추가하여 작동 방식을 살펴보겠습니다.

/app/ui 폴더에서 fonts.ts라는 새 파일을 만듭니다. 이 파일을 사용하여 응용 프로그램 전체에서 사용할 글꼴을 유지합니다.

next/font/google 모듈에서 Inter 글꼴을 가져옵니다 - 이것이 기본 글꼴이 됩니다. 그런 다음 로드할 하위 집합을 지정합니다. 이 경우 latin입니다.

/app/ui/fonts.ts
import { Inter } from 'next/font/google';

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

마지막으로 <body> /app/layout.tsx의 요소에 글꼴을 추가합니다.

/app/layout.tsx
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>
  );
}

요소에 Inter를 추가하면 <body> 글꼴이 응용 프로그램 전체에 적용됩니다. 여기에 글꼴을 매끄럽게 하는 Tailwind 앤티앨리어싱 클래스도 추가됩니다. 이 클래스를 사용할 필요는 없지만 멋진 터치를 추가합니다.

브라우저로 이동하여 개발 도구를 열고 body 요소를 선택합니다. 이제 InterInter_Fallback이 스타일 아래에 적용된 것을 볼 수 있습니다.

Practice: Adding a secondary font

애플리케이션의 특정 요소에 글꼴을 추가할 수도 있습니다.

이제 당신 차례입니다! Fonts.ts 파일에서 Lusitana라는 보조 글꼴을 가져와 /app/page.tsx 파일의 <p> 요소에 전달합니다. 이전처럼 하위 집합을 지정하는 것 외에도 다양한 글꼴 두께도 지정해야 합니다. 예를 들어 400(보통) 및 700(굵게)입니다.

준비가 되면 아래 코드 조각을 확장하여 솔루션을 확인하세요.

Hints:

글꼴에 전달할 가중치 옵션이 확실하지 않은 경우 코드 편집기에서 TypeScript 오류를 확인하세요. Google Fonts 웹사이트를 방문하여 Lusitana를 검색하여 사용 가능한 옵션을 확인하세요. 여러 글꼴 추가 및 전체 옵션 목록에 대한 설명서를 참조하세요.



마지막으로 <AcmeLogo /> 구성요소도 Lusitana를 사용합니다. 오류를 방지하기 위해 주석 처리되었습니다. 이제 주석 처리를 해제할 수 있습니다.

/app/page.tsx
// ...

export default function Page() {
  return (
    <main className="flex min-h-screen flex-col p-6">
      <div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
        <AcmeLogo />
        {/* ... */}
      </div>
    </main>
  );
}

좋습니다. 애플리케이션에 두 개의 사용자 정의 글꼴을 추가했습니다! 다음으로 홈 페이지에 히어로 이미지를 추가해 보겠습니다.

Why optimize images?

Next.js 이미지와 같은 정적 자산을 최상위 /public 폴더 아래에 제공할 수 있습니다. /public 내의 파일은 응용 프로그램에서 참조할 수 있습니다. 일반 HTML을 사용하면 다음과 같이 이미지를 추가할 수 있습니다.

<img
  src="/hero.png"
  alt="Screenshots of the dashboard project showing desktop version"
/>

그러나 이는 수동으로 다음을 수행해야 함을 의미합니다.

  • 이미지가 다양한 화면 크기에서 반응하는지 확인하세요.
  • 장치마다 이미지 크기를 지정합니다.
  • 이미지가 로드될 때 레이아웃이 이동하는 것을 방지합니다.
  • 사용자의 표시 영역 밖에 있는 이미지를 지연 로드합니다.

이미지 최적화는 그 자체로 전문화로 간주될 수 있는 웹 개발의 큰 주제입니다. 이러한 최적화를 수동으로 구현하는 대신 next/image 구성 요소를 사용하여 이미지를 자동으로 최적화할 수 있습니다.

The component

구성 요소는 HTML 태그의 확장이며 다음과 같은 자동 이미지 최적화와 함께 제공됩니다.

  • 이미지를 로드할 때 레이아웃이 자동으로 이동하는 것을 방지합니다.
  • 뷰포트가 더 작은 장치로 큰 이미지를 배송하지 않도록 이미지 크기를 조정합니다.
  • 기본적으로 이미지를 지연 로드합니다(이미지가 뷰포트에 들어갈 때 로드됨).
  • 브라우저가 지원하는 경우 WebPAVIF와 같은 최신 형식으로 이미지를 제공합니다.

Adding the desktop hero image

구성 요소를 사용하겠습니다./public 폴더 안을 살펴보면 hero-desktop.pnghero-mobile.png의 두 이미지가 있음을 알 수 있습니다. 이 두 이미지는 완전히 다르며 사용자의 디바이스가 데스크톱인지 모바일인지에 따라 표시됩니다.

/app/page.tsx 파일의 next/image에서 구성 요소를 가져옵니다. 그런 다음 주석 아래에 이미지를 추가합니다.

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';

export default function Page() {
  return (
    // ...
    <div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
      {/* Add Hero Images Here */}
      <Image
        src="/hero-desktop.png"
        width={1000}
        height={760}
        className="hidden md:block"
        alt="Screenshots of the dashboard project showing desktop version"
      />
    </div>
    //...
  );
}

import Image from ‘next/image’;는 Next.js에서 제공하는 내장 컴포넌트인 Image를 가져오는 코드입니다.

이 컴포넌트는 이미지 최적화를 기본적으로 지원하며, 성능과 사용자 경험을 개선하기 위해 설계되었으며 프로젝트의 public 디렉토리를 정적 파일(static files)을 제공하는 기본 위치로 사용합니다.

여기서는 너비를 1000픽셀로, 높이를 760픽셀로 설정합니다. 레이아웃 이동을 피하기 위해 이미지의 너비와 높이를 설정하는 것이 좋으며, 이는 원본 이미지와 동일한 가로 세로 비율이어야 합니다. 이러한 값은 이미지가 렌더링되는 크기가 아니라 가로 세로 비율을 이해하는 데 사용되는 실제 이미지 파일의 크기입니다.

또한 모바일 화면의 DOM에서 이미지를 제거하려면 hidden 클래스를, 데스크톱 화면에 이미지를 표시하려면 md:block 클래스를 사용할 수 있습니다.

  • className=“hidden md:block”
    • hidden: 기본적으로 요소를 숨깁니다. Tailwind의 hidden 클래스는 display: none; 스타일을 적용하여 해당 요소를 렌더링하지 않습니다.
    • md:block: 화면 크기가 md 이상(768px 이상)일 경우 요소를 표시
    • md:hidden: 화면 크기가 md 이상(768px 이상)일 경우 이미지를 숨김.

이제 홈페이지는 다음과 같아야 합니다.

Practice: Adding the mobile hero image

이제 여러분 차례입니다! 방금 추가한 이미지 아래에 hero-mobile.png에 대한 다른 구성 요소를 추가합니다.

  • 이미지의 너비는 560픽셀이고 높이는 620픽셀이어야 합니다.
  • 모바일 화면에 표시되어야 하고 데스크톱에 숨겨져 있어야 합니다 (개발 도구를 사용하여 데스크톱 및 모바일 이미지가 올바르게 교체되었는지 확인할 수 있습니다.)

준비가 되면 아래 코드 스니펫을 확장하여 솔루션을 확인하세요.

/app/page.tsx


이제 홈페이지에 웹 브라우저의 크기를 줄이면 아래와 같이 사용자 지정 글꼴과 영웅 이미지가 나타납니다!

Note

이미지가 변경되지 않는 다면 pnpm dev 명령으로 재실행해보세요.

퀴즈를 풀 시간입니다!

지식을 테스트하고 방금 배운 내용을 확인하세요. True or False: Images without dimensions and web fonts are common causes of layout shift.