본문 바로가기
Web/Next.js

Next.js 13 pages 라우터에서 app router로 마이그레이션하기 - next/head

by 김첨지 2023. 2. 1.

 

next/head migration

pages 라우터에서는 next/head를 이용하여 meta, title와 같은 html 요소를 관리하였다.

// pages/index.tsx

import Head from 'next/head'

export default function Page() {
  return (
    <>
      <Head>
        <title>My page title</title>
      </Head>
    </>
  )
}

 

 

app 라우터에서는 이것이 head.js라는 special 파일로 대체되었다.

// app/head.tsx

export default function Head() {
  return (
    <>
      <title>My Page Title</title>
      <meta name="viewport" content="width=device-width, initial-scale=1"  />
    </>
  )
}

 

 

이에 따라 기존에 웹폰트 방식으로 사용하던 폰트 또한 마이그레이션 해야 했다.

// pages/_document/tsx

  render() {
    return (
      <Html lang="kr">
        <Head>
          <link
            as="style"
            href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/variable/pretendardvariable.css"
            rel="stylesheet"
          />
          <link
            as="style"
            href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendardstatic.css"
            rel="stylesheet"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

 

 

next/font를 이용하여 최적화하고자 하였지만, (https://beta.nextjs.org/docs/api-reference/components/font#font-function-arguments)

다음과 같은 에러가 뜨며 동작하지 않았다.

Error : @next/font/google failed to run or is incorrectly configured. If you just installed `@next/font`, please try restarting `next dev` and resaving your file. Read more: https://nextjs.org/docs/basic-features/font-optimization

 

 

해결 방법으로 라이브러리 삭제후 재설치, next.js 최신 버전으로 업데이트, 구글링, next.js 깃허브 이슈 확인 등 할 수 있는 건 다 해봤지만 자료도 부족하고 도저히 해결할 수가 없었다. 

조만간 next.js 깃허브에 이슈를 올려볼 계획인데, 해결된다면 여기 바로 아래에 추가 내용을 작성해 보겠다.

 

일단 웹 폰트방식이라도 사용하고자 하였지만 이것도 순탄치 않았다.

Warning: Cannot render a <link rel="stylesheet" /> outside the main document without knowing its precedence. Consider adding precedence="default" or moving it into the root <head> tag.

 

 

app/head.tsx에 해당 폰트의 <link> 코드를 넣었지만 위와 같은 에러가 발생했다.

에러 문구를 읽어보니 precedence 속성을 넣어주면 된다는데, 

<link>에서는 해당 속성은 존재하지 않는다고 에러를 발생시켰다.

'{ as: string; href: string; rel: string; precedence: string; }' 형식은 'DetailedHTMLProps<LinkHTMLAttributes<HTMLLinkElement>, HTMLLinkElement>' 형식에 할당할 수 없습니다.

 

 

이에 head.js에 대한 공식문서를 읽어보았고, head.js에 <link rel="stylesheet" />을 사용할 경우 precedence 속성이 필수적이라는 것을 알았다. (https://beta.nextjs.org/docs/api-reference/file-conventions/head#supported-head-tags)

실제로 위 에러를 무시하고 해당 속성을 넣은 채로 실행시켜 보니 문제없이 잘 작동하였다. 

에러가 타입스크립트 에러라는 것을 깨닫고 @ts--ignore 코드를 넣어주었다.

// app/head.tsx

export default function Head() {
  return (
    <>
      <title>My Page Title</title>
      <link
        as="style"
        href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/variable/pretendardvariable.css"
        rel="stylesheet"
        // @ts-ignore
        precedence="default"
      />
      <link
        as="style"
        href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendardstatic.css"
        rel="stylesheet"
        // @ts-ignore
        precedence="default"
      />
    </>
  );
}