웹 개발

Next.js 프로젝트를 GitHub pages에 배포하기

깨비아빠0 2023. 12. 15. 14:01
728x90
반응형

Next.js 프로젝트를 GitHub pages에 배포하려면 다음 과정을 거치면 된다.

 

  1. static site 빌드
  2. GitHub에 올리기(push)
  3. GitHub pages 노출 설정

Next.js GitHub pages 배포 샘플 프로젝트를 참고하여 그 과정을 정리하면 다음과 같다.

 

 

프로젝트 GitHub 등록

우선 새 repository를 만들어서 Next.js 프로젝트를 올린다.

 

next.config.js 수정

next.config.js 파일을 다음과 같이 수정한다.

const nextConfig = {
    output: 'export',
    basePath: '/(repository 이름)',
}

 

static site 생성을 위해 output: 'export' 설정을 추가한다. 이렇게 지정하면 next build 실행 시 out 폴더에 static site 파일들이 생성된다.

이전 버전에서는 static site 생성을 위해 "next export" 명령을 사용한 듯하나, 이제 "output: 'export'" 설정을 통해 "next build" 명령으로 out 폴더에 출력물들이 생성된다.

 

그리고, basePath 속성에 repository 이름으로 경로를 지정한다. GitHub pages는 "xxx.github.io/(repository 이름)" URL을 사용하기 때문인데, basePath를 지정하면 사이트 생성 시 Link 컴포넌트의 href 경로 앞에 자동으로 basePath가 붙는다. 단, Image 컴포넌트의 src 경로는 자동으로 변경되지 않는다. (이 이슈는 뒤에 다시 다룰 예정)

 

package.json에 deploy 명령 추가

package.json 파일에 다음과 같이 deploy 명령을 추가한다.

  "scripts": {
    ...
    "deploy": "next build && touch out/.nojekyll && git add -f out/ && git commit -m \"Deploy\" && git subtree push --prefix out origin gh-pages"
  },

 

위 명령을 통해

 

  1. 사이트 빌드
  2. out 폴더를 git에 추가 및 커밋
  3. out 폴더를 gh-pages 브랜치에 서브트리로 추가

를 수행한다.

"touch out/.nojekyll"은 GitHub pages의 jekyll 처리과정을 생략하기 위해 ".nojekyll" 파일을 만드는 명령이다.
(https://github.blog/2009-12-29-bypassing-jekyll-on-github-pages/)
jekyll이 out/_next 폴더를 생략하는 것을 방지하기 위해 필요하다고 한다.

 

GitHub에 올리기(push)

터미널에서 npm run deploy를 실행하면 빌드한 사이트가 gh-pages 브랜치에 올라간다.

이후에 사이트를 수정할 때마다 이 명령만 실행하면 자동으로 사이트에 반영된다.

 

GitHub pages 설정

GitHub 저장소의 Settings > Pages > Branch 에서 gh-pages 브랜치와 / (root) 폴더를 선택하고 저장하면 된다.

(어쩐 일인지 자동으로 선택되어 있었다.)

 

이제 GitHub pages 사이트 주소(https://freeislet.github.io/home/)로 접속해보면 아래와 같이 사이트가 표시된다.

 

Image 경로가 깨지는 문제

위 스크린샷을 보면 이미지가 제대로 나오지 않고 있는데, basePath를 사용할 때 Link 경로는 자동으로 바뀌지만, 이미지 경로는 바뀌지 않기 때문이다. 공식 문서에 따르면 src에 basePath 경로를 직접 추가해줘야 한다. (next.config.js 설정에 assetPrefix가 있지만, 이 옵션은 CDN 사용을 위한 옵션이다. public 폴더의 파일들은 마찬가지로 경로에 basePath를 직접 포함해줘야 한다.)

 

다음과 같이 Image src 경로 앞에 "/(repository 이름)"을 붙여주고 다시 배포하면, 이미지가 정상적으로 표시되는 것을 볼 수 있다.

            <Image
              src="/(repository 이름)/vercel.svg"
              alt="Vercel Logo"
              className="dark:invert"
              width={100}
              height={24}
              priority
            />

 

경로 하드코딩 피하기

경로에 basePath 하드코딩을 피하고 싶다면 다음의 방법들이 있다.

 

참고: https://stackoverflow.com/questions/65930789/how-does-next-js-basepath-works-for-images/76197261#76197261

 

How does Next.js basePath works for images?

I'm trying to add a basePath to my next.config.js, it works well for the website content. But all the images are broken. // next.config.js module.exports = { basePath: '/my-sub-url', assetPrefi...

stackoverflow.com

 

이미지 import

import flower from '../public/images/flower.jpg'와 같이 이미지 import 후 src={flower}와 같이 사용

    import Head from 'next/head';
    import styles from '../styles/Home.module.css';
    import Link from 'next/link';
    import Image from 'next/image';
    import flower from '../public/images/flower.jpg'
    export default function Home() {
        return (
            <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <Image
                src={flower}// Route of the image file
                height={144} // Desired size with correct aspect ratio
                width={144} // Desired size with correct aspect ratio
                alt="Your Name"
                />
            </main>
            </div>
        )
    }

 

basePath import 후 src 경로에 사용

import { basePath } from '../next.config'로 basePath import 후 src={`${basePath}/images/flower.jpg`}와 같이 src 경로에 사용

    import Head from 'next/head';
    import styles from '../styles/Home.module.css';
    import Link from 'next/link';
    import Image from 'next/image';

    import { basePath } from '../next.config';

    export default function Home() {
        return (
            <div className={styles.container}>
            <Head>
                <title>Create Next App</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main>
                <Image
                src={`${basePath}/images/flower.jpg`}// Route of the image file
                height={144} // Desired size with correct aspect ratio
                width={144} // Desired size with correct aspect ratio
                alt="Your Name"
                />
            </main>
            </div>
        )
    }

 

컴포넌트에 prefix 전달 후 src 경로에 사용

검색하다 보니 prefix라는 이름의 props를 전달하여 src 경로에 포함시키는 방법도 있었다. (위의 basePath import와 유사)

https://boramyy.github.io/dev/front-end/nextjs/deploy-gh-pages/#prefix-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0

 

nextjs gh-pages로 배포하기

nextjs로 만든 모바일 웹을 gh-pages로 배포해보자

boramyy.github.io

 

Debug 설정 변경

basePath 옵션 추가 후에 디버깅을 실행하여 "http://localhost:3000"에 접속하면 404 오류 페이지가 나오는데, 로컬 실행 시에도 URL에 "/(repository 이름)" 경로를 붙여줘야 한다.

아래와 같이 .vscode/launch.json의 url, uriFormat에 "/(repository 이름)"을 추가하면 된다.

      {
        "name": "Next.js: debug client-side",
        ...
        "url": "http://localhost:3000/(repository 이름)"
      },
      {
        "name": "Next.js: debug full stack",
        ...
        "serverReadyAction": {
          ...
          "uriFormat": "%s/(repository 이름)",
          ...
        }
      }

 

반응형