한번 깨지고 다시 다진 Next.js

이전 글인 Next.js가 함정이었던 타자 연습 프로젝트 회고에서 겪었던 Next.js에 대한 경험을 바탕으로, 새 프로젝트에 서는 어떻게 적용하고 개선했는지에 대해 정리한 글이다.
들어가며
이전 프로젝트에서 모든 페이지에 use client를 남용하면서 설계의 중요성을 깨달았다. 이번 프로젝트에서는 Next.js App Router의 핵심인 서버/클라이언트 분리 원칙을 설계하는데 집중했다. 어떻게 지킬 것인지 세가지의 규칙을 세우고 개발을 시작했다.
app/폴더 내의Layout과Page는 기본적으로 서버 컴포넌트로 작성한다.components/폴더 내의 기능 단위 컴포넌트 중, 상호작용이 발생하는 최소 단위만use client를 선언한다.- 불필요한 것까지 원자 단위로 쪼개지 않는다.(과분리X)
실전 적용 코드

메인 화면의 배너와 검색창 섹션을 보면서 어떻게 적용했는지 살펴보자.
컴포넌트 계층 구조를 다음과 같이 설계했다.
- Home (Page / Server):
Home페이지 전체 레이아웃, 카테고리별 데이터 페칭 - HomeVisual (Component / Server): 배너 이미지, 타이틀 구성
- HomeSearchBar (Component / Client): 입력과 페이지 이동이 일어나는 검색창 구성
코드분석
Home 페이지는 HomeVisual을 호출하고, HomeVisual은 내부에서 HomeSearchBar를 띄운다.
export default async function Home() {
const supabase = await createClient();
// 생략
return (
<>
<HomeVisual/>
<TemplatePreview .../>
</>
);
}
HomeVisual은 배너부분을 구성한다. 인터렉션이 필요한 검색바만 분리했다.
const HomeSearchBar = dynamic(() =>
import("@/components/(main)/search/SearchBar").then(mod => mod.HomeSearchBar),
{
ssr: true,
loading: () => <div className="h-[46px] ..." /> // skeleton ui
}
);
export function HomeVisual(){
return (
<section>
<Image src="/search.png" alt="banner" priority />
<h1>노션 템플릿, 커버 사진, 아이콘 검색</h1>
<HomeSearchBar />
</section>
)
}