NextJS 로컬 환경에 https 적용하는 방법

팀가이스트·2024년 2월 17일
post-thumbnail

일반적으로 개발 환경 즉, 로컬호스트 환경에서는 자동적으로 http가 적용된다.

필자의 경우, 백엔드 파트로부터 api 명세를 넘겨 받아서 개발을 하는 과정에서 문제가 생겼다. 서버쪽에서는 이미 https로 암호화된 도메인을 사용하는데 클라이언트 사이드에서는 http를 사용했기 때문이었다.

그렇다면 개발환경을 배포환경과 일치시켜 개발을 편리하게 해보자.

1. 인증 기관 설치 & 인증서 발급

// windows
choco install mkcert

// macOS
brew install mkcert

windows는 chocolatey가 설치되어 있어야하고, macOS의 경우 brew가 설치되어 있어야한다.

choco 또는 brew 명령어를 이용해서 mkcert를 설치해보자.

mkcert is a simple tool for making locally-trusted development certificates. It requires no configuration.

"mkcert는 로컬에서 신뢰할 수 있는 개발 인증서를 만들기 위한 간단한 도구입니다. 복잡한 설정을 할 필요가 없습니다." 라고 공식 깃허브에 설명이되어 있다.

mkcert github 바로가기

로컬 인증 기관을 로컬 환경에 설치한다.

mkcert -install

이 방식은 설치한 컴퓨터에서만 가능하다. 다른 컴퓨터에서 프로젝트를 clone해서 작업을 하려는 경우 mkcert 환경을 다시 한번 세팅해줘야 한다.

프로젝트 루트 경로에서 다음 키워드를 입력해보자.

mkcert localhost

위 커맨드는 localhost에 대한 key, cert를 현재 경로에 생성한다는 의미이다.
localhost-key.pem, localhost.pem 파일이 생성된 것을 확인할 수 있다.

2. 프로젝트 세팅

기존에는 next의 dev 스크립트로 개발 환경을 사용했지만 https를 적용하려면 내부적으로 서버를 커스텀해서 사용해야 한다.

루트 경로에 server.js를 생성한다.

const { createServer } = require('https');
const { parse } = require('url');
const next = require('next');
const fs = require('fs');

const hostname = 'localhost';
const port = 3000;

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

const httpsOptions = {
  key: fs.readFileSync('./localhost-key.pem'),
  cert: fs.readFileSync('./localhost.pem'),
};

app.prepare().then(() => {
  createServer(httpsOptions, async (req, res) => {
    try {
      const parsedUrl = parse(req.url, true);
      await handle(req, res, parsedUrl);
    } catch (err) {
      console.error('Error occurred handling', req.url, err);
      res.statusCode = 500;
      res.end('internal server error');
    }
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(`> Ready on https://${hostname}:${port}`);
  });
});

package.json으로 이동해서 scripts 부분을 설정해보자.
나는 명령어를 secure로 설정했다. 명령어는 마음애 드는대로 설정하자.

{
"scripts": {
    "secure": "node server.js",
  },
}

3. 자동화

새로운 인원이 참여할때마다 위 과정을 거쳐 세팅을 하게 되면 시간도 오래걸리고 생산성에 영향을 미칠수 밖에 없다.

위 과정을 쉘스크립트를 이용해서 자동화해보자.

루트 경로에 init-https.sh파일을 생성한다.

#!/bin/bash

MKCERT_INSTALLED=$(which mkcert)

# install mkcert
if [ -z $MKCERT_INSTALLED ];then 
    brew install mkcert
fi

# Create server.js file
cat <<EOT >> server.js
const { createServer } = require('https');
const { parse } = require('url');
const next = require('next');
const fs = require('fs');

const hostname = 'localhost';
const port = 3000;

const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();

const httpsOptions = {
  key: fs.readFileSync('./localhost-key.pem'),
  cert: fs.readFileSync('./localhost.pem'),
};

app.prepare().then(() => {
  createServer(httpsOptions, async (req, res) => {
    try {
      const parsedUrl = parse(req.url, true);
      await handle(req, res, parsedUrl);
    } catch (err) {
      console.error('Error occurred handling', req.url, err);
      res.statusCode = 500;
      res.end('internal server error');
    }
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(\`> Ready on https://\${hostname}:\${port}\`);
  });
});
EOT


mkcert -install
mkcert localhost

위 코드를 추가하자.
macOS 기준으로 작성된 쉘 스크립트이다.

  1. mkcert 설치 여부를 확인하고 설치가 안되어있다면 brew로 mkcert를 설치한다.
  2. 현재 경로에 server.js 파일을 생성하고 코드를 추가해준다.
  3. mkcert -install 실행
  4. mkcert localhost 실행

package.json 스크립트에 코드를 추가한다.

{
"scripts": {
    "secure": "node server.js",
    "init-https": "sh init-https.sh"
  },
}

마지막으로 localhost-key.pem, localhost.pem은 .gitigonore에 등록해준다.

0개의 댓글