performance2025-06-13·9 min·27/348

next/image priority 속성으로 LCP 최적화하기

Next.js Image 컴포넌트의 priority 속성을 활용하여 Largest Contentful Paint를 개선하는 방법을 알아봅니다.

next/image priority 속성으로 LCP 최적화하기

Introduction

Largest Contentful Paint(LCP)는 페이지 로딩 성능을 측정하는 Core Web Vitals 중 하나입니다. Next.js의 priority 속성을 사용하면 hero 이미지나 로고 같은 첫 화면 이미지를 빠르게 로드할 수 있습니다. 이 글에서는 priority 속성의 동작 원리와 최적화 전략을 다룹니다.

Environment

# 프로젝트 구조
my-app/
├── app/
│   ├── page.tsx
│   └── components/
│       └── Hero.tsx
├── public/
│   └── images/
│       ├── hero.jpg
│       └── logo.png
└── package.json

# 기술 스택
Next.js: 14.2.5
React: 18.3.1
Lighthouse: 11.0

Problem

기본 Image 컴포넌트는 lazy loading을 적용하므로 LCP에 부정적 영향을 줄 수 있습니다:

// ❌ LCP 이미지에 lazy loading 적용
import Image from 'next/image';

export function Hero() {
  return (
    
{/* 이 이미지도 lazy loading되어 지연 로드됨 */} Hero image
); }
# Lighthouse 결과
Largest Contentful Paint (LCP): 4.2s
  - 이미지 로딩 지연이 주요 원인

Analysis

priority 속성을 설정하면:

  1. loading="lazy" 대신 loading="eager" 적용
  2. <link rel="preload"> 태그 자동 생성
  3. 브라우저가 이미지를 우선적으로 로드

Solution

1. 기본 priority 설정

// app/components/Hero.tsx
import Image from 'next/image';

export function Hero() {
  return (
    
Hero image
); }

2. 조건부 priority 설정

// app/components/DynamicHero.tsx
import Image from 'next/image';

interface DynamicHeroProps {
  isAboveFold: boolean;
  src: string;
  alt: string;
}

export function DynamicHero({ isAboveFold, src, alt }: DynamicHeroProps) {
  return (
    
{alt}
); }

3. 복수 LCP 이미지 처리

// app/page.tsx
import Image from 'next/image';

export default function HomePage() {
  return (
    
{/* 첫 번째 LCP 이미지 */} Hero {/* 두 번째 LCP 이미지 (슬라이드쇼 등) */} Featured {/* 일반 이미지는 lazy loading 유지 */} Content
); }

4. 뷰포트 기반 동적 priority

// hooks/useViewport.ts
'use client';

import { useState, useEffect } from 'react';

export function useViewport() {
  const [isMobile, setIsMobile] = useState(false);
  
  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768);
    };
    
    checkMobile();
    window.addEventListener('resize', checkMobile);
    
    return () => window.removeEventListener('resize', checkMobile);
  }, []);
  
  return { isMobile };
}
// app/components/ResponsiveHero.tsx
'use client';

import Image from 'next/image';
import { useViewport } from '@/hooks/useViewport';

export function ResponsiveHero() {
  const { isMobile } = useViewport();
  
  return (
    
Hero
); }

5. priority 사용 시 주의사항

// ❌ 과도한 priority 사용 (성능 저하)
export function BadExample() {
  return (
    
{/* 모든 이미지에 priority 설정 - 안 됨 */} 1 2 3 4 5
); } // ✅ 올바른 사용 (LCP 이미지만 priority) export function GoodExample() { return (
Hero 1 2
); }

6. 빌드 타임 이미지 최적화

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    // priority 이미지에 대한 추가 설정
    minimumCacheTTL: 60 * 60 * 24 * 30, // 30일
    
    // 기기별 크기 설정
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
    
    // 이미지 포맷 설정
    formats: ['image/avif', 'image/webp'],
  },
};

module.exports = nextConfig;

Lessons Learned

  1. LCP 이미지만 priority 적용: 페이지당 1-2개의 LCP 이미지만 priority 설정
  2. above-the-fold 판단: 뷰포트 위에 보이는 이미지만 priority 적용
  3. sizes 속성 병행: prioritysizes를 함께 사용하여 반응형 이미지 최적화
  4. 성능 측정: Lighthouse로 priority 적용 전후 LCP 비교

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.