Next.js를 aws에 서버리스로 배포하는 방법 with sst

순민·2024년 1월 2일
3
post-thumbnail

next11에서 serverless-next를 이용하여 배포하던 방식을(serverless-next는 현재 관리가 되지 않는 오픈소스여서 next13이후 배포를 지원하지 않습니다.) next14로 버전업을 함에 따라 SST로 변경을 했습니다.
SST를 이용하여 next.js를 배포하는 방법에 대해 공유하고자 합니다.

SST란?

SST는 Next.js,Svelte,Remix,Astro,Solid와 같은 프레임워크의 배포를 손 쉽게 도와줍니다.

사용되는 AWS의 서비스는 기본적으로 다음과 같습니다.

  • S3 : 클라이언트 자산이 위치합니다.
  • Cloudfront : 빠른 컨텐츠 전송을 위해 사용이 됩니다.
  • Lambda : app server와 api기능이 배포 됩니다. (edge플래그가 활성화된 경우 Lambda@Edge에 배포가 됩니다.)

SST로 배포하는 방법

프로젝트에 sst 세팅

npx create-sst@latest를 실행후 sst.config.ts파일이 생성이 됐는지 확인을 해줍니다.(drop-in mode)

위 사진처럼 파일이 생성되게 됩니다. npm install을 해주고 sst모듈을 받아주시면 됩니다.(빨간줄도 사라지게 됩니다.)

//package.json
"scrips":{
  "dev": "sst bind next dev"
  //...
}

dev 명령어가 next dev 에서 sst bind next dev 로 바뀐것도 인지를 해줍니다.
만약 로컬 환경에서 sst가 필요 없다면 next dev로 돌려주시면 됩니다.
(제 생각엔 로컬에서 lambda함수를 디버깅이나 테스트를 할 필요가 없다면 로컬 환경마다 credential 설정을 해야 하므로 next dev로 개발을 하는게 좋을거 같습니다.)

로컬에서 SST를 실행시키기 위한 IAM Credentials 설정

aws에 배포하기 때문에 SST가 사용할 IAM Credentials 설정을 해줘야 합니다.

저의 경우 로컬에서는 SST를 이용하지 않아서 로컬에 credential을 설정하는 과정은 생략했습니다.

로컬에 Credential 설정

일반적으로 credential 파일이 존재한다면 다음 경로에 위치합니다.

  • macOS : ~/.aws/credentials
  • windows : C:\Users\USER_NAME\.aws\credentials

내 컴퓨터에 credential파일이 없는 경우 다음 두가지 과정을 진행해줘야 합니다.

  1. IAM 사용자 생성 가이드를 이용하여 key 생성후
  2. AWS CLI를 이용하여 컴퓨터에 credential구성

위 과정을 마쳤으면 다음과 같은 파일이 생성되어야 합니다.

[default]
aws_access_key_id = <YOUR_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>

여러 자격 증명을 구성한 경우

[default]
aws_access_key_id = <DEFAULT_ACCESS_KEY_ID>
aws_secret_access_key = <DEFAULT_SECRET_ACCESS_KEY>

[staging]
aws_access_key_id = <STAGING_ACCESS_KEY_ID>
aws_secret_access_key = <STAGING_SECRET_ACCESS_KEY>

[production]
aws_access_key_id = <PRODUCTION_ACCESS_KEY_ID>
aws_secret_access_key = <PRODUCTION_SECRET_ACCESS_KEY>

기본적으로 SST는 [defalut] 프로필에 대한 credential을 사용합니다.
위의 staging이나 production중 하나를 사용하려면 AWS_PROFILE 환경 변수를 설정하면 됩니다.

$ AWS_PROFILE=staging npx sst deploy

이제 sst bind next devnpx sst deploy와 같은 명령어를 실행시키면 정상적으로 동작하는걸 확인할 수 있습니다.

GitHub Action으로 배포하기 위한 방법

OpenID Connect를 통해 AWS에 인증처리를 해줍니다.

1. 자격 증명 공급자 추가

공급자 추가를 눌러줍니다.

  • Provider URL: https://token.actions.githubusercontent.com
  • Audience: sts.amazonaws.com

위의 설정값을 넣어주고 공급자 추가를 해주면 완료입니다.

2. IAM Role 설정

공급자 상세로 들어가 줍니다.

해당 화면에서 역할 할당을 눌러줍니다.

  • Trusted entity type: Web identity
  • Identity provider: token.actions.githubusercontent.com
  • Audience: sts.amazonaws.com
  • GitHub organization: 깃헙 조직이름이나 자신의 깃헙 계정 이름

각 칸에 위와 같이 정보들을 제대로 입력을 했다면, 다음으로 넘어가줍니다.

AdministratorAccess 정책을 선택 후 다음을 눌러줍니다.

역할 이름을 입력을 해주고 역할 생성을 하면 완료입니다.

생성했던 역할 이름으로 역할 검색을 해주고 ARN을 확인해줍니다.
(arn:aws:iam::?????????:role/Ssoon과 같은 형태입니다.)

3. Github Worlfow 구성하기

name: SST workflow
on: push

# Concurrency group name ensures concurrent workflow runs wait for any in-progress job to finish
concurrency:
  group: merge-${{ github.ref }}

permissions:
  id-token: write # This is required for requesting the JWT
  contents: read # This is required for actions/checkout

jobs:
  DeployApp:
    runs-on: ubuntu-latest
    steps:
      - name: Git clone the repository
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::????????:role/Ssoon
          aws-region: us-east-1
      - name: Deploy app
        run: |
          npm i && npx sst deploy --stage prod

두가지 부분만 수정을 해주면 됩니다.

  • role-to-assume : 위에서 설정한arn:aws:iam::?????????:role/Ssoon를 입력해주면 됩니다.

  • aws-region : sst.config.ts에 설정한 region을 적어주면 됩니다.

모든 과정을 마치고 github action을 실행시켜보면 정상적으로 배포가 되는걸 확인할 수 있습니다.

SST 배포환경별 설정및 사용자 지정 도메인 구성

배포 환경별 설정

stage option을 이용하여 production과 staging환경을 나눌수 있습니다.

$ npx sst deploy --stage prod

stage에 전달한 값이 sst config파일에 아래와 같이 전달이 됩니다.

//sst.config.ts
import { SSTConfig } from "sst";
import { NextjsSite } from "sst/constructs";

export default {
  config(_input) {
    return {
      name: _input.stage === "prod" ? "prod-web" : "staging-web",
      region: "us-east-1",
    };
  },
  stacks(app) {
    if (!["dev", "prod"].includes(app.stage)) {
      throw new Error("Invalid stage");
    }
    app.stack(function Site({ stack }) {
      const site = new NextjsSite(stack, "site", {
        customDomain: {
          domainName:
            stack.stage === "prod" ? "naver.com" : "dev.naver.com",
            hostedZone: "naver.com",
        },
      });
      stack.addOutputs({
        SiteUrl: site.url,
      });
    });
  },
} satisfies SSTConfig;

Route 53을 사용할 경우

customDomain 부분의 hostedZoneRoute 53호스팅 영역을 적어주면 됩니다.
domainName 부분에는 말 그대로 도메인명을 적어주면 됩니다. 만약 하위 도메인을 적어주면 sst에서 자동으로 하위 도메인을 생성해서 배포를 진행해줍니다.

외부 호스팅을 사용할 경우

제일 간단한 방식은 Route 53으로 이동시키는 것입니다.
1. 사용 중인 도메인을 Route 53으로 DNS 서비스로 설정 - 도메인이 현재 많은 트래픽이 있을 경우에 대한 방법
2. 비활성화된 도메인을 Route 53으로 DNS서비스로 설정 - 도메인이 사용되지 않거나 많은 트래픽이 없을 경우에 대한 방법

Route 53을 사용하지 않을 경우
CNAME레코드를 생성하고 이를 CloudFront배포로 지정하면됩니다.
배포를 했을때 자동으로 생성되는 URL인 d1p6z4d11yxxds.cloudfront.net을 가리키면 됩니다.
자세한 내용은 공식문서에 있습니다.

SST의 장점

SST의 단점

  • Next의 경우 open-next기반으로 배포 처리가 되는데, 공식문서를 확인해보면 현재 스트리밍 기술은 실험적인 단계로 지원을 하고 있습니다. 프로덕션에서는 사용하지 않기를 권장하고 있습니다.
  • vercel보다 비교적 적은 커뮤니티가 형성되어 있습니다.
  • Next.js에서 제공하는 최신 기술이 나오게 되면 해당 기술을 반영하기 까지 오래 걸릴수도 있습니다.
  • vercel에 비해 배포하는 과정이 살짝 까다롭습니다.

번외

serverless-next에서 sst로 이관하는 방법에 대해 알아보겠습니다.

  1. serverless-next 관련된 패키지를 다 삭제해주고 관련 파일도 삭제를 해줍니다.
  2. 기존에 serverless-next를 배포함에 따라 생성된 aws에서의 cloudfront를 삭제를 해줍니다.
  3. Route 53에 들어가서 배포할 호스트에 연결되어 있는 A레코드를 전부 삭제를 해줍니다.
  4. 위에서 설명한 내용과 같이 sst에 대한 설정을 전부 마치고 aws에 배포를 해주면 정상적으로 배포가 진행이 되는걸 확인할 수 있습니다.
profile
개발을 재밌게!

0개의 댓글