제3장
이전 장에서는 Next.js 애플리케이션을 스타일링하는 방법에 대해 배웠습니다. 사용자 정의 글꼴 및 히어로 이미지를 추가하여 홈 페이지 작업을 계속해 보겠습니다.
다음과 같은 주제들을 다룰 예정입니다.
next/font
를 사용하여 사용자 정의 글꼴 추가하는 방법next/image
를 사용하여 이미지 추가하는 방법- Next.js에서 글꼴과 이미지가 어떻게 최적화되는지
글꼴은 웹사이트 디자인에서 중요한 역할을 합니다. 그러나 프로젝트에서 사용자 정의 글꼴을 사용하면 글꼴 파일을 가져오고 로드해야 하므로 성능에 영향을 미칠 수 있습니다.
Cumulative Layout Shift는 Google이 성능 및 사용자 경험을 평가하는 데 사용하는 측정항목 중 하나입니다. 글꼴을 사용하면, 브라우저가 처음에 대체 또는 시스템 글꼴로 텍스트를 렌더링하고 로드된 후에 사용자 정의 글꼴로 교체될 때 레이아웃 시프트가 발생합니다. 이 교체로 인해 텍스트 크기, 간격 또는 레이아웃이 변경되어 주변 요소가 이동할 수 있습니다.
Next.js는 next/font
모듈을 사용할 때 애플리케이션에서 글꼴을 자동으로 최적화합니다. 이 모듈을 사용하면 글꼴 파일을 빌드 시 다운로드하고 다른 정적 애셋과 함께 호스팅합니다. 이렇게 하면 사용자가 애플리케이션을 방문할 때 글꼴에 대한 추가 네트워크 요청이 없으므로 성능에 영향을 미치지 않습니다.
지금까지 배운 내용을 테스트해 보세요.
Next.js는 글꼴을 어떻게 최적화하나요?
- A: 성능을 향상시키기 위해 추가적인 네트워크 요청을 발생시킵니다.
- B: 모든 사용자 정의 글꼴을 비활성화합니다.
- C: 모든 글꼴을 런타임에 미리로드합니다.
- D: 글꼴 파일을 다른 정적 애셋과 함께 호스팅하여 추가적인 네트워크 요청이 없도록 합니다.
정답 확인
D: 글꼴 파일을 다른 정적 애셋과 함께 호스팅하여 추가적인 네트워크 요청이 없도록 합니다.
이제 애플리케이션에 Google 글꼴을 추가하여 이 작업이 어떻게 수행되는지 살펴보겠습니다!
/app/ui
폴더에서 fonts.ts
라는 새 파일을 만들어서 애플리케이션 전체에서 사용될 글꼴을 관리할 것입니다.
/app/ui/fonts.ts
import { Inter } from 'next/font/google';
그런 다음, next/font/google
모듈에서 Inter
글꼴을 가져옵니다. 이것이 주요 글꼴이 될 것입니다.
/app/ui/fonts.ts
import { Inter } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] });
마지막으로, /app/layout.tsx
에서 <body>
요소에 글꼴을 추가합니다.
/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>
);
}
<body>
요소에 Inter
를 추가함으로써 글꼴이 애플리케이션 전체에 적용됩니다. 여기서는 Tailwind의 antialiased
클래스도 추가했습니다. 이 클래스를 사용하는 것이 필수는 아니지만 글꼴을 부드럽게 만들어줍니다.
브라우저로 이동하여 개발자 도구를 열고 body
요소를 선택하십시오. 이제 Inter
및 Inter_Fallback
이 스타일 아래에 적용된 것을 확인할 수 있습니다. 또한 애플리케이션의 특정 요소에도 글꼴을 추가할 수 있습니다.
이제 당신의 차례입니다! fonts.ts
파일에서 Lusitana
라는 보조 글꼴을 가져와 /app/page.tsx
파일의 <p>
요소에 전달하십시오. 이전과 마찬가지로 서브셋을 지정하는 것 외에도 글꼴 두께를 지정해야합니다.
준비가 되면 아래의 코드 스니펫을 확장하여 정답을 확인하세요.
힌트:
- 글꼴에 어떤 두께 옵션을 전달해야 하는지 확실하지 않다면 코드 편집기에서 TypeScript 오류를 확인하세요.
- Google Fonts 웹사이트를 방문하여
Lusitana
를 검색하여 사용 가능한 옵션을 확인하세요.- 여러 글꼴 추가 및 전체 옵션 목록에 대한 문서를 참조하세요.
솔루션 보기
/app/ui/fonts.ts
import { Inter, Lusitana } from 'next/font/google';
export const inter = Inter({ subsets: ['latin'] });
export const lusitana = Lusitana({
weight: ['400', '700'],
subsets: ['latin'],
});
/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import { lusitana } from '@/app/ui/fonts';
export default function Page() {
return (
// ...
<p
className={`${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal`}
>
<strong>Welcome to Acme.</strong> This is the example for the{' '}
<a href="https://nextjs.org/learn/" className="text-blue-500">
Next.js Learn Course
</a>
, brought to you by Vercel.
</p>
// ...
);
}
마지막으로 <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>
);
}
좋습니다! 애플리케이션에 두 개의 사용자 정의 글꼴이 추가되었습니다! 이제 홈 페이지에 히어로 이미지를 추가해 보겠습니다.
Next.js는 이미지와 같은 정적 자산을 최상위 /public
폴더 아래에서 제공할 수 있습니다. /public
내부의 파일은 애플리케이션에서 참조할 수 있습니다.
/public
폴더 내부를 살펴보면 두 개의 이미지, hero-desktop.png
와 hero-mobile.png
가 있습니다. 이 두 이미지는 완전히 다르며 사용자의 기기가 데스크톱인지 모바일인지에 따라 표시됩니다.
일반적인 HTML에서는 이미지를 다음과 같이 추가합니다.
<img
src="/hero.png"
alt="데스크톱 및 모바일 버전의 대시보드 프로젝트 스크린샷"
/>
그러나 이렇게 하면 다음을 수동으로 수행해야 합니다.
- 이미지가 다양한 화면 크기에 반응적으로 표시되도록 보장합니다.
- 다양한 기기에 대한 이미지 크기를 지정합니다.
- 이미지가 로드됨에 따라 레이아웃 시프트를 방지합니다.
- 뷰포트 외부에 있는 이미지를 지연로드합니다.
이미지 최적화는 웹 개발에서 큰 주제이며 그 자체로 전문 분야로 간주될 수 있습니다. 이러한 최적화를 수동으로 구현하는 대신 next/image
컴포넌트를 사용하여 이미지를 자동으로 최적화할 수 있습니다.
<Image>
컴포넌트는 HTML <img>
태그의 확장이며 다음과 같은 자동 이미지 최적화 기능을 제공합니다.
- 이미지가 로드될 때 자동으로 레이아웃 시프트 방지.
- 뷰포트에 들어올 때 이미지 크기를 조절하여 작은 뷰포트 기기로 큰 이미지를 전송하지 않도록 함.
- 기본적으로 이미지를 지연로드 (이미지가 뷰포트에 진입할 때 로드).
- 브라우저가 지원하는 경우 WebP 및 AVIF와 같은 현대적인 포맷으로 이미지 제공.
<Image>
컴포넌트를 사용해보겠습니다.
/app/page.tsx
파일 안에, next/image
에서 컴포넌트를 가져와 주석 아래에 이미지를 추가하세요:
/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
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">
{/_ 여기에 히어로 이미지 추가 _/}
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block"
alt="데스크톱 및 모바일 버전을 보여주는 대시보드 프로젝트의 스크린샷"
/>
</div>
//...
);
}
여기서 이미지의 width
를 1000
으로, height
를 760
으로 설정하고 있습니다. 레이아웃 이동을 방지하기 위해 이미지의 width
와 height
를 소스 이미지와 동일한 종횡비로 설정하는 것이 좋습니다.
또한, 모바일 화면에서 이미지를 제거하기 위해 hidden
클래스를, 데스크톱 화면에서 이미지를 보여주기 위해 md:block
클래스를 사용하고 있습니다.
이제 홈페이지는 다음과 같아야 합니다:
이제 여러분의 차례입니다! 방금 추가한 이미지 아래에 mobile-hero.png
에 대한 또 다른 <Image>
컴포넌트를 추가하세요.
- 이미지의
width
는560
이고height
는620
픽셀로 설정하세요. - 모바일 화면에서 보이고 데스크톱에서는 숨겨져야 합니다 - 데스크톱 및 모바일 이미지가 올바르게 교체되었는지 확인하려면 개발 도구를 사용하세요.
준비가 되었으면 아래의 코드 스니펫을 확장하여 정답을 확인하세요.
솔루션 보기
/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
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">
{/* 히어로 이미지 추가 */}
<Image
src="/hero-desktop.png"
width={1000}
height={760}
className="hidden md:block"
alt="데스크톱 및 모바일 버전을 보여주는 대시보드 프로젝트의 스크린샷"
/>
<Image
src="/hero-mobile.png"
width={560}
height={620}
className="block md:hidden"
alt="모바일 버전을 보여주는 대시보드 프로젝트의 스크린샷"
/>
</div>
//...
);
}
좋습니다! 이제 홈페이지에는 커스텀 폰트와 히어로 이미지가 있습니다.
여러분이 방금 배운 내용을 테스트하고 학습한 내용을 확인하세요.
참/거짓: 크기를 지정하지 않은 이미지와 웹 폰트는 레이아웃 이동의 일반적인 원인입니다.
- A: 참
- B: 거짓
정답 확인
A: 참
이러한 주제에 대해 더 알아보려면 원격 이미지 최적화 및 로컬 글꼴 파일 사용과 관련된 추가 정보를 확인하세요. 글꼴 및 이미지에 대해 더 깊게 파고들고 싶다면 다음을 참고하세요: