Next.js를 넘어: TanStack Start와 풀스택 React 개발의 미래

발행: (2025년 12월 15일 오전 07:08 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

배경

4~5년 동안 Next.js로 개발하면서, 나는 이 프레임워크가 단순하고 예측 가능한 도구에서 훨씬 더 복잡한 형태로 진화하는 모습을 지켜봤다. Next.js는 올바른 사용 사례에선 여전히 굉장히 강력하지만, 끊임없는 정신 모델 변화는 많은 개발자에게 피로감을 주고 있다.

Next.js가 처음 출시됐을 때는 정말 혁신적이었다. 그 이전에 프로덕션 수준의 React 앱을 만들려면 webpack, Babel, 라우팅 라이브러리, 그리고 수많은 다른 도구들을 각각 설정해야 했고, 각 도구마다 고유한 설정 트릭이 있었다. Next.js는 “여기 한 가지가 있어. 라우팅, 렌더링, 최적화, 모든 걸 다 처리해. 그냥 써.”라고 말했다.

Pages Router는 단순하고 예측 가능했다: 직관적인 파일 기반 라우팅, 자연스러운 API 라우트, 그리고 일관된 정신 모델.

Next.js의 문제점

Next.js 13부터는 상황이 덜 안정적이 되었다. React Server Components(RSC)가 App Router와 함께 도입되면서 프레임워크는 기본 가정을 자주 바꾸기 시작했다.

  • 서버‑우선 기본값 – “use client”, “use server”, 그리고 “use cache” 지시어가 패러다임을 뒤바꾸어 빈번한 하이드레이션 문제를 일으켰다.
  • 캐싱 모델 변화 – Next.js 14는 기본적으로 모든 것을 캐시했지만, Next.js 15(Turbopack 사용)에서는 이를 뒤집어 캐시를 명시적으로 선택하도록 바꾸었다.
// Next.js 15 – 'use cache' 지시어를 통한 명시적 캐싱
'use cache'

export async function getData() {
  const data = await fetch('/api/data')
  return data
}

Next.js 15는 Turbopack을 기본(또는 최소한 강력히 권장) 빌드 도구로 삼아 Webpack에서 벗어나게 했다. Rust 기반 번들러는 10배 성능 향상을 약속했지만, 실제 데이터는 혼재된 결과를 보여준다—핫 리프레시는 뛰어나지만 가끔 깨진 import, 높은 리소스 사용량, 콜드 스타트 문제가 발생한다.

Vercel이 “Next.js App Router에서 흔히 저지르는 10가지 실수”라는 공식 가이드를 발표했다는 사실 자체가 상황을 말해준다.

Next.js를 언제 사용해야 할까

  • 콘텐츠가 많은 사이트 – 블로그, 문서, 전자상거래 제품 카탈로그 등.
  • SEO가 중요한 페이지 – 서버 렌더링이 필요한 마케팅 홈페이지 등.

대부분(≈70 %)의 애플리케이션은 어느 정도 서버‑사이드가 필요하면서도 인터랙티브한데, “use client” 경계를 계속 추가하고 서버/클라이언트 복잡성을 관리해야 하는 마찰이 점점 무시하기 어려워진다.

TanStack Start 소개

TanStack Start는 안정적이고 검증된 도구들을 기반으로 한 풀‑스택 프레임워크다:

  • TanStack Router – 타입‑안전 라우팅.
  • Vite – 업계 표준 빌드 도구.

2025년 11월 현재, 베타(v1)를 벗어나 활발히 개발 중이며 커뮤니티 채택이 늘고 있다. Next.js와 달리, 이 프레임워크는 기본 원칙에서 일관성을 유지한다.

주요 차이점

측면Next.jsTanStack Start
기본 렌더링서버‑우선(React Server Components)클라이언트‑우선; 라우트별 SSR 선택 가능
라우팅파일 기반, 제한된 타입 안전성TanStack Router와 완전한 TypeScript 추론 제공
빌드 도구Turbopack(기본) 또는 WebpackVite
캐싱버전마다 변하는 기본값ssr 속성을 통한 라우트별 명시적 설정
정신 모델서버‑중심, “use client” 마커 다수클라이언트‑중심, SSR은 선택적 기능

라우트별 SSR 설정

// TanStack Start – 라우트별 SSR 설정

// 전통적인 SPA처럼 순수 클라이언트‑사이드 렌더링
export const Route = createFileRoute('/dashboard')({
  ssr: false,
  component: DashboardComponent,
})

// SEO가 중요한 페이지를 위한 전체 SSR
export const Route = createFileRoute('/products')({
  ssr: true,
  loader: async () => fetchProducts(),
  component: ProductsComponent,
})

// 데이터‑전용 SSR: 서버에서 데이터만 가져오고 클라이언트에서 렌더링
export const Route = createFileRoute('/admin')({
  ssr: 'data-only',
  loader: async () => fetchAdminData(),
  component: AdminComponent,
})

철학

  • 클라이언트‑우선 정신 모델 – 먼저 클라이언트 경험을 생각하며 코드를 작성한다.
  • SSR은 라우트별 선택 사항 – Next.js가 “옵트아웃”하는 반면, TanStack Start는 필요한 곳에만 “옵트인”한다.
  • 기본적으로 이소모픽 코드 – 라우트 로더는 서버(초기 로드)와 클라이언트(내비게이션) 모두에서 실행된다.

타입 안전성과 라우팅

TanStack Start는 routeTree.gen.ts 파일을 자동 생성해 모든 라우트에 대한 완전한 타입 정보를 제공한다. 이는 Next.js에서는 찾아볼 수 없는 기능이다.

// routes/products.$id.tsx
export const Route = createFileRoute('/products/$id')({
  loader: async ({ params }) => {
    // params.id는 자동으로 완전한 타입을 가짐
    return getProduct(params.id)
  },
  component: ProductComponent,
})

function ProductComponent() {
  const product = Route.useLoaderData() // 완전한 타입!
  return {product.name}
}

네비게이션은 컴파일 타임에 안전하다:

navigate({
  to: '/products/$id',
  params: { id: productId }, // TypeScript가 검증함
})

결론

Next.js는 콘텐츠가 많고 SEO가 중요한 사이트에 여전히 훌륭한 선택이지만, 서버‑우선 기본값과 변하는 정신 모델은 고도로 인터랙티브한 애플리케이션에 마찰을 일으킬 수 있다. TanStack Start는 클라이언트‑우선 접근 방식에 라우트별 명시적 SSR, 강력한 타입‑안전 라우팅, 그리고 TanStack Router와 Vite 같은 검증된 도구들을 기반으로 한 안정적인 생태계를 제공한다. 클라이언트 인터랙티브와 선택적 서버 렌더링을 균형 있게 필요로 하는 프로젝트라면, TanStack Start가 매력적인 대안이 될 수 있다.

Back to Blog

관련 글

더 보기 »