πŸ’ͺμ˜¨ν•(on-fit) 첫 CI/CD 배포기 1편

μ‘°μ€€ν˜•Β·2025λ…„ 11μ›” 18일

μ˜¨ν•

λͺ©λ‘ 보기
8/16

EC2에 Next.js 올리기 (μˆ˜λ™ 배포)

μ˜¨ν• ν”„λ‘œμ νŠΈμ—μ„œ κΈ°λŠ₯이 μ–΄λŠ 정도 μ™„μ„±λ˜μžλ§ˆμž κ°€μž₯ λ¨Όμ € λ– μ˜€λ₯Έ 건 λ”± ν•˜λ‚˜μ˜€λ‹€.

β€œμ΄μ œβ€¦ μ§„μ§œ μ„œλΉ„μŠ€μ²˜λŸΌ μ£Όμ†Œ 찍고 접속해보고 μ‹Άλ‹€.”

이번 글은 Next.js + Supabase 기반 μ˜¨ν•(on-fit) ν”„λ‘œμ νŠΈλ₯Ό AWS EC2에 처음 λ°°ν¬ν•œ 과정을 μ •λ¦¬ν•œ 기둝이닀.

특히 프리티어 ν•œλ„ μ•ˆμ—μ„œ μ–΄λ–»κ²Œ μ„€μ •ν–ˆλŠ”μ§€, 그리고 GitHub Actions둜 CI/CDκΉŒμ§€ μ—°κ²°ν•˜λ©΄μ„œ μ–΄λ–€ μ‚½μ§ˆμ„ ν–ˆλŠ”μ§€ λ‹¨κ³„λ³„λ‘œ 적어본닀.


1. 전체 μ•„ν‚€ν…μ²˜ κ·Έλ¦Ό

이번 배포의 λͺ©ν‘œ μ•„ν‚€ν…μ²˜λŠ” μ•„μ£Ό μ‹¬ν”Œν–ˆλ‹€.

  • ν΄λΌμ΄μ–ΈνŠΈ/μ„œλ²„: Next.js 16 (App Router, Turbopack)
  • DB/Auth: Supabase (PostgreSQL + Auth)
  • 인프라: AWS EC2 (Ubuntu, t2.micro / 프리티어)
  • ν”„λ‘œμ„ΈμŠ€ 관리: PM2
  • Reverse Proxy + HTTPS: Nginx + Certbot
  • CI/CD: GitHub Actions β†’ EC2 SSH β†’ git pull + build + pm2 restart

즉, 그림으둜 그리면:

GitHub(dev/main) ──▢ GitHub Actions ──SSH──▢ EC2
                                     β”‚
                                     β”œβ”€ pm2: onfit (Next.js)
μ‚¬μš©μž λΈŒλΌμš°μ € ──▢ onfit.today ──DNS──▢ EC2 ──Nginx──▢ localhost:3000 (Next)

2. EC2 μΈμŠ€ν„΄μŠ€ 생성

ν”„λ¦¬ν‹°μ–΄λ§Œ μ“Έ 수 μžˆμ–΄μ„œ κ°€μž₯ 기본적인 μ„ΈνŒ…μœΌλ‘œ μ‹œμž‘ν–ˆλ‹€.

  • 리전: ap-northeast-1 (도쿄) – ν•œκ΅­μ΄λž‘ κ°€κΉŒμš΄ 리전
  • μΈμŠ€ν„΄μŠ€ νƒ€μž…: t2.micro (프리티어 κ°€λŠ₯)
  • AMI: Ubuntu Server 22.04 LTS
  • ν‚€νŽ˜μ–΄: onfit.pem (μΆ”ν›„ GitHub Actionsμ—μ„œ μ‚¬μš©ν•  핡심)

λ³΄μ•ˆ 그룹은 μ²˜μŒμ— μ΄λ ‡κ²Œ μ—΄μ–΄λ’€λ‹€.

  • 22번 포트(SSH): λ‚΄ IP만 ν—ˆμš©
  • 80번 포트(HTTP): 0.0.0.0/0
  • 3000번 포트: 0.0.0.0/0 (μ²˜μŒμ—” 직접 접속 ν…ŒμŠ€νŠΈ μœ„ν•΄, λ‚˜μ€‘μ— Nginx 뢙인 ν›„μ—” μ•ˆ 써도 됨)

μΈμŠ€ν„΄μŠ€κ°€ 뜨고 λ‚˜λ©΄ 퍼블릭 IPλ₯Ό ν•˜λ‚˜ λ°›κ²Œ λœλ‹€.

예λ₯Ό λ“€μ–΄:

EC2 Public IP: 35.74.238.231  (μ˜ˆμ‹œ)

3. SSH 접속: pem 파일둜 μ„œλ²„μ— λ“€μ–΄κ°€κΈ°

λ§₯μ—μ„œ pem 파일 κΆŒν•œμ„ λ¨Όμ € μ‘°μ •ν•œλ‹€.

chmod 400 ~/Downloads/onfit.pem

그리고 μ•„λž˜μ²˜λŸΌ 접속:

ssh -i ~/Downloads/onfit.pem ubuntu@35.74.238.231

처음 접속할 λ•ŒλŠ” 이런 λ©”μ‹œμ§€κ°€ λœ¬λ‹€.

The authenticity of host '35.74.238.231 (...)' can't be established.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

μ—¬κΈ°μ„œ yes 치면 λœλ‹€.


4. μ„œλ²„ κΈ°λ³Έ μ„ΈνŒ… (Node, git, nginx, pm2)

4-1. νŒ¨ν‚€μ§€ μ—…λ°μ΄νŠΈ

sudo apt update
sudo apt upgrade -y

4-2. Node.js 20 μ„€μΉ˜

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -v   # v20.x 확인
npm -v

4-3. git & nginx & certbot μ„€μΉ˜

sudo apt install -y git nginx
sudo apt install -y certbot python3-certbot-nginx

4-4. pm2 κΈ€λ‘œλ²Œ μ„€μΉ˜

sudo npm install -g pm2
pm2 -v

5. ν”„λ‘œμ νŠΈ μ½”λ“œ κ°€μ Έμ˜€κΈ°

이제 EC2 μ•ˆμ—μ„œ GitHub 레포λ₯Ό ν΄λ‘ ν–ˆλ‹€.

cd ~
git clone https://github.com/Jojunhyeong/on-fit.git
cd on-fit/on-fit-next

μ˜¨ν• 레포 ꡬ쑰가 λŒ€λž΅ 이런 λŠλ‚Œμ΄λ‹€.

on-fit/
  β”œβ”€ on-fit-next/   # Next.js ν”„λ‘ νŠΈ + μ„œλ²„
  └─ ... (기타)

6. μ„œλ²„μ—μ„œ .env μ„ΈνŒ…

μ€‘μš”ν•œ 건 ν™˜κ²½λ³€μˆ˜λŠ” μ ˆλŒ€ GitHub에 μ˜¬λ¦¬μ§€ μ•ŠλŠ”λ‹€λŠ” 점.

κ·Έλž˜μ„œ EC2 μ•ˆμ—μ„œ 직접 .env νŒŒμΌμ„ λ§Œλ“€μ—ˆλ‹€.

cd ~/on-fit/on-fit-next
nano .env

그리고 λ‘œμ»¬μ—μ„œ μ‚¬μš©ν•˜λ˜ 값듀을 κ·ΈλŒ€λ‘œ 넣어쀬닀. μ˜ˆμ‹œ:

NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
NEXT_PUBLIC_SITE_URL=https://onfit.today
...

μ €μž₯(Ctrl+O) ν›„ nano μ’…λ£Œ(Ctrl+X).


7. μˆ˜λ™ λΉŒλ“œ & μ‹€ν–‰ ν…ŒμŠ€νŠΈ

λ¨Όμ € μ˜μ‘΄μ„± μ„€μΉ˜:

npm install --omit=dev

λΉŒλ“œ:

npm run build

μ—λŸ¬ 없이 잘 λλ‚˜λ©΄, 일단 λ°”λ‘œ μ‹€ν–‰ν•΄λ³Έλ‹€.

npm start   # λ˜λŠ” package.json의 start 슀크립트

μ„œλ²„μ—μ„œ λ°”λ‘œ 확인:

curl -I http://127.0.0.1:3000

200 OKκ°€ λ–¨μ–΄μ§€λ©΄, λΈŒλΌμš°μ €μ—μ„œ http://EC2_PUBLIC_IP:3000 으둜 μ ‘μ†ν•΄μ„œ ν™•μΈν–ˆλ‹€.

μ—¬κΈ°κΉŒμ§€κ°€ β€œμˆ˜λ™ λ°°ν¬β€μ˜ 첫 λ‹¨κ³„μ˜€λ‹€.


8. pm2둜 ν”„λ‘œμ„ΈμŠ€ 데λͺ¬ν™”

npm startλ₯Ό ν„°λ―Έλ„μ—μ„œ 직접 돌리면 μ„Έμ…˜ μ’…λ£Œ μ‹œ μ„œλ²„λ„ 같이 μ£½λŠ”λ‹€.

κ·Έλž˜μ„œ pm2둜 Next.jsλ₯Ό 데λͺ¬μœΌλ‘œ 띄웠닀.

cd ~/on-fit/on-fit-next

pm2 start npm --name "onfit" -- start
pm2 status

μ΄λ ‡κ²Œ 뜨면 성곡:

β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ id  β”‚ name  β”‚ mode   β”‚ ... β”‚ status β”‚ cpu    β”‚ memory β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 0   β”‚ onfit β”‚ fork   β”‚ ... β”‚ online β”‚ 0.1%   β”‚ 80MB   β”‚
β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”˜

μ„œλ²„ μž¬λΆ€νŒ… 후에도 μžλ™μœΌλ‘œ 뜨게 ν•˜λ €λ©΄:

pm2 save
pm2 startup
# 좜λ ₯λ˜λŠ” λͺ…λ Ή ν•œ 쀄을 sudo둜 μ‹€ν–‰

이제 이걸 정식 도메인(onfit.today) + HTTPS둜 λ¬Άκ³ ,

κ·Έ μœ„μ— GitHub Actions둜 CI/CD μžλ™ν™”λ₯Ό μ˜¬λ €μ•Ό ν•œλ‹€.

profile
코린이

0개의 λŒ“κΈ€