[AWS] Next.js 환경 구축하기 (Serverless)

본 포스트에서는 AWS 환경에서 Nextjs 환경을 구축하는 법에 대해 다룬다.

일반적인 정적페이지는 S3+Cloudfront 만으로 충분히 구현 가능하나, nextjs는 서버가 필요하다.
그래서 여기에서는 Lambda Edge가 추가로 사용될 것이다.

그래서 보통 아래와 같은 구조를 가진다.

출처 https://registry.terraform.io/modules/dealmore/next-js/aws/latest
하나하나 직접 세팅하려면 번거로운게 한두개가 아니라서, 본 포스트에서는 자동화된 도구 serverless를 사용해서 배포를 해보도록 한다.

관련 서비스들을 써보지 않았다면, 한번쯤 먼저 봐두면 괜찮겠다.

참조
https://blog.naver.com/sssang97/222567479583
https://blog.naver.com/sssang97/222395985480
https://blog.naver.com/sssang97/222504226420




Next.js 프로젝트 생성

git 레포지토리 파주고, npx를 사용해서 프로젝트를 생성해준다.

npx create-next-app@latest --typescript .

타입스크립트가 싫다면 --typescript 플래그를 제거하면 되고, 별도 디렉터리로 생성하고 싶다면 경로값 .를 제거하면 된다.


이렇게 생성되면 잘 된 것이다.

.gitignore에도 이걸 좀 추가해주면 좋겠다.
.env를 제외하고는 serverless에서 뱉는 찌꺼기다.

.env
.serverless/
.serverless_nextjs
.swc/



S3 버킷 생성

정적페이지를 저장해놓고 렌더링시킬 버킷을 생성한다.

특별히 뭘 설정할건 없다.




cloudfront 배포 생성

그리고 저 버킷을 기반으로 하는 cloudfront를 생성해준다.

그리고 나오는 저 배포 번호 E3E54UMBLWT141를 좀 있다가 사용할 것이다.




서버리스 설정

serverless는 기존의 프레임워크들을 aws lambda에 맞게 말아서 배포해주는 편리한 보조도구다.
먼저 아래 버전으로 깔아준다.

 npm install --save-dev serverless@2.72.2

3.0 버전도 있긴 있는데.. 뭐가 좀 잘 안되는게 있다.

그리고 next용 serverless 컴포넌트를 추가로 깔아준다.

npm install --save-dev @sls-next/serverless-component@3.7.0

그리고 서버리스용 설정파일을 프로젝트 루트경로에 만들어준다.

awsNestJs:
  component: "./node_modules/@sls-next/serverless-component"
  inputs:
	  bucketName: 'myyrakle-nextjs'
	  cloudfront:
	    distributionId: E3E54UMBLWT141
	  name:
	    defaultLambda: 'next-js-default'
	    apiLambda: 'nextjs-api'

만들어놓은 버킷 이름과 Cloudfront 배포 번호를 넣고, 생성할 람다 이름을 적절히 써넣어준다.
해당 이름의 함수가 있다면 있는대로 쓰고, 없다면 자동으로 만들어준다.

여기서는 기본적인 설정값만 넣었지만, 다른것도 많다.
자세한건 문서를 참조하길 바란다.
https://github.com/serverless-nextjs/serverless-next.js/

그리고 serverless에서 내 AWS에 접속할 수 있도록 인증키를 환경변수에 넣어준다.

계정을 만들고 키를 받는건 다음 포스트를 참조하면 된다.
https://blog.naver.com/sssang97/222503738493

루트계정이라면 상관없지만, 추가로 만든 계정이라면 꽤나 많은 권한을 부여해줘야 한다.
배포에 필요한 권한은 다음과 같다.

  "acm:DescribeCertificate", // only for custom domains
  "acm:ListCertificates",    // only for custom domains
  "acm:RequestCertificate",  // only for custom domains
  "cloudfront:CreateCloudFrontOriginAccessIdentity",
  "cloudfront:CreateDistribution",
  "cloudfront:CreateInvalidation",
  "cloudfront:GetDistribution",
  "cloudfront:GetDistributionConfig",
  "cloudfront:ListCloudFrontOriginAccessIdentities",
  "cloudfront:ListDistributions",
  "cloudfront:ListDistributionsByLambdaFunction",
  "cloudfront:ListDistributionsByWebACLId",
  "cloudfront:ListFieldLevelEncryptionConfigs",
  "cloudfront:ListFieldLevelEncryptionProfiles",
  "cloudfront:ListInvalidations",
  "cloudfront:ListPublicKeys",
  "cloudfront:ListStreamingDistributions",
  "cloudfront:UpdateDistribution",
  "cloudfront:TagResource",         // for adding tags
  "cloudfront:UntagResource",       // for adding tags
  "cloudfront:ListTagsForResource", // for adding tags
  "iam:AttachRolePolicy",
  "iam:CreateRole",
  "iam:CreateServiceLinkedRole",
  "iam:GetRole",
  "iam:PutRolePolicy",
  "iam:PassRole",
  "lambda:CreateFunction",
  "lambda:EnableReplication",
  "lambda:DeleteFunction",            // only for custom domains
  "lambda:GetFunction",
  "lambda:GetFunctionConfiguration",
  "lambda:PublishVersion",
  "lambda:UpdateFunctionCode",
  "lambda:UpdateFunctionConfiguration",
  "lambda:ListTags",                  // for tagging lambdas
  "lambda:TagResource",               // for tagging lambdas
  "lambda:UntagResource",             // for tagging lambdas
  "route53:ChangeResourceRecordSets", // only for custom domains
  "route53:ListHostedZonesByName",
  "route53:ListResourceRecordSets",   // only for custom domains
  "s3:CreateBucket",
  "s3:GetAccelerateConfiguration",
  "s3:GetObject",                     // only if persisting state to S3 for CI/CD
  "s3:ListBucket",
  "s3:PutAccelerateConfiguration",
  "s3:PutBucketPolicy",
  "s3:PutObject",
  "s3:PutBucketTagging",              // for tagging buckets
  "s3:GetBucketTagging",              // for tagging buckets
  "lambda:ListEventSourceMappings",
  "lambda:CreateEventSourceMapping",
  "iam:UpdateAssumeRolePolicy",
  "iam:DeleteRolePolicy",
  "sqs:CreateQueue", // SQS permissions only needed if you use Incremental Static Regeneration. Corresponding SQS.SendMessage permission needed in the Lambda role
  "sqs:DeleteQueue",
  "sqs:GetQueueAttributes",
  "sqs:SetQueueAttributes"



배포

이제 배포를 해보자.
package.json에 배포 명령을 추가해주고

명령을 사용한다.

그럼 보통 5분 이상은 걸린다.

그러고 나서 보면 요소들이 생성되어있을 것이고

배포도 잘 되어있을 것이다.

어렵지 않다.
이게 다다.



참조
https://github.com/serverless-nextjs/serverless-next.js/
https://falsy.me/%EC%83%88%EB%A1%9C%EC%9A%B4-%EB%B2%84%EC%A0%84-serverless-framework%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-nextjs-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-aws-lambda%EB%A5%BC-%ED%86%B5/