ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [React.js] Next.js + Serverless 구축하기
    Web Programming/React.js 2020. 7. 27. 03:44

    국내에서는 한국어로 된 자료가 최초이지 않을까 조심스럽게 추측해봐요.

    수많은 구글링을 통해 영어로 된 자료를 모두 찾아보며 글을 작성해보도록 할게요!

     

    시작하기 전

    저는 이러한 모듈을 사용해요!

    "aws-serverless-express"
    "axios"
    "express"
    "mobx"
    "mobx-react"
    "next"
    "react"
    "react-dom"
    "styled-components"

    기본 모듈을 제외하고는 axios, mobx, mobx-react, styled-components가 있네요!

    styled-components를 ssr를 적용하느라 애 좀 먹었지만 해결을 마치는 데로 블로그 포스팅을 시작합니다.

     

    설치하기

    yarn add express aws-serverless-express
    yarn global add serverless // serverless 글로벌 설치
    yarn add -D serverless-domain-manager serverless-offline

    기본적으로 서버사이드 렌더링이기에 express를 사용하며,

    express를 간단하게 serverless로 변경해주는 모듈인 aws-serverless-express를 설치합니다.

     

    serverless가 설치되어있지 않은 분들은 글로벌로 serverless를 설치해줍니다.

     

    devDependencies으로는 serverless 프로젝트와 도메인을 간단히 설치해주는 모듈 serverless-domain-manager

    serverless 프로젝트를 로컬에서도 확인할 수 있는 모듈 serverless-offline을 설치합니다.

     

    링크

    - aws-serverless-express : https://github.com/awslabs/aws-serverless-express

    - serverless : https://github.com/serverless/serverless

    - serverless-domain-manager : https://github.com/amplify-education/serverless-domain-manager

    - serverless-offline : https://github.com/dherault/serverless-offline

     

     

    세팅 시작 - config 파일

    // .babelrc
    {
    	"presets": [
    		"next/babel"
    	],
    	"plugins": [
    		[
    			"styled-components",
    			{
    				"ssr": true,
    				"minify": true,
    				"displayName": true,
    				"preprocess": true
    			}
    		],
            ["@babel/plugin-proposal-decorators", { "legacy": true } ],
    		["@babel/plugin-proposal-class-properties", { "loose": true } ]
    	]
    }

    .bablerc 파일 설정입니다. styled-components plugin부분을 보면 ssrtrue로 두셔야 해요.

     

    // next.config.js
    
    module.exports = {
    	target: "serverless",
    	webpack: config => {
    		config.node = {
    			fs: "empty"
    		};
    		return config;
    	}
    };

    next.config.js 파일 설정입니다. targetserverless로 두어야 next build 할 때 serverless 폴더가 .next폴더에 생기므로 꼭 설정해주셔야 해요. config.node에서 fs는 empty로 둘게요.

     

    // jsconfig.json
    
    {
    	"compilerOptions": {
    		"baseUrl": "./src"
    	}
    }
    

    jsconfig.json 파일 설정입니다. compilerOptions에서 baseUrl./src로 설정하면 absolute import가 가능해져요. 필수 사항은 아니에요.

     

    설정만 해도 벌써 피곤하지만, 이제 시작합니다. 얼른 차근차근 따라와 주세요.

     

    server.js

    server.js 파일에서 express를 이용해 next.js를 렌더링 해줄 거예요. 또한 aws-serverless-express 모듈을 이용해서 serverless proxy를 만들어서 export 해줄 예정이에요.

    const express = require("express");
    const awsServerlessExpress = require('aws-serverless-express')
    const { parse } = require('url');
    const isDev = process.env.NODE_ENV !== 'production';
    
    const app = express();
    
    const getPage = page => require(`./.next/serverless/pages/${page}`).render;
    app.get("/", getPage("index"));
    
    app.use("/_next/static", express.static("./.next/static"));
    app.use("/robots.txt", function(req, res){
        res.sendFile(__dirname + "/public/robots.txt");
    });
    
    app.get("*", require("./.next/serverless/pages/_error").render);
    
    isDev && app.listen(3000, function(){
        console.log(`Ready on localhost:3000`);
    });
    
    const server = awsServerlessExpress.createServer(app);
    exports.handler = (event, context) => { awsServerlessExpress.proxy(server, event, context) }

    next build를 하게 되면 .next폴더에 serverless폴더가 있는 것을 확인하실 수 있어요.

    next.config.js 파일에서 target을 serverless로 설정했기 때문이에요.

     

    코드를 간략하게 설명드릴게요.

    - getPage function은 serverless를 import 함과 동시에 render 함수를 return 해줘요. 

    - public 폴더 안에 있는 robots.txt 파일은 /robots.txt경로로 올 경우 내보내 줍니다. sitemap.xml은 js파일로 만들기 때문에 여기서는 처리할 필요가 없어요!

    - 그 이외에는 error로 내보내도록 구현하였어요.

     

    serverless.yml

    service: nextjs-serverless
    
    provider:
      name: aws
      runtime: nodejs12.x
      stage: prod
      region: us-east-1
    
    plugins:
      - serverless-offline
      - serverless-domain-manager
    
    functions:
      index:
        handler: server.handler
        events:
          - http: ANY /
          - http: ANY /{proxy+}
    
    package:
      exclude:
        - src/**
        - scripts/**
        - .serverless/**
        - node_modules/**/*.md
        - node_modules/**/bin/**
        - node_modules/react/**
        - node_modules/react-dom/**
        - node_modules/next/**
        - node_modules/prismjs/**
        - node_modules/mobx/**
        - node_modules/mobx-react/**
        - node_modules/axios/**
        - node_modules/classnames/**
        - node_modules/react-slick/**
        - node_modules/react-typed/**
        - node_modules/sass/**
        - node_modules/styled-components/**
        - node_modules/typed.js/**
        - node_modules/disqus-react/**
      excludeDevDependencies: true
        
      include:
        - .next/**
        - public/**
        - server.js
    
    custom:
      customDomain:
        domainName: nextjs.alpoxdev.com
        certificateName: "*.alpoxdev.com"
        certificateArn: ""
        createRoute53Record: true
        basePath: ''

    가장 중요한 파트인 serverless.yml 설정!

     

    - plugin: serverless-offlineserverless-domain-manager를 추가해주세요.

    - functions : 전에 만들었던 server.js파일과 연결해줍니다. express에서 events를 조절하기에 http ANY로 설정해주세요.

    - package : 프로젝트를 AWS Lambda 올리는데 파일 제한이 있습니다. 그렇기에 package.json에 설치된 expressaws-serverless-express를 제외한 모든 모듈을 제외하고(다 제거하고 express와 aws-serverless-express를 include 하고자 했지만 express에서 추가적으로 사용되는 모듈이 많기에 설치된 모듈을 exclude 하는 게 편하다고 생각) excludeDevDependenciestrue로 설정해주세요.

    - custom : serverless-domain-manager를 설정하는 구간이에요. ACM에서 도메인 인증서를 받은 후 처리해주세요. 기회가 되면 ACM등록 방법도 포스팅하도록 하겠습니다. ACM에서 도메인 인증서를 발급하게 되면 ARN을 확인할 수 있는데, AR NcertificateArn에 넣어주세요. createRoute53 Record를 true로 설정하게 되면 Route53에서 추가로 설정 안 해도 연결됩니다.

     

    배포하기

    serverless create_domain

    serverless-domain-manager로 도메인이 API Gateway에 등록이 안되어있을 경우 도메인을 만들 수 있어요. 도메인을 만들어주세요.

     

    yarn build
    serverless deploy --verbose --aws-profile default

    next.js 프로젝트를 빌드한 후, serverless로 deploy를 해줍니다. ~/.aws/credentials 설정을 해주신 후, default로 올리시면 돼요.

    credentials는 AWS IAM에서 accessKey와 secretKey를 얻어온 후 설정하시면 돼요. default가 아니어도 되지만 저는 이렇게 할게요.

     

    끝입니다!

     

    후기

    next.js를 serverless로 배포하는 자료 자체가 너무 없었기에 하나하나 삽질을 하면서 배운 경험을 공유합니다. 저와 같이 vercel에서 aws lambda로 배포를 바꾸고 싶어 하시는 분들께 큰 도움이 됐으면 좋겠습니다.

    AWS Lambda 배포로 LIghthouse 올 100점을 만들었습니다.

     

    코드

    https://github.com/AlpoxDev/nextjs-serverless

     

     

     

    'Web Programming > React.js' 카테고리의 다른 글

    [React.js] 리액트js 구글 로그인 구현하기  (0) 2020.07.16

    댓글

Copyright 2020. Alpox(양민열)