Published on

Next.js에서 "invariant expected app router to be mounted" 오류 해결하기

Authors
  • avatar
    Name
    Hyo814
    Twitter

Next.js에서 "invariant expected app router to be mounted" 오류 해결하기

Next.js 에서 "invariant expected app router to be mounted" 오류 해결하기

Next.js 으로 업그레이드한 후, useRouter 훅을 사용하면서 "invariant expected app router to be mounted"라는 오류가 발생할 수 있습니다. 이 오류는 주로 라우터가 제대로 마운트되지 않았을 때 나타나며, 특히 새로운 라우팅 시스템과 컴포넌트 구조에서 발생할 수 있습니다.

문제 상황

  • 라우터가 올바르게 마운트되지 않음
  • Link 컴포넌트와 관련된 네비게이션 문제
  • 클라이언트 컴포넌트와 서버 컴포넌트의 혼용 문제

원인 분석

  1. Link 컴포넌트의 속성 변경: Next.js 에서는 Link 컴포넌트의 사용 방식이 업데이트되었습니다. 특히 legacyBehavior 속성을 지원하여, 이전 버전과의 호환성을 유지할 수 있지만 이를 사용하지 않을 경우 예상치 못한 동작이 발생할 수 있습니다.
  2. 라우팅 시스템 개선: Next.js 은 라우팅 시스템을 개선하면서 서버 컴포넌트와 클라이언트 컴포넌트를 구분하는 방식을 도입했습니다. 클라이언트 컴포넌트에서만 사용할 수 있는 useRouter 훅을 서버 컴포넌트에서 사용하려 할 때 문제가 발생합니다.
  3. 폴더 구조 문제: Next.js 의 app 디렉토리와 기존 pages 디렉토리의 구조와 동작이 다르기 때문에, 잘못된 폴더 구조가 문제가 될 수 있습니다.

해결 방법

  1. Next.js 버전 확인: Next.js가 최신 버전인지 확인하세요. 업데이트를 통해 기존의 버그가 해결될 수 있습니다.
  2. App Router 설정 확인: Next.js 에서 app 디렉토리를 사용하려면 next.config.js 파일에 appDir 옵션이 활성화되어 있는지 확인합니다.
// next.config.js
module.exports = {
  experimental: {
    appDir: true,
  },
};

   ```

3. **useRouter 사용 확인**: `useRouter` 훅은 클라이언트 컴포넌트에서만 사용할 수 있습니다. 따라서 `use client` 지시어를 사용하여 해당 컴포넌트를 클라이언트 컴포넌트로 변환해야 합니다.

```jsx
// app/myComponent/page.tsx
'use client';

import { useRouter } from 'next/navigation';
import { useEffect } from 'react';

const MyComponent: React.FC = () => {
  const router = useRouter();

  useEffect(() => {
    // 클라이언트에서만 실행
    if (typeof window !== 'undefined') {
      // 라우터 관련 코드
    }
  }, []);

  return <div>My Component</div>;
};

export default MyComponent;

   ```

4. **App 컴포넌트 확인**: `pages/_app.js` 파일에서 Next.js 라우터가 제대로 설정되었는지 확인합니다. 기본적으로 Next.js는 `pages/_app.js` 파일을 사용하여 페이지 전환을 처리합니다.

```jsx
// pages/_app.js
import { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;

   ```

5. **Next.js 에서 클라이언트 컴포넌트로 변환**: Next.js 의 `app` 디렉토리에서 `useRouter` 훅을 사용하는 컴포넌트는 클라이언트 컴포넌트로 변환되어야 합니다. 이를 위해 파일 상단에 `'use client';`를 추가합니다.

### 추가적인 사항

### 1. **`use client` 지시어의 역할**

Next.js 의 `app` 폴더에서는 기본적으로 서버 컴포넌트(Server Components)가 사용됩니다. 하지만 클라이언트 측에서 실행되어야 하는 코드(예: `useRouter`, `useState`, `useEffect` 등)가 있을 경우, 해당 컴포넌트를 클라이언트 컴포넌트로 지정하기 위해 `'use client';` 지시어를 사용합니다.

### 2. **Next.js 에서 라우터가 올바르게 마운트되지 않을 때 발생하는 일반적인 원인**

- **클라이언트 컴포넌트 설정 누락**: 클라이언트에서 실행되어야 할 컴포넌트가 `use client` 지시어로 지정되지 않은 경우.
- **라우팅 설정 문제**: Next.js의 라우팅 설정이 제대로 구성되지 않았거나 `next.config.js` 파일에서 `experimental.appDir` 설정이 활성화되지 않은 경우.
- **폴더 구조 문제**: `app` 폴더 내의 파일 및 디렉토리 구조가 Next.js의 요구사항에 맞지 않는 경우.
- **잘못된 훅 사용**: 서버 컴포넌트에서 클라이언트 훅(예: `useRouter`, `useState`, `useEffect`)을 사용한 경우.

### 3. **Next.js 의 `app` 디렉토리와 `pages` 디렉토리의 차이점**

- **렌더링 방식**:
 - `pages` 디렉토리: 클라이언트 측 렌더링(CSR) 또는 서버 측 렌더링(SSR)을 선택적으로 사용할 수 있습니다.
 - `app` 디렉토리: 기본적으로 서버 컴포넌트를 사용하며, 필요한 경우 클라이언트 컴포넌트로 지정할 수 있습니다.
- **파일 기반 라우팅**:
 - `pages` 디렉토리: 파일 기반 라우팅이 기본으로 제공되며, 각 파일이 페이지로 매핑됩니다.
 - `app` 디렉토리: 더 유연한 라우팅 구조를 제공하며, 서버 컴포넌트와 클라이언트 컴포넌트를 혼합하여 사용할 수 있습니다.
- **데이터 페칭**:
 - `pages` 디렉토리: `getStaticProps`, `getServerSideProps` 등을 사용하여 데이터를 페칭합니다.
 - `app` 디렉토리: `fetch` API를 사용하여 서버 컴포넌트에서 직접 데이터를 페칭할 수 있습니다.

### Next.js 에서 `use client` 지시어를 사용하지 않으면 어떤 문제가 발생하나요?

Next.js 에서는 기본적으로 서버 컴포넌트(Server Components)를 사용하며, 클라이언트 컴포넌트(Client Components)는 명시적으로 지정해야 합니다. `use client` 지시어를 사용하지 않으면 다음과 같은 문제가 발생할 수 있습니다:

1. **클라이언트 전용 훅 사용 불가:** `useRouter`, `useState`, `useEffect`와 같은 클라이언트 전용 훅을 서버 컴포넌트에서 사용할 경우 오류가 발생합니다. 서버 컴포넌트는 서버 측에서만 실행되기 때문에 클라이언트 측 훅과 호환되지 않습니다.
2. **상호작용 불가:** 서버 컴포넌트는 상호작용(예: 버튼 클릭, 폼 제출 등)이 필요한 클라이언트 측 기능을 처리할 수 없습니다. `use client` 지시어를 사용하여 클라이언트 컴포넌트로 지정하지 않으면 이러한 상호작용이 동작하지 않습니다.
3. **렌더링 문제:** 클라이언트 컴포넌트로 동작해야 할 컴포넌트가 서버 컴포넌트로 렌더링될 경우, 예상치 못한 렌더링 문제나 UI 오류가 발생할 수 있습니다. 클라이언트 컴포넌트로 명시적으로 지정하지 않으면, 컴포넌트의 상태 관리 및 DOM 조작이 제대로 작동하지 않습니다.

### Next.js 에서 `app` 디렉토리를 사용할 때, 기존 `pages` 디렉토리와 혼용해도 되나요?

Next.js 에서는 `app` 디렉토리와 `pages` 디렉토리를 함께 사용하는 것이 가능합니다. 그러나 다음과 같은 사항을 고려해야 합니다:

1. **라우팅 우선순위:** `app` 디렉토리의 라우트가 `pages` 디렉토리의 라우트보다 우선합니다. 즉, 동일한 경로가 두 디렉토리 모두에 존재할 경우, `app` 디렉토리의 라우트가 먼저 적용됩니다.
2. **점진적 마이그레이션:** Next.js 은 점진적 업그레이드를 지원하므로, 기존의 `pages` 디렉토리를 유지하면서 `app` 디렉토리로 점진적으로 전환할 수 있습니다. 이 방법은 기존 프로젝트를 한 번에 모두 전환하는 데 따른 위험을 줄이는 데 유리합니다.
3. **서버 컴포넌트와 클라이언트 컴포넌트 혼용:** `app` 디렉토리는 기본적으로 서버 컴포넌트를 사용하는 반면, `pages` 디렉토리는 클라이언트 컴포넌트를 사용합니다. 두 디렉토리의 차이점을 이해하고 혼용할 경우 각 디렉토리에 맞는 컴포넌트 구조를 유지하는 것이 중요합니다.

### Next.js 에서 클라이언트 컴포넌트를 제대로 설정했는지 확인하는 방법은 무엇인가요?

Next.js 에서 클라이언트 컴포넌트를 제대로 설정했는지 확인하려면 다음 방법을 사용하세요:

1. **`use client` 지시어 확인:** 클라이언트 컴포넌트로 지정하려는 파일의 최상단에 `'use client';` 지시어가 있는지 확인합니다. 이 지시어가 없으면 컴포넌트는 기본적으로 서버 컴포넌트로 인식됩니다.

```jsx
// app/myComponent/page.tsx
'use client';

import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

const MyComponent = () => {
  const router = useRouter();
  const [count, setCount] = useState(0);

  useEffect(() => {
    // 클라이언트 전용 코드
  }, []);

  return <div>Count: {count}</div>;
};

export default MyComponent;

   ```

2. **클라이언트 전용 훅 사용 여부 확인:** `useRouter`, `useState`, `useEffect` 등 클라이언트 전용 훅이 사용된 경우, 해당 컴포넌트가 클라이언트 컴포넌트로 설정되었는지 확인합니다. 서버 컴포넌트에서 이러한 훅을 사용하면 오류가 발생합니다.
3. **개발자 도구 확인:** Next.js 개발자 도구 또는 브라우저의 개발자 도구를 사용하여 렌더링된 컴포넌트를 확인합니다. 클라이언트 컴포넌트로 설정된 경우, 클라이언트 측에서 상호작용이 제대로 동작하는지 확인합니다.
4. **콘솔 오류 및 경고 확인:** 브라우저 콘솔에서 오류나 경고 메시지를 확인합니다. 클라이언트 컴포넌트로 설정되지 않았을 때 발생하는 오류는 `use client` 지시어가 누락된 경우가 많습니다.