운영 환경 체크리스트
Next.js 애플리케이션을 운영 환경에 배포하기 전에, 최상의 사용자 경험, 성능 및 보안을 위해 구현을 고려해야 할 몇 가지 최적화와 패턴이 있습니다.
이 페이지는 애플리케이션 구축 중, 운영 환경 배포 전, 그리고 배포 후에 참조할 수 있는 모범 사례를 제공합니다. 또한 알아두어야 할 자동 Next.js 최적화에 대해서도 다룹니다.
자동 최적화
이러한 Next.js 최적화는 기본적으로 활성화되어 있으며 추가 구성이 필요하지 않습니다:
- 서버 컴포넌트: Next.js는 기본적으로 서버 컴포넌트를 사용합니다. 서버 컴포넌트는 서버에서 실행되며, 클라이언트에서 렌더링하기 위해 JavaScript가 필요하지 않습니다. 따라서 클라이언트 측 JavaScript 번들 크기에 영향을 미치지 않습니다. 필요에 따라 상호작용을 위해 클라이언트 컴포넌트를 사용할 수 있습니다.
- 코드 분할: 서버 컴포넌트는 라우트 세그먼트별로 자동 코드 분할을 가능하게 합니다. 또한 적절한 경우 클라이언트 컴포넌트와 서드파티 라이브러리의 지연 로딩을 고려할 수 있습니다.
- 프리페칭: 새 라우트로의 링크가 사용자의 뷰포트에 들어오면, Next.js는 백그라운드에서 해당 라우트를 프리페치합니다. 이로 인해 새 라우트로의 네비게이션이 거의 즉각적으로 이루어집니다. 필요한 경우 프리페칭을 비활성화 할 수 있습니다.
- 정적 렌더링: Next.js는 빌드 시 서버와 클라이언트 컴포넌트를 정적으로 렌더링하고 렌더링된 결과를 캐시하여 애플리케이션의 성능을 향상시킵니다. 필요한 경우 특정 라우트에 대해 동적 렌더링을 사용하도록 설정할 수 있습니다.
- 캐싱: Next.js는 데이터 요청, 서버 및 클라이언트 컴포넌트의 렌더링 결과, 정적 리소스 등을 캐시하여 서버, 데이터베이스 및 백엔드 서비스에 대한 네트워크 요청 수를 줄입니다. 필요한 경우 캐싱을 비활성화 할 수 있습니다.
이러한 기본 설정은 애플리케이션의 성능을 향상시키고, 각 네트워크 요청에서 전송되는 데이터의 양과 비용을 줄이는 것을 목표로 합니다.
개발 과정에서
애플리케이션을 구축하는 동안, 최상의 성능과 사용자 경험을 보장하기 위해 다음 기능들을 사용하는 것을 권장합니다:
라우팅 및 렌더링
- 레이아웃: 레이아웃을 사용하여 페이지 간 UI를 공유하고 네비게이션 시 부분 렌더링을 가능하게 합니다.
<Link>
컴포넌트:<Link>
컴포넌트를 사용하여 클라이언트 측 네비게이션 및 프리페칭을 구현합니다.- 에러 처리: 커스텀 에러 페이지를 만들어 운영 환경에서 전체 에러와 404 에러를 우아하게 처리합니다.
- 컴포지션 패턴: 서버 및 클라이언트 컴포넌트에 대한 권장 컴포지션 패턴을 따르고, 클라이언트 측 JavaScript 번들이 불필요하게 증가하는 것을 방지하기 위해
"use client"
경계의 배치를 확인합니다. - 동적 함수:
cookies()
와searchParams
prop과 같은 동적 함수는 전체 라우트를 동적 렌더링으로 옵트인한다는 점을 인지하세요 (루트 레이아웃에서 사용된 경우 전체 애플리케이션에 영향을 미칩니다). 동적 함수 사용이 의도적인지 확인하고 적절한 경우<Suspense>
경계로 감싸세요.
알아두면 좋은 점: 부분 프리렌더링(실험적)은 전체 라우트를 동적 렌더링으로 설정하지 않아도, 라우트의 일부를 동적으로 만들 수 있게 해줍니다.
데이터 가져오기 및 캐싱
- 서버 컴포넌트: 서버 컴포넌트를 사용하여 서버에서 데이터를 페칭하는 이점을 활용합니다.
- 라우트 핸들러: 클라이언트 컴포넌트에서 백엔드 리소스에 접근하기 위해 라우트 핸들러를 사용합니다. 하지만 추가적인 서버 요청을 피하기 위해 서버 컴포넌트에서 라우트 핸들러를 호출하지 마세요.
- 스트리밍: 로딩 UI와 React Suspense를 사용하여 UI를 서버에서 클라이언트로 점진적으로 전송하고, 데이터를 페칭하는 동안 전체 라우트가 차단되는 것을 방지합니다.
- 병렬 데이터 가져오기: 적절한 경우 병렬로 데이터를 페칭하여 네트워크 워터폴을 줄입니다. 또한 적절한 경우 데이터 프리로딩을 고려하세요.
- 데이터 캐싱: 데이터 요청이 캐시되고 있는지 확인하고, 적절한 경우 캐싱을 옵트인합니다.
fetch
를 사용하지 않는 요청이 캐시되고 있는지 확인하세요. - 정적 이미지:
public
디렉토리를 사용하여 이미지와 같은 애플리케이션의 정적 리소스을 자동으로 캐시합니다.
UI 및 접근성
-
폼 및 유효성 검사: 서버 액션을 사용하여 폼 제출, 서버 측 유효성 검사 및 오류 처리를 관리합니다.
-
폰트 모듈: 폰트 모듈을 사용하여 폰트를 최적화합니다. 이 모듈은 자동으로 폰트 파일을 다른 정적 리소스와 함께 호스팅하고, 외부 네트워크 요청을 제거하며, 레이아웃 시프트를 줄입니다.
-
<Image>
컴포넌트: Image 컴포넌트를 사용하여 이미지를 최적화합니다. 이 컴포넌트는 자동으로 이미지를 최적화하고, 레이아웃 시프트를 방지하며, WebP나 AVIF와 같은 최신 형식으로 이미지를 제공합니다. -
<Script>
컴포넌트: Script 컴포넌트를 사용하여 서드파티 스크립트를 최적화합니다. 이 컴포넌트는 자동으로 스크립트를 지연시키고 메인 스레드를 차단하지 않도록 합니다. -
ESLint: 내장된
eslint-plugin-jsx-a11y
플러그인을 사용하여 접근성 문제를 조기에 발견합니다.
보안
-
오염: 데이터 객체 및/또는 특정 값을 오염시켜 민감한 데이터가 클라이언트에 노출되는 것을 방지합니다.
-
환경 변수:
.env.*
파일이.gitignore
에 추가되어 있는지 확인하고 공개 변수만NEXT_PUBLIC_
접두사를 사용하도록 합니다. -
콘텐츠 보안 정책: 콘텐츠 보안 정책을 추가하여 크로스 사이트 스크립팅, 클릭재킹 및 기타 코드 주입 공격과 같은 다양한 보안 위협으로부터 애플리케이션을 보호하는 것을 고려하세요.
메타데이터 및 SEO
- 메타데이터 API: 메타데이터 API를 사용하여 페이지 제목, 설명 등을 추가함으로써 애플리케이션의 검색 엔진 최적화(SEO)를 개선합니다.
- 오픈 그래프(OG) 이미지: OG 이미지를 생성하여 애플리케이션의 소셜 미디어 공유를 준비합니다.
- 사이트맵과 로봇: 사이트맵과 robots 파일을 생성하여 검색 엔진이 페이지를 크롤링하고 인덱싱하는 데 도움을 줍니다.
타입 안전성
- TypeScript와 TS 플러그인: TypeScript와 TypeScript 플러그인을 사용하여 더 나은 타입 안전성을 확보하고 오류를 조기에 발견할 수 있습니다.
운영 환경 배포 전
운영 환경에 배포하기 전에 next build
를 실행하여 애플리케이션을 로컬에서 빌드하고 빌드 오류를 포착한 다음, next start
를 실행하여 운영 환경과 유사한 환경에서 애플리케이션의 성능을 측정할 수 있습니다.
핵심 웹 바이탈
-
Lighthouse: 시크릿 모드에서 Lighthouse를 실행하여 사용자가 사이트를 어떻게 경험할지 더 잘 이해하고 개선이 필요한 영역을 파악합니다. 이는 시뮬레이션된 테스트이므로 실제 데이터(예: 핵심 웹 바이탈)를 확인하는 것과 함께 사용해야 합니다.
-
useReportWebVitals
훅: 이 훅을 사용하여 핵심 웹 바이탈 데이터를 분석 도구로 전송합니다.
번들 분석
@next/bundle-analyzer
플러그인을 사용하여 JavaScript 번들의 크기를 분석하고 애플리케이션의 성능에 영향을 미칠 수 있는 큰 모듈과 종속성을 식별합니다.
추가로, 다음 도구들은 새로운 종속성을 애플리케이션에 추가할 때의 영향을 이해하는 데 도움이 될 수 있습니다:
배포 후
애플리케이션을 어디에 배포하느냐에 따라 애플리케이션의 성능을 모니터링하고 개선하는 데 도움이 되는 추가 도구와 통합을 사용할 수 있습니다.
Vercel 배포의 경우, 다음을 권장합니다:
- Analytics: 고유 방문자 수, 페이지 뷰 등을 포함한 애플리케이션의 트래픽을 이해하는 데 도움이 되는 내장 분석 대시보드입니다.
- Speed Insights: 방문자 데이터를 기반으로 한 실제 성능 인사이트로, 웹사이트가 실제 환경에서 어떻게 수행되고 있는지에 대한 실용적인 뷰를 제공합니다.
- 로깅: 런타임 및 활동 로그를 통해 문제를 디버깅하고 운영 환경에서 애플리케이션을 모니터링할 수 있습니다.