frontend

[Next.js] - 코드잇(단기 심화) 프로젝트 성능 최적화

프론트엔드코린이 2025. 4. 18. 17:04

✅ 프로젝트 성능 최적화 — 어떻게 접근했는가?

Next.js의 가장 큰 장점 중 하나는 기본적으로 자동 코드 분할SSR(서버사이드 렌더링)을 지원한다는 점이다.

하지만 프로젝트 규모가 커지거나 다양한 외부 라이브러리를 쓰다 보면 불필요한 리렌더링, 번들 크기 증가, 느린 TTFB 등이 성능 이슈로 이어질 수 있다.

단기 심화 과정에서 배운 이론에 그치지 않고, 개인적으로 블로그와 기술 아티클을 찾아보며 실습을 병행했습니다.
이러한 능동적인 학습을 통해 최적화 전략들을 빠르게 이해하고 적용할 수 있었으며, 새로운 기술을 빠르게 익히는 데 강점을 가지고 있음을 직접 확인할 수 있었다.

  1. 이미지 최적화
    next/image를 활용해 lazy loading 및 자동 리사이징 적용
    → 빠른 이미지 로딩이 필요할 땐 priority 속성을 사용해 최우선으로 적용
    → 이미지 최적화에 있어선 next/image를 사용했고, 특히 fill 속성을 적용하여 반응형 레이아웃에 맞춰 부모 요소를 가득 채우도록 설정함으로써 이미지 성능을 향상시켰다.
  2. SSR 적용을 통한 LCP시간 단축 및 SEO 개선
    → 초기에는 CSR(Client-Side Rendering) 방식으로 구현되어 있어 첫 페이지 로딩이 느리고 SEO에 불리한 구조였다.
    → 이후 SSR(Server-Side Rendering) 방식으로 전환하면서 초기 로딩 속도 개선검색엔진 노출 최적화(SEO) 효과를 동시에 얻을 수 있었다.
  3. React 최적화 테크닉
    React.memo를 적절히 활용해 불필요한 리렌더링 방지

1. priority 사용으로 핵심 콘텐츠 로딩 속도 향상 → 더 빠른 UI 응답성 제공

priority 적용 전

priority 적용 후

//이미지 섹션
function ImageSection({ src, alt }: { src: string; alt: string }) {
    return (
        <div className='w-full md:w-[256px] h-[156px] bg-white sm:border-r-2 relative'>
            <Image
                alt={alt}
                src={src}
                fill
                priority
                className='h-full w-full object-fit'
            />
        </div>
    );
}
  • 또한, fill 속성을 사용하면 부모 요소의 영역을 가득 채우는 반응형 이미지를 만들어 이미지 최적화를 진행했습니다.

2. CSR에서 SSR로 전환 → LCP 단축 & SEO 점수 향상까지

  • 초기 개발시에는 CSR 방식으로 데이터패칭 후 브라우저에 렌더링하는 방식으로 개발
  • 메인 홈 useInfiniteQuery를 사용하여 무한스크롤을 구현

CSR 적용 전

CSR 적용 전

CSR 적용 전


  • SSR 방식으로 데이터 패칭 후 브라우저에 렌더링 하는 방식으로 리팩토링
  • prefetchInfiniteQuery를 사용하여 초기 데이터를 미리 불러오는 형식으로 변경

SSR 적용 후

SSR 적용 후

SSR 적용 후

※ CSR과 SSR 방식에서 Lighthouse 검사를 통해 LCP를 3.9s → 0.6s(84.6% 단축), SEO 점수는 63 → 100으로 개선하며 성능 최적화를 달성했습니다.


3. React.memo 적용 → 불필요한 렌더링 방지로 성능 최적화

컴포넌트 리렌더링 발생

React.memo 적용으로 리렌더링 방지

 

리렌더링이 불필요한 컴포넌트가 state 변경에 따라 반복적으로 리렌더링되는 현상이 발생해 UI 성능 저하가 나타났습니다.  
이에 `React.memo`를 적용하여 동일 props로 호출되는 컴포넌트의 리렌더링을 방지하였고,  
사용자 인터랙션 시 화면 깜빡임 제거, 불필요한 DOM 연산 최소화를 통해 렌더링 성능을 개선할 수 있었습니다.

 

※ 해결 방법 : React.memo를 사용하여 불필요한 리렌더링을 방지

export default function CardListInfinite() {
	const router = useRouter();
	const pathname = usePathname();
	const { ref, inView } = useInView();
	const [isDelayed, setIsDelayed] = useState(false);

	return (
		<div className='flex flex-col items-center gap-6'>
			모달에 관련된 내용 
		</div>
	);
}
  • 위 컴포넌트 자체를 React.memo 함수를 사용해 컴포넌트 자체를 한번 감싼 형식으로 수정
const CardListInfinite = React.memo(function CardListInfinite() {
	const router = useRouter();
	const pathname = usePathname();
	const { ref, inView } = useInView();
	const [isDelayed, setIsDelayed] = useState(false);

	return (
		<div className='flex flex-col items-center gap-6'>
			모달에 관련된 내용 
		</div>
	);
});

 

 


 

코드잇 단기심화과정 팀 프로젝트 회고

1. 협업 구조를 처음부터 끝까지 경험해볼 수 있었다

- 단순히 코드를 나누는 수준이 아니라, 기획 → 디자인 → 개발 → 발표까지 한 사이클을 직접 겪으면서 협업의 본질을 체감할 수 있었다. 특히 역할 분담과 소통의 중요성을 크게 느꼈다.

2. Git & GitHub, Jira 협업 방식에 익숙해졌다

- jira를 활용한 주 단위 스프린트, 브랜치 전략, PR 리뷰를 통해 실제 실무처럼 Git을 사용하는 경험을 할 수 있었다. git pull 한 줄에도 책임감이 생겼고, 코드 리뷰 문화를 경험해본 것도 큰 수확이다.

3. 처음 해보는 SSR과 무한스크롤 구현이 기억에 남는다

- Next.js의 SSR과 React Query의 useInfiniteQuery를 활용해 무한스크롤을 구현하면서, 성능 최적화와 UX 사이의 밸런스를 고민해보게 되었다. 성능 개선 효과를 직접 수치로 비교해본 것도 인상 깊었다.

4. 빠르게 성장할 수 있다는 자신감을 얻었다

- 주어진 시간이 짧았지만, 각자 맡은 부분을 책임감 있게 진행했고 꾸준한 피드백과 공유를 통해 빠르게 기능을 완성할 수 있었다. 스스로 기술 습득 속도에 자신감이 붙었다.

5. 개발 외적인 요소의 중요성도 느꼈다

- 좋은 코드뿐 아니라, 명확한 커뮤니케이션, 일정 조율, 발표자료 구성 등 비개발적인 역량도 프로젝트의 완성도를 좌우한다는 걸 몸소 느꼈다.

 

 

프로젝트에 적극 참여하여 뜻깊은 상장 수여🙊