본문 바로가기

next.js

next.js parallel routes

회사에서 메인프로젝트를 page router -> app router로 마이그레이션하면서 next의 여러가지 기능을 쓸 수 있게 되었다. parallel routes는 처음 접해보는 기능이었기에 글을 쓰게 되었다.


Next.js 패러럴 라우팅으로 헤더와 푸터를 관리한 경험

회사에서 PC 웹용 헤더와 푸터를 공통 컴포넌트로 만들고 있었다. 문제는 “공통”이라는 말과 다르게, 실제 요구사항은 전혀 공통적이지 않았다는 점이다. 페이지마다 헤더와 푸터가 조금씩 달랐다.

어떤 페이지는 검색창이 있는 헤더가 필요했고,
어떤 페이지는 로고만 있는 단순한 헤더가 필요했다.

처음에는 조건 분기로 해결하려 했지만, 곧 한계를 느꼈다. 이때 동료가 추천해준 방법이 Next.js의 패러럴 라우트이다.


기존 방식의 문제점

처음 접근은 전형적이었다.

  • 하나의 Header 컴포넌트
  • props 또는 pathname 기반 분기
  • 조건이 늘어날수록 코드 복잡도 증가

예를 들어 이런 코드가 계속 늘어났다.

  • 특정 페이지면 메뉴 A 표시
  • 다른 페이지면 메뉴 B 표시
  • 또 다른 페이지면 아예 숨김

이 방식은 몇 가지 문제가 있었다.

  • 헤더 로직이 페이지 요구사항을 모두 알고 있어야 했다
  • 페이지 하나 추가할 때마다 공통 컴포넌트를 수정해야 했다
  • “공통 컴포넌트”가 더 이상 공통이 아니게 됐다

헤더와 푸터는 페이지에 종속적인데, 이를 하나의 컴포넌트로 묶으려다 보니 구조가 계속 깨졌다.


패러럴 라우팅이 해결책이 된 이유

핵심은 하나의 URL에서 여러 라우트 트리를 동시에 렌더링할 수 있다는 점이다.

이때 사용하는 문법이 @ slots 이다.

 
app/ layout.tsx @header/ @footer/ page.tsx

이 구조를 보고 처음 든 생각은

“이거 헤더랑 푸터 만들라고 있는 기능 아닌가?”

실제로 PC 웹 헤더·푸터 구조에 굉장히 잘 맞았다.


기본 구조 설계

최상위 layout.tsx를 이렇게 두었다.

export default function Layout({
  header,
  footer,
  children,
}: {
  header: React.ReactNode;
  footer: React.ReactNode;
  children: React.ReactNode;
}) {
  return (
    <>
      {header}
      <main>{children}</main>
      {footer}
    </>
  );
}

그리고 폴더 구조를 다음처럼 구성했다.

app/
  layout.tsx
  @header/
    default.tsx
  @footer/
    default.tsx
  page.tsx
 
 

이 상태에서는 모든 페이지가 동일한 헤더와 푸터를 사용한다.


페이지별로 다른 헤더·푸터 적용하기

페이지마다 헤더와 푸터가 다르다는 요구사항은 해당 페이지 경로에만 @header와 @footer를 오버라이드하면 된다.

예를 들어 /review 내부의 페이지는 다른 헤더가 필요했다.

 
app/
  review /
    page.tsx //혹은 slug를 사용하여 review 내부의 모든 페이지에 적용 가능하다.
    @header/
      page.tsx
    @footer/
      page.tsx
 

이렇게 하면 /review 경로에서는

  • 기본 헤더가 아니라 /review/@header/page.tsx
  • 기본 푸터가 아니라 /reviewe/@footer/page.tsx
    가 렌더링된다.

URL은 그대로인데, 레이아웃 구성만 바뀐다.


이 방식의 가장 큰 장점

이 구조를 도입하고 나서 가장 크게 느낀 장점은 다음과 같다.

헤더와 푸터가 페이지를 모르게 된다

기존에는 헤더 컴포넌트가 현재 페이지가 무엇인지 알고 있어야 했다.
패러럴 라우팅을 사용하면 그 반대다.

  • 페이지가 어떤 헤더를 쓸지 결정한다
  • 헤더는 자신의 역할만 수행한다

의존성이 완전히 뒤집힌다.


조건 분기가 사라진다

if (pathname === ...) 같은 코드가 사라졌다.
헤더 내부에는 조건이 없다.
필요한 헤더는 “그냥 다른 파일”로 존재할 뿐이다.

이건 유지보수에서 체감이 크다.


디자이너·기획 변경에 강하다

“이 페이지 헤더를 살짝 바꿔주세요”라는 요구가 왔을 때,
공통 컴포넌트를 건드릴 필요가 없다.

  • 해당 페이지 폴더에 @header/page.tsx 추가
  • 기존 페이지에는 영향 없음

변경이 찾은 우리 서비스 특성상 이게 굉장히 중요했다.


@header, @footer 슬롯만으로 구조가 훨씬 명확해진다.

공통 컴포넌트를 억지로 공통으로 만들기보다,
레이아웃을 조합하는 쪽으로 사고를 전환하는 계기가 됐다.

이 기능은 복잡한 서비스일수록 가치가 커진다.

'next.js' 카테고리의 다른 글

병원 페이지 seo 자산화  (0) 2026.01.06