You have a Server Component that imports next/router.

 

Next JS 학습 중 위 에러가 발생했다.

id라는 이름의 path parameter를 사용하려던 중 발생했는데, 그 해결과정을 간략히 정리해보고자 한다.

 



1. 에러 발생 및 설명

먼저, 문제가 된 코드는 아래와 같다.

import { useRouter } from 'next/router';

export default function Id() {
  const router = useRouter();
  const id = Number(router.query.id);

  return (
    <>
      <h1>/pages/sub/[id]/page.js</h1>
      <p>Parameter id: {id}</p>
      <a href="/">/pages/page.js</a>
    </>
  );
}

/sub/[id] 라는 경로로 접근했을 때, next/router의 useRouter를 활용하여 query 값에서 id를 찾아내는 구조이다.

하지만 위 코드를 컴파일하던 중 You have a Server Component that imports next/router, 즉  서버 컴포넌트에서 next/router를 사용했다는 에러가 발생했다.

 

알아보니 next.js 13 버전부터 기존 pages 폴더에서 app 폴더 기반 라우팅 시스템으로 바뀌었는데, 이와 함께 서버 컴포넌트와 클라이언트 컴포넌트를 구분하기 시작했다. next/router의 useRouter는 클라이언트 전용 훅으로서, 클라이언트 컴포넌트에서만 사용이 가능하기 때문에 서버 컴포넌트에서 호출 시 위 에러가 발생한다.


2. 해결

다른 블로그를 참고했을 때 서버 컴포넌트에서는 next/router가 대신 next/navigation을 사용해야 한다고 하여 적용해보았다. 하지만 next/navigation의 useRouter는 query를 포함하고 있지 않아 고민하던 중, 아래와 같이 pathname을 활용하는 방식으로 먼저 접근해보았다.

'use client';

import { usePathname } from 'next/navigation';

export default function IdPage() {
  const pathname = usePathname();
  const id = pathname.split("/")[2];

  return (
    <div>
      <h1>/pages/sub/[id]/page.js</h1>
       <p>Parameter id: {id}</p>
       <a href="/">/pages/page.js</a>
    </div>
  );
}

접근경로인 /sub/[id] 을 pathname으로 받은 후 split()하여 id를 추출하는 방식이다.

 

하지만 위와 같은 방식은 url이 변경될 때마다 코드의 수정이 필요하다.

그래서 좀 더 알아보니, 간단한 해결책이 나왔다. 알고보니 app 폴더 기반 라우팅 시스템에서는 params 객체를 통해 path parameter 값을 받아올 수 있었다.

따라 아래와 같이 params 객체에서 id를 추출하는 방식을 채택했다.

export default function Id({ params }) {
  const { id } = params;

  return (
    <>
      <h1>/pages/sub/[id]/page.js</h1>
      <p>Parameter id: {id}</p>
      <a href="/">/pages/page.js</a>
    </>
  );
}

3. 서버 컴포넌트 & 클라이언트 컴포넌트

서버 컴포넌트

서버 컴포넌트는 서버에서만 실행되는 컴포넌트로 클라이언트 측에서 렌더링되는 JavaScript 코드를 보내지 않고, 서버에서 데이터를 처리하거나 렌더링을 한 뒤 HTML을 클라이언트로 전송한다. Next JS에서는 별다른 선언을 하지 않으면 서버 컴포넌트로 간주한다.

  • 서버에서 동적으로 데이터를 처리하고 렌더링
  • 클라이언트에서 JavaScript를 실행하지 않으며 필요한 경우 React의 상태 업데이트나 이벤트 핸들러 없이 서버에서 완료된 HTML을 클라이언트로 전송
  • 서버 컴포넌트는 클라이언트 사이드 라이브러리나 API 호출과 같은 동적 JavaScript 동작을 할 수 없으며, 대신 서버에서 데이터를 가져와서 HTML을 렌더링

 

클라이언트 컴포넌트

클라이언트 컴포넌트는 클라이언트 브라우저에서 실행되는 컴포넌트이며, 상태 관리, 이벤트 핸들링, 클라이언트 측 API 요청, 동적 렌더링 등을 클라이언트에서 처리할 수 있다. 최상단에 'use client'를 적음으로써 클라이언트 컴포넌트를 선언할 수 있다.

  • 클라이언트에서 JavaScript를 실행하여 동적인 콘텐츠를 표시
  • 상태(state)를 관리하거나 이벤트 핸들러를 통해 동작을 처리
  • 클라이언트에서 useState, useEffect, useRouter와 같은 React 훅을 사용하여 UI를 동적으로 업데이트

 

서버 컴포넌트와 클라이언트 컴포넌트의 구분 이유

  • 서버 컴포넌트는 최적화된 서버 사이드 렌더링(SSR)을 통해 페이지를 클라이언트에게 전달하고, 불필요한 JavaScript 번들을 줄여 페이지 로딩 속도를 개선
  • 클라이언트 컴포넌트는 상태 관리, 이벤트 처리, 동적 UI 업데이트를 클라이언트에서 처리하게 함으로써 사용자 경험 향상

끝!

'Languages > Next.js' 카테고리의 다른 글

[NextJS] Fast Refresh 무한루프 해결  (0) 2025.02.18

+ Recent posts