Next.js 성능 최적화
프론트엔드 성능 최적화는 웹 애플리케이션의 로딩 속도, 반응성, 사용자 경험(UX)을 개선하는 핵심 요소이다.
이번 글에서는 실제 프로젝트에서 적용한 프론트엔드 성능 최적화 기법을 정리한다.
1. 이미지 최적화
📌 웹사이트의 성능 저하 원인 중 하나는 크기가 큰 이미지
- 고해상도 이미지는 로드 속도를 늦추고 네트워크 비용을 증가
- 최적화된 이미지 제공을 통해 로딩 시간을 줄일 수 있음
✅ 최적화 방법
- WebP, AVIF 같은 최신 이미지 포맷 사용
- Next.js
next/image
컴포넌트 활용 (자동 최적화, Lazy Loading 지원) - CDN(Content Delivery Network) 사용으로 전송 속도 개선
- 반응형 이미지 (
srcset
,sizes
) 활용하여 적절한 해상도로 제공
💡 Next.js의 next/image
를 활용한 이미지 최적화 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Image from "next/image";
const OptimizedImage = () => {
return (
<Image
src="/example.jpg"
alt="최적화된 이미지"
width={800}
height={600}
quality={80}
priority
/>
);
};
export default OptimizedImage;
✔️ quality={80}
: 품질을 유지하면서 파일 크기 감소
✔️ priority
: 중요한 이미지를 우선 로드
2. 코드 스플리팅(Code Splitting)과 Lazy Loading
📌 모든 코드를 한 번에 로드하면 초기 로딩 속도가 느려짐
- 사용자가 필요할 때만 해당 코드를 불러오면 성능 개선 가능
✅ 최적화 방법
- React.lazy + Suspense를 사용하여 동적 임포트
- 라우트 기반 코드 스플리팅 (
React Router
,Next.js Dynamic Import
) - 모달, 차트, 비디오 등 무거운 컴포넌트는 Lazy Loading 적용
💡 React.lazy + Suspense를 활용한 동적 로딩 예제
1
2
3
4
5
6
7
8
9
import { lazy, Suspense } from "react";
const HeavyComponent = lazy(() => import("./HeavyComponent"));
const App = () => (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
✔️ lazy()
를 사용해 필요할 때만 컴포넌트를 로드
✔️ Suspense
의 fallback
속성을 이용해 로딩 UI 제공
💡 Next.js dynamic()
을 활용한 코드 스플리팅
1
2
3
4
5
6
7
8
9
import dynamic from "next/dynamic";
const DynamicChart = dynamic(() => import("./Chart"), { ssr: false });
const Dashboard = () => {
return <DynamicChart />;
};
export default Dashboard;
✔️ 서버 사이드 렌더링(SSR) 비활성화하여 클라이언트에서만 로드
✔️ 초기 번들 크기 감소
3. 메모이제이션을 활용한 렌더링 최적화
📌 불필요한 렌더링을 줄이는 것이 성능 최적화의 핵심
- 리렌더링이 빈번한 경우 성능 저하 발생
useMemo
,useCallback
을 활용해 메모이제이션 적용
✅ 최적화 방법
useMemo
를 사용하여 계산 비용이 큰 연산을 캐싱useCallback
을 사용하여 불필요한 함수 재생성 방지- React.memo를 사용하여 동일한 props가 전달되면 렌더링 방지
💡 useMemo
를 활용한 최적화 예제
1
2
3
4
5
6
7
8
9
10
import { useMemo } from "react";
const ExpensiveCalculation = ({ value }) => {
const result = useMemo(() => {
console.log("Expensive Calculation...");
return value * 2;
}, [value]);
return <div>Result: {result}</div>;
};
✔️ useMemo
를 활용하여 value
가 변경될 때만 연산 수행
💡 useCallback
을 활용한 최적화 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { useState, useCallback } from "react";
const Button = ({ onClick }) => {
return <button onClick={onClick}>Click Me</button>;
};
const App = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
return (
<>
<p>Count: {count}</p>
<Button onClick={handleClick} />
</>
);
};
✔️ useCallback
을 사용하여 handleClick
함수가 매번 새로 생성되지 않도록 최적화
💡 React.memo를 활용한 최적화 예제
1
2
3
4
5
6
import React from "react";
const ExpensiveComponent = React.memo(({ value }) => {
console.log("Rendering...");
return <div>Value: {value}</div>;
});
✔️ 동일한 props
가 전달되면 리렌더링을 방지
4. 서버 사이드 렌더링(SSR)과 정적 사이트 생성(SSG) 활용
📌 클라이언트에서 모든 데이터를 렌더링하면 성능 저하 발생
- SSR을 사용하면 서버에서 미리 렌더링 후 전달하여 초기 로딩 속도를 개선
- SSG는 빌드 시 HTML을 생성하여 정적 파일로 제공
✅ 최적화 방법
- Next.js
getServerSideProps
를 사용하여 서버에서 데이터를 미리 가져오기 - 정적 페이지는
getStaticProps
를 사용하여 SSG 적용
💡 Next.js getServerSideProps
를 활용한 SSR 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export async function getServerSideProps() {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
return {
props: { data }
};
}
const Page = ({ data }) => {
return <div>{data.title}</div>;
};
export default Page;
✔️ 서버에서 데이터를 가져와 HTML을 완성한 후 클라이언트에 전달
💡 Next.js getStaticProps
를 활용한 SSG 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export async function getStaticProps() {
const res = await fetch("https://api.example.com/data");
const data = await res.json();
return {
props: { data }
};
}
const StaticPage = ({ data }) => {
return <div>{data.title}</div>;
};
export default StaticPage;
✔️ 정적 HTML을 빌드 시 생성하여 빠른 로딩 제공
🔹 결론
프론트엔드 성능 최적화는 사용자 경험과 SEO 성능을 높이는데 필수적이다.
✔️ 이미지 최적화(WebP, Lazy Loading, CDN)로 로딩 속도 개선
✔️ 코드 스플리팅과 Lazy Loading으로 불필요한 로드 방지
✔️ 메모이제이션(useMemo
, useCallback
)을 통해 렌더링 최적화
✔️ SSR과 SSG를 활용하여 빠른 페이지 로딩 제공
💡 이러한 기법들을 적용하면 Lighthouse 성능 점수가 크게 향상되며, 실제 사용자 경험도 개선된다. 🚀