Next.js 프로젝트, 제대로 셋업하고 있습니까?

Next.js 프로젝트, 제대로 셋업하고 있습니까?

Hydration Mismatch부터 Cache Component, Biome 전환, TypeScript 모범 사례까지—현대 Next.js 셋업의 고통 포인트 4가지를 한 번에 짚습니다.

Next.js App Router Hydration Mismatch Cache Component Biome ESLint TypeScript 모범 사례 SSR 렌더링 프론트엔드 셋업
광고

매번 새 Next.js 프로젝트를 시작할 때마다 느끼는 게 있습니다. '이번엔 제대로 하자'고 다짐하는데, 막상 며칠 지나면 콘솔에 빨간 경고가 하나씩 쌓이고, 번들 사이즈는 예상보다 두 배, CI 린팅은 느릿느릿... 그 고통의 패턴이 매번 비슷하다는 거죠. 최근 프론트엔드 커뮤니티에서 이 고통 포인트 네 가지를 정면으로 다룬 글들이 나왔습니다. 하나씩 짚어볼게요.


1. Hydration Mismatch: '어떤 라이브러리 문제냐'보다 '입력이 어디서 갈라지냐'를 먼저 보세요

Warning: Text content does not match server-rendered HTML. 이 메시지, App Router 쓰면서 한 번도 안 본 분 있으면 손 들어보세요. 저는 못 들겠습니다. velog의 nowrobin님 글이 이 문제를 구조적으로 정리했는데, 핵심 문장 하나가 머리를 탁 치더라고요.

"Hydration mismatch는 React의 버그가 아니다. 서버와 클라이언트가 서로 다른 입력을 받았기 때문에 생기는 일이다."

맞아요. 우리가 흔히 하는 실수가 suppressHydrationWarning 붙이거나, Zustand 탓하거나, i18n 라이브러리 버전 의심하는 건데—이건 증상 치료입니다. 진짜 원인은 서버 렌더링 환경에서 localStorage, navigator.language, window 같은 브라우저 전용 API를 첫 렌더 입력으로 쓰는 순간 발생하는 비결정적 렌더링이에요.

App Router는 Pages Router와 다릅니다. 서버 컴포넌트가 기본값이고 HTML이 서버에서 먼저 확정되기 때문에, 예전엔 그냥 넘어가던 코드가 이제 경고를 뱉습니다. 'use client'를 남발해서 피해가는 건 서버 컴포넌트의 이점을 통째로 버리는 거고요. 처방은 간단합니다. 첫 렌더는 결정적이어야 한다—브라우저 API는 hydration 이후에, persist 상태 분기는 hydrated 플래그가 true가 된 다음에, 언어 설정은 쿠키나 URL 기반으로 서버·클라이언트가 같은 값을 보도록. Figma에서 볼 때 레이아웃이 깔끔했는데 실제 구현하면 Layout shift가 생기는 이유가 바로 여기 있습니다.


2. Next.js 16 Cache Component: '페이지 단위 블로킹'에서 '컴포넌트 단위 블로킹'으로

velog의 rlaugs15님이 Next.js 16 Cache Component를 직접 코드를 짜보며 정리한 글인데, 제가 보기엔 이게 단순한 API 추가가 아니라 렌더링 패러다임의 전환입니다. 기존 SSR은 페이지 전체가 데이터 준비가 끝날 때까지 기다렸죠. SuspensePostList 컴포넌트로 분리하면 전체 블로킹이 아니라 컴포넌트 단위 블로킹이 됩니다—이게 스트리밍 렌더링의 실체예요.

여기서 'use cache'가 등장합니다. Next.js 16의 기본 철학이 바뀌었어요. 예전엔 프레임워크가 알아서 static인지 dynamic인지 추측했는데, 이제는 기본이 dynamic, static 경계는 개발자가 직접 선언하는 구조입니다. 'use cache'를 함수에 붙이면 반환값이 캐싱되고, 컴포넌트에 붙이면 렌더링 결과 HTML까지 저장됩니다. 단, 컴포넌트 캐싱은 요청과 완전히 무관한 순수 UI일 때만 안전해요—요청마다 달라지는 값이 섞이면 캐시가 오염됩니다.

사용자 입장에서 이 변화가 체감되는 건 'First Byte'가 빨라지는 것입니다. Core Web Vitals 기준으로 TTFB와 LCP에 직접적인 영향을 주죠. 기획자가 "왜 이 페이지는 이렇게 느리냐"고 물을 때, 이제는 컴포넌트 단위로 블로킹 구간을 찾아 대답할 수 있게 됐습니다.


3. Biome vs ESLint: 56배 빠른데, 지금 당장 갈아타야 할까요?

dev.to에 올라온 Biome vs ESLint 비교 글이 화제인데, 숫자가 자극적이긴 합니다. 10,000개 파일 린팅에 ESLint는 45초, Biome는 0.8초. 56배 차이. Rust로 컴파일된 네이티브 바이너리 vs Node.js JavaScript AST 파서의 아키텍처 차이에서 오는 필연적인 결과예요.

저도 솔직히 eslint.config.js, .prettierrc, .prettierignore, eslint-config-prettier... 파일 네 개 관리하다가 팀원이랑 "Prettier 통합 방식 뭐로 할 거야" 논쟁한 경험이 한두 번이 아닙니다. Biome는 biome.json 하나, npm 의존성 0개(단일 바이너리)로 린팅과 포매팅을 다 처리합니다. 신규 프로젝트라면 npx @biomejs/biome init 한 줄로 끝이에요.

그런데 기존 프로젝트라면 좀 더 따져봐야 합니다. Biome v2.x 기준으로 ESLint 핵심 규칙의 약 90%, TypeScript 규칙은 강력하게 내장, React/JSX도 웬만한 건 커버합니다. 하지만 Vue·Angular 프레임워크 플러그인, 팀 자체 커스텀 ESLint 규칙, 접근성(a11y) 쪽 세밀한 규칙은 아직 ESLint가 우위입니다. 제 결론은 이렇습니다—React + TypeScript 신규 프로젝트면 Biome로 바로 가세요. 기존 프로젝트는 플러그인 의존도 체크 먼저. CI 린팅 시간이 2~3분에서 10초 미만으로 줄어드는 건 Lighthouse 점수만큼이나 실체적인 개선이니까요.


4. TypeScript 제대로 쓰고 있습니까? '타입 더 쓰기'가 아니라 '경계 명확히 하기'

dev.to의 타입스크립트 모범 사례 글이 불편한 진실을 꺼내놓습니다. JSON.parse(body) as User—이거 본 적 있죠? 저도 써봤고, 사실 지금도 급하면 씁니다. 근데 이건 TypeScript가 일하는 게 아니라 개발자가 타입 검사에서 이탈하는 겁니다. TypeScript는 컴파일 타임, 실패는 런타임. 그 갭이 가장 크게 드러나는 곳이 API 응답, 환경변수, DB 조회 결과 같은 시스템 경계예요.

처방은 Zod(또는 Valibot)로 경계에서 런타임 검증하고, 내부로 들어오면 TypeScript가 가드를 맡는 구조입니다. 그리고 상태 모델링—loading?: boolean; data?: User; error?: string 이런 optional soup 대신 discriminated union으로 불가능한 상태 자체를 타입 시스템에서 제거하는 거요. UI 코드에서 if (loading && data) 같은 방어 코드가 줄어드는 건 컴포넌트 코드가 깔끔해지는 것 이상의 의미입니다—UI 상태 전환이 명확해지면 애니메이션·트랜지션 설계도 깔끔해집니다.

한 가지 더. 타입이 복잡할수록 팀에서 아무도 안 건드리는 코드가 됩니다. type ApiResult<T> = T extends { error: infer E } ? ... 이런 거 보면 저도 주석 달고 싶어집니다. 가장 주니어 팀원이 읽고 수정할 수 있는 타입이 좋은 타입이에요. TypeScript는 컴파일러가 강제하는 팀원 간 커뮤니케이션 도구라는 관점이 중요합니다.


결국 이 네 가지는 같은 이야기입니다

Hydration Mismatch, Cache Component, Biome 전환, TypeScript 모범 사례—표면적으로는 다른 주제처럼 보이지만, 공통 맥락이 있습니다. "암묵적 가정을 명시적 선언으로 바꾸는 것"이요. 서버·클라이언트 입력을 통일하고(Hydration), 캐싱 경계를 직접 선언하고(Cache Component), 툴체인 설정을 단순화하고(Biome), 타입 경계를 런타임까지 확장하는 것(TypeScript)—모두 같은 방향을 가리킵니다.

프론트엔드 개발 환경이 점점 복잡해지면서 "돌아가면 됐지"가 통하지 않는 레이어가 늘었습니다. 1px 어긋난 여백이 눈에 거슬리듯, 구조적으로 어긋난 셋업은 결국 어느 날 밤 콘솔 빨간 불로 돌아옵니다. 새 프로젝트 시작 전에, 아니면 기존 프로젝트 리팩토링 전에—이 네 가지를 체크리스트로 삼아보세요. 처음부터 제대로 하는 게 나중에 밤새는 것보다 낫습니다.

출처

더 많은 AI 트렌드를 Seedora 앱에서 확인하세요