Next js앱 github action 이용해서 github-page/vercel에 배포하기

zmin·2022년 10월 2일
0

지난 번 github-page 배포는 react 앱이이었고 이번에는 Next js 앱을 배포해봤다 with github action
이 과정을 간단히 서술한다. #다사다난

github action

CI/CD

https://www.redhat.com/en/topics/devops/what-is-ci-cd#:~:text=CI%2FCD%20is%20a%20method,continuous%20delivery%2C%20and%20continuous%20deployment


continuous integrationcontinuous delivery/deployment의 줄임말이다.

보통 분업하여 작업할 때 계속 끝까지 따로 작업하다가 마지막에 한 번에 합칠 수는 없다. 지속적으로 서로의 코드를 통합하고 테스트하는 과정이 필요 → CI

  • 이 과정이 없으면 엄청 많이 개발했는데 합쳐보니 맞지 않아서 처음부터 다시 개발해야하는 상황이 생길 수 있다.
    특히 각 요소들을 세세하게 분리하여 작업하는 경우 꼭 필요하다.
  • 각자 idle등을 통해 진행하는 검사와는 다르다
    협업에서 발생할 수 있는 문제 사항들을 초기에 발견할 수 있도록 하는 과정

이렇게 합치면서 개발 단계에서만 끝나는 것이 아니라 지속적으로 이 개발된 것들을 실제로 production으로 만들어주는 과정 → CD

둘다 직접 할 수 있겠지만 굉장히 번거롭다. 불필요한 시간을 줄여서 개발 시간을 단축해야함. 그래서 많은 관련 툴을 많이 제공해주고 있음. 그중 하나가 github action

github action 기본

https://docs.github.com/en/actions/quickstart
양이 많은데 typescript 공부하듯이 하기엔 좀 불필요 한 것 같아서 기본적인 틀만 이해했다.

레포지토리 루트에 .github/workflows.yml 을 정의하여 액션을 추가한다.

workflow는 트리거 이벤트를 기반으로 작동한다. 특정한 이벤트(push, merge 등)가 발생했을 때 지정해둔 job을 하며 workflow를 따라가도록 지정해주는 것

job은 말그대로 workflow에서의 작업들을 의미한다. push발생시 eslint를 돌린다, merge발생시 build를 한다.

다른 job에 의존성을 가질 수도 있다. 1번 job이 실행되어야 2번 job이 실행될 수 있는 것.
이런 job들은 은 실제로 runs-on 항목에 정의된 가상환경에서 실행한다.

아래는 workflow 파일(확장자 .yml)의 예시 코드

name: learn-github-actions
on: [push]
jobs:
  check-bats-version:        # 작업의 이름
    runs-on: ubuntu-latest   # 어느 가상환경에서 이를 작동시킬 것인지
    steps:                   # 이 작업의 단계들을 차례로 정의. 단계는 - 으로 구분한다.
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '14'
      - run: npm install -g bats
      - run: bats -v
  • name: workflow의 이름 - learn-github-actions
  • on: 트리거 이벤트 - push
  • jobs: 해당 이벤트 발생시 진행할 작업들을 그룹화. 바로 하위 depth에 작업들의 이름 check-bats-version:으로 여러 작업을 정의한다.
    • 여기서 uses 는 이미 정의되어있는 action을 사용할 때 [소유자]/[액션 이름]의 형태로 작성
  • 각 스텝의 키워드와 자세한 사용은 여기 참조
  • github action에서 simple workflow config를 누르면 나오는 기본 코드도 설명이 잘 되어있다

github-page

https://github.com/vercel/next.js/tree/canary/examples/github-pages
를 참고해서 package.json의 값 아래처럼 수정

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

하지만 이렇게 하고 yarn run deploy를 실행하면 했는데 out/.nojekyll 을 찾을 수 없다는 에러와 함께 배포가 안된다..

당연하다 out폴더 자체를 만들지 않았음. next export를 실행하면 out/ 폴더가 생기고 그 아래에 배포될 파일들이 들어가게 그냥 빌드만 해서 /.next 안에 빌드된 파일들이 생기기만 한 것.. 이걸 빼먹니

  • nojekyll?
    • next js는 _app 처럼 언더스코어로 시작하는 파일명들이 존재하는데 깃허브 페이지에서 기본적으로 사용하는 jekyll프로세스는 이런 파일들을 무시한다. 그래서 jekyll을 사용하지 않겠다고 말해줘야한다.

그래서 next export도 추가해서 만들어줍니다. 아래가 최종적으로 완성된….이 아니라
이렇게만 쓰면 이미 gh-pages가 존재한다고 뜨기 때문에 강제로 업데이트를 해줘야해서
아예 새롭게 가상환경의 로컬에 브랜치를 만들어주고 origin으로 force push 한다.

"deploy": "next export && touch out/.nojekyll && git add -f out/ && git commit -m \"Deploy\" && git subtree split --prefix out -b gh-pages && git push -f origin gh-pages:gh-pages && git branch -D gh-pages",

이렇게 쓰면 배포는 성공하는데 next js가 구성해서 보내는 html로만 만들어진 페이지가 존재한다. css-in-js, js, image같은 파일들의 path가 제대로 설정되지 않아서 파일을 찾을 수가 없는 것이다.
next.config.jsassetPrefix을 설정하여 asset들을 요청할 때 prefix로 붙일 path를 설정해준다.

또한 이미지 최적화를 위해서 next js에서 제공하는 <Image>태그를 이용했는데 여기서도 문제 생김 → 해결을 반복한다.

  • optimizing에 사용되는 default로더를 next export 에서는 사용할 수 없어서 아예 빌드가 되지 않았다.
    다른 기본 제공 로더를 사용
  • 깃허브 페이지의 경우 요청을 보내는 base 주소가 https://{닉네임}.github.io/ 이기 때문에 (레포지토리 이름을 포함하지 않음) assetPrefix/레포지토리명으로 지정해줘야한다. 하지만 한 번만 입력했음에도 중복으로 입력되는 것zmin9.githhub.io/premium-page/premium-page)을 발견.
    → 위에서 로더 지정할 때 path를 ‘’으로 입력했더니 Image 컴포넌트의 원래 요청 prefix 주소 zmin9.githhub.io/premium-page 으로 설정되서 아예 images.path를 아래와 같이 사이트 주소로 설정해주었다.

그렇게 완성된 next.config.js

/**
 * @type {import('next').NextConfig}
 */

const isProduction = process.env.NODE_ENV === 'production';

export default {
  compiler: {
    styledComponents: true
  },
  eslint: {
    ignoreDuringBuilds: true,
  },
  images: {
    loader: 'akamai',
    path: isProduction ? 'https://zmin9.github.io' : 'http://localhost:3000',
  },
  assetPrefix: isProduction ? '/premium-page' : '',
};

완성된 workflow

on:
  push:
    branches:
      - main
jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: yarn set version 3.2.2
      - run: yarn install
      
      - name: Build
        run: yarn build

      - run: yarn run export        # scripts : { export: 'next export' }
      - run: touch ./out/.nojekyll  #위에서 말한 것처럼 이파일을 추가하지 않으면 _app 인식 못함

      - name: Deploy 🚀
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          branch: gh-pages
          folder: out

위를 보면 알 수 있지만 결국 만들어둔 yarn run deploy는 쓰지 않았다... 왜냐면 github config 인증하는 과정도 따로 추가해줘야하고 이미 잘 만들어진 액션이 있으면 그걸 써서 불필요한 작업을 줄이는게 좋다고 생각했기 때문이다.
물론 이미 yarn run deploy를 만들었기 때문에 시간을 절약했다고 볼 수는 없었지만 그 과정을 깨닫는 것도 + 한 번 정도는 경험해보는 것도 좋았다고 생각...^_^ 아무튼... 이제 main branch에 push가 일어나면 잘 배포된다.

vercel

은 훨씬 쉽다.
이유: vercel 홈페이지에 그냥 있음
https://vercel.com/guides/how-can-i-use-github-actions-with-vercel

그리고 vercel의 좋은 점이라하면 preview 배포와 production 배포를 구분할 수 있다는 건데 위 링크에서 .github/workflows/production.yaml만 만들면 모든 브랜치에서 preview deploy가 이루어지는 약간은 비효율적인 상황이 생긴다.

  1. 만약 preview deploy를 특정 브랜치에서만 일어나게 하고싶다면
    위 링크에서 .github/workflows/preview.yaml의 branches 부분을 수정한다.
    on:
      push:
        branches-ignore:
          - main

          를

    on:
      push:
        branches:
          - 특정 브랜치 이름
  1. 아예 이용하고 싶지 않다면
    vercel dashboard > 현재 프로젝트 > project setting > Git > Ignore build step 수정 [ "$VERCEL_ENV" != production ]

아주 잘 작동한다.

profile
308 Permanent Redirect

0개의 댓글