Next.js App Router를 실무에서 언제 선택하고 언제 조심해야 하는가

Frontend

Next.js App Router는 이제 단순한 새 라우터가 아니라, Next.js의 기본 문법에 가깝게 자리잡았습니다.

하지만 실무에서 App Router를 선택할 때는 "최신 방식이니까" 정도로 접근하면 금방 어려워집니다.

왜냐하면 App Router는 단순히 파일 구조가 바뀐 것이 아니라:

  • 서버 컴포넌트
  • 클라이언트 컴포넌트
  • 레이아웃 계층
  • 데이터 캐시
  • 스트리밍

같은 개념이 한꺼번에 들어오기 때문입니다.

즉, App Router를 선택한다는 것은 새 폴더 구조를 고르는 것이 아니라, 렌더링 방식과 데이터 흐름의 기본 모델을 같이 선택하는 것에 가깝습니다.

이 글에서는 App Router가 실무에서 언제 잘 맞는지, 반대로 언제 조심해야 하는지를 담백하게 정리해보겠습니다.

한눈에 보면

먼저 짧게 정리하면 이렇습니다.

  • App Router는 서버 중심 렌더링과 하이브리드 페이지 운영이 필요한 서비스에서 강합니다
  • 공개 웹, 블로그, 커머스, SaaS처럼 서로 다른 렌더링 요구사항이 섞인 제품에 잘 맞습니다
  • 반면 전부 클라이언트 상호작용 중심인 앱에서는 체감 이점보다 복잡도가 더 크게 느껴질 수 있습니다
  • 특히 서버/클라이언트 경계, 캐시, 재검증 개념을 팀이 이해하지 못한 상태에서 도입하면 혼란이 커집니다

표로 보면 더 빠릅니다.

질문 App Router가 잘 맞는 경우 조심해야 하는 경우
공개 페이지와 앱이 같이 있는가 잘 맞음 해당 없음
SEO와 서버 렌더링이 중요한가 잘 맞음 필요가 약하면 이점이 줄어듦
서버 데이터와 캐시 전략을 함께 다뤄야 하는가 잘 맞음 전부 클라이언트 패칭이면 과할 수 있음
팀이 서버/클라이언트 경계를 이해하는가 도입 효과 큼 이해가 낮으면 혼란 가능
클라이언트 전용 라이브러리 의존이 큰가 일부 조심 필요 과도하면 마찰 큼
빠른 CRUD 위주의 내부 앱인가 경우에 따라 다름 단순 SPA가 더 효율적일 수 있음

App Router를 선택하면 무엇이 달라지나?

Pages Router와 비교했을 때 핵심 차이는 단순 라우팅이 아닙니다.

App Router는 기본적으로 다음 사고방식을 가져옵니다.

  • 페이지는 서버에서 먼저 그릴 수 있다
  • 꼭 필요한 부분만 클라이언트 컴포넌트로 내린다
  • 데이터 패칭과 캐시 정책을 컴포넌트 가까이 둔다
  • 중첩 레이아웃과 로딩 상태를 라우트 구조로 표현한다

예를 들어:

// app/dashboard/page.tsx
import { DashboardFilters } from './dashboard-filters';
 
export default async function DashboardPage() {
  const summary = await getDashboardSummary();
 
  return (
    <>
      <h1>{summary.title}</h1>
      <DashboardFilters />
    </>
  );
}
'use client';
 
type DashboardFiltersProps = {
  // ...
};
 
export function DashboardFilters(_: DashboardFiltersProps) {
  return <div>interactive filters</div>;
}

이 구조는 "기본은 서버, 상호작용은 클라이언트"라는 분리를 더 자연스럽게 만듭니다.

언제 App Router가 잘 맞을까?

1. 공개 웹과 앱이 같이 있는 서비스

이 경우가 가장 대표적입니다.

예를 들어:

  • 랜딩 페이지
  • 가격 소개
  • 블로그
  • 로그인 후 대시보드
  • 관리자 페이지

이런 제품은 한 가지 렌더링 방식으로 설명되지 않습니다.

  • 공개 페이지는 SEO가 중요하고
  • 블로그는 정적 생성이나 재검증이 효율적이고
  • 대시보드는 상호작용이 중요하고
  • 일부 관리 화면은 최신 데이터가 더 중요할 수 있습니다

App Router는 이 섞인 구조를 한 프로젝트 안에서 관리하기 좋습니다.

2. 서버에서 먼저 그려주는 것이 명확한 이점이 있을 때

검색 유입이 중요한 서비스나 초기 응답이 중요한 화면에서는 서버 렌더링이 실질적인 이점이 됩니다.

예를 들어 상품 상세나 아티클 페이지는 아래처럼 구성하기 좋습니다.

// app/products/[slug]/page.tsx
export default async function ProductPage({ params }: { params: { slug: string } }) {
  const product = await getProduct(params.slug);
 
  return (
    <article>
      <h1>{product.name}</h1>
      <p>{product.summary}</p>
    </article>
  );
}

이 구조는:

  • 초기 HTML을 서버에서 만들고
  • SEO를 확보하고
  • 필요한 상호작용만 클라이언트로 남기는

식의 구성이 자연스럽습니다.

3. 레이아웃과 로딩 상태를 계층적으로 관리하고 싶을 때

App Router의 장점 중 하나는 레이아웃 구조입니다.

app/
  layout.tsx
  (marketing)/
    layout.tsx
    pricing/page.tsx
  dashboard/
    layout.tsx
    page.tsx
    loading.tsx

이 구조가 좋은 이유는 단순히 파일이 예쁘기 때문이 아닙니다.

  • 공통 레이아웃 책임이 분리되고
  • 로딩 상태와 에러 처리 위치가 명확해지고
  • 서비스 영역별 UI 골격을 나누기 쉬워집니다

즉, 화면 수가 많아질수록 체감이 커집니다.

4. 데이터 캐시와 재검증을 운영 정책으로 다뤄야 할 때

App Router에서는 데이터 패칭이 단순 구현이 아니라 운영 정책과 가깝습니다.

await fetch('https://api.example.com/posts', {
  next: { revalidate: 300 },
});

이 코드는 곧 아래 질문과 연결됩니다.

  • 이 데이터는 5분까지 stale해도 되는가
  • 응답 속도와 최신성 중 무엇을 우선할 것인가
  • 어떤 페이지는 정적에 가깝게 둘 것인가

실무에서는 이 운영 판단을 코드 가까이에서 표현할 수 있다는 점이 꽤 큰 장점입니다.

5. 팀이 서버와 클라이언트 책임 분리에 익숙할 때

App Router는 팀이 아래 질문에 답할 수 있을수록 더 잘 맞습니다.

  • 이 로직은 서버에 있어야 하는가
  • 이 컴포넌트는 브라우저 API를 쓰는가
  • 이 데이터는 요청마다 새로 받아야 하는가
  • 이 화면은 어디까지 서버에서 만들고 어디부터 클라이언트에 맡길 것인가

팀이 이 경계를 이해하고 있으면 App Router는 구조를 더 분명하게 만들어줍니다.

언제 조심해야 할까?

1. 전부 클라이언트 상호작용 중심인 앱

예를 들어:

  • 로그인 이후에만 쓰는 내부 툴
  • 대시보드 중심의 SPA
  • SEO가 거의 필요 없는 제품

이런 경우에는 App Router의 장점이 생각보다 크지 않을 수 있습니다.

물론 사용 못 하는 것은 아닙니다. 다만 아래 같은 상황이 생깁니다.

  • 거의 모든 파일에 'use client'가 붙고
  • 서버 컴포넌트 이점은 작고
  • 오히려 경계만 복잡하게 느껴질 수 있습니다

이럴 때는 단순한 React SPA가 더 효율적일 수 있습니다.

2. 팀이 서버/클라이언트 경계에 익숙하지 않을 때

App Router에서 자주 생기는 혼란은 기능 부족이 아니라 사고방식 충돌입니다.

예를 들어 아래 코드는 서버 컴포넌트에서 바로 쓸 수 없습니다.

import { useEffect, useState } from 'react';
 
export default function Page() {
  const [open, setOpen] = useState(false);
 
  useEffect(() => {
    console.log(window.location.href);
  }, []);
 
  return <button onClick={() => setOpen(true)}>open</button>;
}

왜냐하면 브라우저 전용 로직이기 때문입니다. 그래서 'use client'를 붙여야 합니다.

문제는 팀이 이 기준을 이해하지 못하면:

  • 왜 어떤 파일은 동작하고 어떤 파일은 안 되는지
  • 왜 props 직렬화 제약이 생기는지
  • 왜 서버에서 읽은 값을 클라이언트로 바로 넘기는 데 제한이 있는지

를 계속 헷갈리게 됩니다.

즉, App Router는 문법보다 개념 학습 비용이 더 큰 편입니다.

3. 클라이언트 전용 라이브러리 의존이 강할 때

차트, 에디터, 드래그 앤 드롭, 브라우저 API 의존 라이브러리가 많으면 조심해야 합니다.

이런 라이브러리는 종종:

  • window
  • document
  • 레이아웃 측정
  • 브라우저 이벤트

에 의존합니다.

그러면 결국 해당 영역은 클라이언트 컴포넌트로 내려야 하고, 서버 컴포넌트 구조의 장점이 줄어듭니다.

즉, 제품의 핵심 UI가 대부분 브라우저 상호작용 위에 서 있다면 App Router의 이점을 냉정하게 다시 봐야 합니다.

4. 캐시와 재검증을 명확히 이해하지 못한 채 도입할 때

App Router는 편한 동시에 오해하기 쉬운 지점이 있습니다.

  • 왜 데이터가 바로 안 바뀌지?
  • 왜 어떤 요청은 캐시되고 어떤 요청은 아닌가?
  • 왜 배포 후에도 이전 데이터가 보이지?

이런 질문은 대부분 캐시와 재검증 정책을 팀이 명확히 잡지 않았을 때 나옵니다.

예를 들어 실무에서는 아래를 반드시 구분해야 합니다.

  • 요청마다 최신 데이터가 필요한가
  • 일정 주기 캐시가 가능한가
  • 수동 재검증이 필요한가

이 기준 없이 App Router를 도입하면 "프레임워크가 이상하다"는 오해가 쉽게 생깁니다.

5. 기존 Pages Router 프로젝트를 무리하게 한 번에 옮길 때

마이그레이션도 조심해야 합니다.

기존 프로젝트가 아래에 많이 기대고 있다면:

  • getServerSideProps
  • getStaticProps
  • pages/api
  • 오래된 클라이언트 중심 패턴

App Router로 한 번에 전환하는 것은 생각보다 비용이 큽니다.

특히 화면 수가 많고 팀이 바쁜 상태라면, 전면 전환보다 신규 영역부터 App Router를 도입하는 방식이 현실적일 수 있습니다.

실무 판단 기준으로 다시 정리하면

아래 질문에 가 많을수록 App Router가 잘 맞을 가능성이 큽니다.

  1. 공개 페이지와 로그인 후 앱을 한 제품 안에서 같이 운영하는가
  2. SEO가 중요한 페이지가 존재하는가
  3. 서버에서 먼저 렌더링하는 이점이 분명한가
  4. 캐시와 재검증을 운영 정책으로 다뤄야 하는가
  5. 팀이 서버/클라이언트 경계에 대한 학습을 감당할 수 있는가

반대로 아래 질문에 가 많다면 더 조심해서 봐야 합니다.

  1. 거의 모든 화면이 브라우저 상호작용 중심인가
  2. 핵심 라이브러리 대부분이 클라이언트 전용인가
  3. SEO 필요가 약한가
  4. 팀이 서버 컴포넌트와 캐시 개념에 익숙하지 않은가
  5. 지금 필요한 것은 구조 고도화보다 빠른 화면 구현인가

개인적으로 추천하는 도입 방식

실무에서는 App Router를 "무조건 전면 도입"보다 아래처럼 보는 편이 더 안전합니다.

잘 맞는 방식

  • 신규 프로젝트에서 시작부터 도입
  • 공개 웹, 블로그, 문서, 커머스 상세 같은 영역부터 도입
  • 팀이 서버/클라이언트 경계를 같이 학습하면서 규칙을 정리

조심할 방식

  • 기존 프로젝트 전체를 단기간에 전면 전환
  • 개념 정리 없이 'use client'만 남발하는 방식
  • 캐시 정책 기준 없이 일단 fetch부터 바꾸는 방식

즉, App Router는 도입 자체보다 어떤 영역부터, 어떤 기준으로, 팀이 얼마나 이해한 상태에서 가져가는가가 더 중요합니다.

정리하면

Next.js App Router를 실무에서 언제 선택해야 하는가를 한 줄로 줄이면 이렇습니다.

서버 중심 렌더링, 하이브리드 페이지 운영, 계층형 레이아웃, 캐시 정책 관리가 중요한 서비스라면 App Router는 꽤 좋은 선택지입니다.

반대로 언제 조심해야 하는가를 한 줄로 줄이면 이렇습니다.

전부 클라이언트 상호작용 중심이거나, 팀이 서버/클라이언트 경계와 캐시 개념을 아직 소화하지 못한 상태라면 App Router는 복잡도부터 체감될 수 있습니다.

결국 중요한 것은 "App Router가 최신인가"가 아니라, 우리 서비스와 팀이 이 모델을 소화했을 때 실제 이점이 생기는가입니다.

같이 보면 좋은 글