AWS EC2에 Next.js 프로젝트 자동 배포하고 호스팅까지

Woody·2024년 12월 17일
post-thumbnail

배포 과정 전체 단계
1. IAM 계정 생성 (보안을 위해 Root 계정 대신 사용)
2. EC2 인스턴스 설정
3. 필수 소프트웨어 설치 및 프로젝트 설정
4. GitHub Actions 설정
5. Nginx 설정
6. 도메인 설정
7. HTTPS(SSL) 설정

1. IAM 계정 생성

이전 S3에 클라이언트 코드를 배포할 때는, Root계정으로 진행했었지만, 보안상 좋지않습니다.
이번에 진행했던 프로젝트에는 openAI의 API키를 사용하기 때문에 더욱 보안에 신경써야 하므로 IAM계정을 사용합니다.

IAM 계정 생성 - 참고 블로그

2. EC2 인스턴스 설정

인스턴스 생성 - 참고 블로그

2-1. 인스턴스 생성 기본 설정

Ubuntu Server + 프리티어(무료)버전의 tc.micro 인스턴스로 선택해줍니다.

2-2. 키 페어 저장하기

RSA유형, .pem형식으로 발급받고 저장해줍니다.

2-3. 보안 그룹 규칙 설정하기

보안그룹 설정으로 다음 포트들을 열어 줍니다.
22 - SSH (기존 설정되어 있던 것)
80 - HTTP (Nginx) 👈🏻 추가!
443 - HTTPS (SSL) 👈🏻 추가!
3000 - Next.js 👈🏻 추가!

2-4. 스토리지 설정하기

30GB까지 무료이므로 30GB로 설정해줍니다.

인스턴스 시작 버튼을 눌러 생성해줍니다.

3. 필수 소프트웨어 설치 (Node.js, pnpm, PM2, Nginx)

EC2 접속

인스턴스 연결 > SSH 클라이언트탭의 명령어로 인스턴스에 접속해줘야합니다.

아까 저장했던.pem 파일이 위치한 경로에서 터미널을 열어줍니다.

SSH는 보안상의 이유로 프라이빗 키 파일의 권한이 너무 개방적인 경우 접속을 거부합니다.
그렇기 때문에 키 파일의 권한이 나에게만 읽기 권한이 있도록 권한을 축소시킵니다.
(chmod 400의 의미는 4/0/0 이므로 )

그 다음 인스턴스에 연결합니다.

chmod 400 ~~~.pem

❯ ssh -i "job-cracker-key.pem" ubuntu@ ~~~amazonaws.com

설치 - 참고 블로그

필수 소프트웨어 설치

Node.js & npm

# Node.js 최신 버전 설치 (또는 프로젝트에 맞는 버전)curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
❯ sudo apt-get install -y nodejs
# npm 설치sudo npm install -g npm@latest

pnpm

# pnpm 설치 (프로젝트 버전)sudo npm install -g pnpm@9.12.3

무중단 배포 구성: PM2

  • Node.js 애플리케이션 프로세스 관리
  • 앱 크래시 시 자동 재시작
  • 로그 관리와 모니터링 기능 제공

기본적인 무중단 배포 흐름
: 사용자 요청 -> Nginx -> PM2로 관리되는 Node.js 앱

# PM2 전역 설치sudo npm install -g pm2

무중단 배포 구성: Nginx

  • 리버스 프록시 역할
  • 포트 포워딩
  • 정적 파일 서빙
  • Blue-Green 배포 시 트래픽 전환 역할
# Nginx 설치sudo apt-get install nginx

# Nginx 설정 파일 열기sudo nano /etc/nginx/sites-available/프로젝트이름
server {
    listen 80;
    server_name ; #일단비워둠(나중에 도메인 생기면 변경)

    location / {
        proxy_pass http://localhost:3000;  # Next.js 앱 포트
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

위 내용을 붙여넣은 후

Ctrl + O를 눌러 저장
Enter를 눌러 확인
Ctrl + X를 눌러 나가기

# 심볼릭 링크 생성해서 설정 활성화sudo ln -s /etc/nginx/sites-available/프로젝트이름 /etc/nginx/sites-enabled/
# 기본 설정 제거sudo rm /etc/nginx/sites-enabled/프로젝트이름  
# Nginx 설정 테스트sudo nginx -t
# Nginx 재시작sudo systemctl restart nginx

이제 EC2의 IP주소로 직접 접속하면 (포트 3000 없이) Next.js 앱에 접근할 수 있습니다.

  • 주의
    EC2 보안그룹에서 80포트(HTTP)가 열려있어야 합니다
    기존 PM2로 실행중인 Next.js 앱이 3000포트에서 실행중이어야 합니다

프로젝트 클론

# 홈 디렉토리로 이동cd ~  
❯ git clone ~

4. GitHub Actions 설정 (워크플로우 파일, Secrets)

Secrets 설정 (GitHub 레포지토리)

.env에 사용하는 값들과, SSH_KEY, EC2 IP주소를 등록해줍니다.

  • EC2_HOST: 퍼블릭 IPv4 주소
    예: 54.163.47.244 형태의 IP 주소

  • EC2_SSH_KEY: 인스턴스 연결할 때 사용했던 .pem 파일의 내용

    로컬 컴퓨터에서 .pem 파일을 텍스트 에디터로 열어서
    -----BEGIN RSA PRIVATE KEY-----부터 -----END RSA PRIVATE KEY-----까지 모든 내용을 복사하여 넣어줍니다.

# EC2 접속 후 각각 위치를 확인which pnpm  # pnpm 위치 확인which pm2   # pm2 위치 확인

워크플로우 파일 생성 (.github/workflows/deploy.yml)

name: Deploy to EC2

on:
  push:
    branches: ['main']

# 동시 실행 방지 추가
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20'

      - name: Install pnpm
        run: npm install -g pnpm@9.12.3

      - name: Deploy to EC2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ubuntu
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            cd ~/Job-Cracker
            echo "OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}" > .env
            git pull
            /usr/bin/pnpm install
            /usr/bin/pnpm build
            /usr/bin/pm2 delete all || true
            /usr/bin/pm2 start ecosystem.config.cjs

5. PM2 설정

로컬의 프로젝트 루트에 ecosystem.config.cjs 파일을 생성하고, git에도 올려줍니다.

module.exports = {
  apps: [{
      name: '프로젝트 이름',
      cwd: './',
      script: 'node_modules/next/dist/bin/next',
      args: 'start -p 3000', // 3000 포트 설정
      exec_mode: 'cluster',
      instances: 0,
      autorestart: true,
      listen_timeout: 50000,
      kill_timeout: 5000
  }]
}

next.config.ts 파일말고 해당 파일에서 server설정을 해줍니다.

6. 도메인 설정 (가비아 구매 → Route53 설정)

도메인 구매

저는 가비아에서 저렴한 도메인을 구매했습니다.

AWS Route53에서 호스팅 영역 생성

Route53 에서 호스팅 영역 생성
도메인 이름에 "구매한 도메인" 입력
생성 완료 후 NS(네임서버) 레코드 4개 복사

www 서브도메인을 설정하기위해 Route53에서 A 레코드를 하나 더 추가합니다.

Route53에서 추가 A 레코드 생성

  • AWS Console → Route53 → 호스팅 영역 → jobcracker.site
  • "레코드 생성" 클릭
  • 이름: www
  • 레코드 유형: A
  • 값: EC2의 퍼블릭 IP 주소
  • 생성!

네임서버 설정

가비아에서 구매했언 도메인을 선택하고 네임서버 설정
Route53에서 제공한 네임서버 주소 4개를 차례대로 입력합니다. 뒤에 '.'은 빼주세요
(예: ns-1234.awsdns-12.org 형식)

DNS 수정 > 레코드 관리까지 수정해줍니다.

참고 블로그

DNS 레코드 설정

호스팅 영역에서 "레코드 생성" 클릭
레코드 유형: A
값: EC2의 퍼블릭 IP 주소 입력

7. Nginx 설정 수정

nano 에디터에서 저장하고 나가는 방법
저장: Ctrl + O 를 누른 후 Enter
종료: Ctrl + X

sudo nano /etc/nginx/sites-available/프로젝트이름

구매한 도메인으로 변경합니다.

server {
    listen 80;
    server_name 도메인주소 www.도메인주소; #아까 비워둔 곳을 구매한 도메인으로 변경

    location / {
        proxy_pass http://localhost:3000;  # Next.js 앱 포트
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

설정을 변경한 후에는 반드시!

sudo nginx -t        # 설정이 올바른지 테스트sudo systemctl reload nginx  # 새로운 설정 적용

8. HTTPS(SSL) 설정

Let's Encrypt라는 무료 SSL 인증서를 사용하여 설정해보겠습니다.

왜 HTTPS를 써야할까?

HTTPS는 웹사이트의 보안을 위해서 매우 중요합니다.

1. 데이터 보안
- 사용자와 서버 간의 모든 통신을 암호화
- 개인정보, 비밀번호 등이 노출되는 것을 방지
_특히 제가 배포하는 사이트는 OpenAI API 키를 사용하므로 보안이 중요!_

2. 브라우저 경고 방지
- 최신 브라우저들은 HTTP 사이트를 "안전하지 않음"으로 표시
- 사용자들에게 경고 메시지를 보여줄 수 있음

3. 신뢰성
- 브라우저의 자물쇠 아이콘이 사이트의 신뢰성을 보여줌
- 사용자들이 안심하고 사이트 이용 가능

4. SEO 이점
- Google은 HTTPS 사이트를 검색 순위에서 우대
- 검색 엔진 최적화에 도움

Certbot 설치

Let's Encrypt 인증서는 90일마다 갱신이 필요한데, certbot이 자동으로 갱신해줍니다.
snap으로 설치해보겠습니다. 자동으로 갱신 크론잡이 설정됩니다.

# 1. snap으로 certbot 설치sudo snap install core
❯ sudo snap refresh core
❯ sudo snap install --classic certbot
❯ sudo ln -s /snap/bin/certbot /usr/bin/certbot

# 2. 인증서 발급sudo certbot --nginx -d 도메인 -d www.도메인

9. 쨘!

https://jobcracker.site/

profile
우디 월드

0개의 댓글