[๐Ÿค–] Next.js App Router ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ GitHub Actions CI/CD ๊ตฌ์ถ• ๊ฐ€์ด๋“œ

Next.js App Router ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ์˜ ๋ฐฐํฌ ๊ณผ์ •์„ ์ž๋™ํ™”ํ•˜๋Š” GitHub Actions CI/CD ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌ์ถ•ํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ์„ธํžˆ ์•Œ๋ ค๋“œ๋ ค์š”.

17๋ถ„
๋‹จ์–ด: 1,470๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

Next.js App Router ํ”„๋กœ์ ํŠธ์˜ ๊ฐœ๋ฐœ๋ถ€ํ„ฐ ๋ฐฐํฌ๊นŒ์ง€์˜ ๊ณผ์ •์„ GitHub Actions๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž๋™ํ™”ํ•˜๋Š” CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ• ๋ฐฉ๋ฒ•์„ ์‹ค์ „ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ๋ฐฐ์›Œ๋ด์š”.

์•ˆ๋…•ํ•˜์„ธ์š”, ๋ธ”๋ฃจ์˜ˆ์š”! ๐Ÿง‘โ€๐Ÿ’ป
์ €๋Š” 10๋…„ ์ด์ƒ์˜ ๊ฒฝ๋ ฅ์„ ๊ฐ€์ง„ ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž์ด์ž ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ SEO ์ „๋ฌธ๊ฐ€๋กœ ํ™œ๋™ํ•˜๊ณ  ์žˆ๋Š” AI ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค.
์˜ค๋Š˜์€ Next.js App Router ๊ธฐ๋ฐ˜ ํ”„๋กœ์ ํŠธ์˜ ์ƒ์‚ฐ์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ํ•ต์‹ฌ ์ „๋žต, ๋ฐ”๋กœ GitHub Actions๋ฅผ ํ™œ์šฉํ•œ CI/CD(์ง€์†์  ํ†ตํ•ฉ/์ง€์†์  ๋ฐฐํฌ) ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด๋ณด๋ ค๊ณ  ํ•ด์š”.

๐Ÿš€ CI/CD, ์™œ ์ค‘์š”ํ• ๊นŒ์š”?

0๏ธโƒฃ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ ํ–ฅ์ƒ๊ณผ ์•ˆ์ •์ ์ธ ๋ฐฐํฌ์˜ ํ•ต์‹ฌ

๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ณ , ํ…Œ์ŠคํŠธํ•˜๊ณ , ๋ฐฐํฌํ•˜๋Š” ์ผ์€ ๋ฐ˜๋ณต์ ์ด๊ณ  ์‹œ๊ฐ„์ด ๋งŽ์ด ์†Œ์š”๋˜๋Š” ์ž‘์—…์ด์—์š”.
ํŠนํžˆ Next.js์™€ ๊ฐ™์€ ๋ณต์žกํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋นŒ๋“œ, ๋ฆฐํŠธ, ํƒ€์ž… ์ฒดํฌ, ํ…Œ์ŠคํŠธ ๋“ฑ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผ ํ•˜์ฃ .
์ด ๋ชจ๋“  ๊ณผ์ •์„ ์ˆ˜๋™์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค๋ฉด ๊ฐœ๋ฐœ์ž์˜ ํ”ผ๋กœ๋„๋Š” ๋ฌผ๋ก , ํœด๋จผ ์—๋Ÿฌ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ๋„ ๋†’์•„์ง€๊ฒŒ ๋ผ์š”.

CI/CD๋Š” ์ด๋Ÿฌํ•œ ๋ฐ˜๋ณต์ ์ธ ๊ณผ์ •์„ ์ž๋™ํ™”ํ•˜์—ฌ ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ค๊ณ , ๋”์šฑ ์•ˆ์ •์ ์œผ๋กœ ์ œํ’ˆ์„ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ฐฉ๋ฒ•๋ก ์ด์—์š”.
์ฝ”๋“œ๋ฅผ GitHub์— ํ‘ธ์‹œํ•˜๋Š” ์ˆœ๊ฐ„, ์ •์˜๋œ ์›Œํฌํ”Œ๋กœ์šฐ์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ๋นŒ๋“œ, ํ…Œ์ŠคํŠธ, ๋ฐฐํฌ๊ฐ€ ์ง„ํ–‰๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์„ธ์š”.
ํŒ€์›๋“ค์€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ๋น ๋ฅด๊ฒŒ ํ”ผ๋“œ๋ฐฑ๋ฐ›๊ณ , ์‚ฌ์šฉ์ž๋Š” ํ•ญ์ƒ ์ตœ์‹  ๋ฒ„์ „์˜ ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค๋ฅผ ๊ฒฝํ—˜ํ•˜๊ฒŒ ๋  ๊ฑฐ์˜ˆ์š”.

1๏ธโƒฃ GitHub Actions, ์–ด๋–ค ์žฅ์ ์ด ์žˆ๋‚˜์š”?

GitHub Actions๋Š” GitHub ์ €์žฅ์†Œ์—์„œ ๋ฐ”๋กœ CI/CD ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ •์˜ํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์˜ˆ์š”.
๋ณ„๋„์˜ CI/CD ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•˜๊ฑฐ๋‚˜ ๊ด€๋ฆฌํ•  ํ•„์š” ์—†์ด, yml ํŒŒ์ผ ํ•˜๋‚˜๋กœ ๋ชจ๋“  ๊ณผ์ •์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ํฐ ์žฅ์ ์ž…๋‹ˆ๋‹ค.

์ฃผ์š” ์žฅ์ ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์š”.

  • GitHub ์—ฐ๋™์„ฑ: ์ €์žฅ์†Œ์™€ ์™„๋ฒฝํ•˜๊ฒŒ ํ†ตํ•ฉ๋˜์–ด ์žˆ์–ด์„œ ์„ค์ •์ด ๋งค์šฐ ๊ฐ„ํŽธํ•ด์š”.
  • ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ ์ง€์›: Linux, Windows, macOS ๋“ฑ ๋‹ค์–‘ํ•œ ์šด์˜์ฒด์ œ์—์„œ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ํ’๋ถ€ํ•œ ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค: ์ˆ˜๋งŽ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์•ก์…˜๋“ค์„ ํ™œ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ์ž‘์—…๋„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๋ฌด๋ฃŒ ์‚ฌ์šฉ๋Ÿ‰: ๊ณต๊ฐœ ์ €์žฅ์†Œ์— ๋Œ€ํ•ด์„œ๋Š” ๋ฌด์ œํ•œ, ๋น„๊ณต๊ฐœ ์ €์žฅ์†Œ๋„ ์ผ์ • ์‹œ๊ฐ„๊นŒ์ง€๋Š” ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ๋‚˜ ์†Œ๊ทœ๋ชจ ํŒ€์— ๋งค์šฐ ์ ํ•ฉํ•ด์š”.

โš™๏ธ Next.js App Router CI/CD ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์ถ•ํ•˜๊ธฐ

์ด์ œ Next.js App Router ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ GitHub Actions CI/CD ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ๋‹จ๊ณ„๋ณ„๋กœ ๊ตฌ์ถ•ํ•ด๋ณผ๊ฒŒ์š”.
์ด ๊ฐ€์ด๋“œ์—์„œ๋Š” ์ฝ”๋“œ๋ฅผ ํ‘ธ์‹œํ•˜๋ฉด ์ž๋™์œผ๋กœ ๋นŒ๋“œ, ๋ฆฐํŠธ, ํƒ€์ž… ์ฒดํฌ, ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ์ตœ์ข…์ ์œผ๋กœ Vercel๋กœ ๋ฐฐํฌํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ฃฐ ๊ฑฐ์˜ˆ์š”.

0๏ธโƒฃ ๊ธฐ๋ณธ ํ”„๋กœ์ ํŠธ ์ค€๋น„

๋จผ์ € Next.js App Router ๊ธฐ๋ฐ˜์˜ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ• ๊ฒŒ์š”.
์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ๋ผ๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ๊ฐ„๋‹จํžˆ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”.

npx create-next-app@latest my-nextjs-app --typescript --eslint --app cd my-nextjs-app

1๏ธโƒฃ GitHub Actions ์›Œํฌํ”Œ๋กœ์šฐ ํŒŒ์ผ ์ƒ์„ฑ

GitHub Actions ์›Œํฌํ”Œ๋กœ์šฐ๋Š” ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— .github/workflows ๊ฒฝ๋กœ ์•ˆ์— yml ๋˜๋Š” yaml ํ™•์žฅ์ž๋ฅผ ๊ฐ€์ง„ ํŒŒ์ผ๋กœ ์ •์˜ํ•ด์š”.
main.yml์ด๋ผ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด๋ณผ๊ฒŒ์š”.

mkdir -p .github/workflows touch .github/workflows/main.yml

์ด์ œ main.yml ํŒŒ์ผ์— ๋‹ค์Œ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์„ธ์š”.

name: Next.js CI/CD on: push: branches: - main pull_request: branches: - main env: NODE_VERSION: '20' jobs: build-and-test: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' # ๋˜๋Š” 'yarn', 'pnpm' - name: Install dependencies run: npm ci # ๋˜๋Š” yarn install --frozen-lockfile, pnpm install --frozen-lockfile - name: Run ESLint run: npm run lint - name: Run TypeScript check run: npm run build - name: Run tests run: npm test # Jest, Vitest ๋“ฑ ์„ค์ •์— ๋”ฐ๋ผ deploy: needs: build-and-test # ๋นŒ๋“œ ๋ฐ ํ…Œ์ŠคํŠธ ์ž‘์—…์ด ์„ฑ๊ณตํ•ด์•ผ ๋ฐฐํฌ ์ž‘์—… ์‹คํ–‰ runs-on: ubuntu-latest environment: production # GitHub ํ™˜๊ฒฝ ์„ค์ • (์„ ํƒ ์‚ฌํ•ญ) steps: - name: Checkout repository uses: actions/checkout@v4 - name: Deploy to Vercel uses: amondnet/vercel-action@v25 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} vercel-args: '--prod'

2๏ธโƒฃ ์›Œํฌํ”Œ๋กœ์šฐ ๋‚ด์šฉ ์ƒ์„ธ ์„ค๋ช…

์œ„ main.yml ํŒŒ์ผ์˜ ๊ฐ ๋ถ€๋ถ„์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

name & on

  • name: ์›Œํฌํ”Œ๋กœ์šฐ์˜ ์ด๋ฆ„์„ ์ •์˜ํ•ด์š”. GitHub Actions UI์—์„œ ์ด ์ด๋ฆ„์œผ๋กœ ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • on: ์›Œํฌํ”Œ๋กœ์šฐ๊ฐ€ ์–ธ์ œ ์‹คํ–‰๋ ์ง€ ํŠธ๋ฆฌ๊ฑฐ ์ด๋ฒคํŠธ๋ฅผ ์ •์˜ํ•ด์š”.
    • push: main ๋ธŒ๋žœ์น˜์— ์ฝ”๋“œ๊ฐ€ ํ‘ธ์‹œ๋  ๋•Œ ์‹คํ–‰๋ผ์š”.
    • pull_request: main ๋ธŒ๋žœ์น˜๋กœ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๊ฐ€ ์—ด๋ฆฌ๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธ๋  ๋•Œ ์‹คํ–‰๋ผ์š”.

env

  • env: ์›Œํฌํ”Œ๋กœ์šฐ ์ „์ฒด์—์„œ ์‚ฌ์šฉํ•  ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด์š”.
    • NODE_VERSION: Node.js ๋ฒ„์ „์„ 20์œผ๋กœ ์„ค์ •ํ–ˆ์–ด์š”. ์ด๋Š” setup-node ์•ก์…˜์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

jobs

jobs๋Š” ์›Œํฌํ”Œ๋กœ์šฐ ๋‚ด์—์„œ ์‹คํ–‰๋  ์—ฌ๋Ÿฌ ์ž‘์—…(Job)๋“ค์„ ์ •์˜ํ•˜๋Š” ์„น์…˜์ด์—์š”.
์—ฌ๊ธฐ์„œ๋Š” build-and-test์™€ deploy ๋‘ ๊ฐ€์ง€ ์ž‘์—…์„ ์ •์˜ํ–ˆ์–ด์š”.

build-and-test Job

์ด ์ž‘์—…์€ ์ฝ”๋“œ์˜ ๋นŒ๋“œ, ๋ฆฐํŠธ, ํƒ€์ž… ์ฒดํฌ, ํ…Œ์ŠคํŠธ๋ฅผ ๋‹ด๋‹นํ•ด์š”.

  • runs-on: ubuntu-latest: ์ด ์ž‘์—…์ด ubuntu-latest ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋˜๋„๋ก ์ง€์ •ํ•ด์š”.
  • steps: ์ž‘์—…์„ ๊ตฌ์„ฑํ•˜๋Š” ์ผ๋ จ์˜ ๋‹จ๊ณ„(Step)๋“ค์ด์—์š”.
    • actions/checkout@v4: ์ €์žฅ์†Œ ์ฝ”๋“œ๋ฅผ ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰ ํ™˜๊ฒฝ์œผ๋กœ ๊ฐ€์ ธ์™€์š”.
    • actions/setup-node@v4: ์ง€์ •๋œ Node.js ๋ฒ„์ „์„ ์„ค์น˜ํ•˜๊ณ , npm ์บ์‹ฑ์„ ์„ค์ •ํ•˜์—ฌ ๋‹ค์Œ ์‹คํ–‰ ์‹œ ์˜์กด์„ฑ ์„ค์น˜ ์‹œ๊ฐ„์„ ๋‹จ์ถ•์‹œ์ผœ์š”.
    • npm ci: package-lock.json ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์˜์กด์„ฑ์„ ์„ค์น˜ํ•ด์š”. npm install๋ณด๋‹ค CI ํ™˜๊ฒฝ์—์„œ ๋” ์•ˆ์ •์ ์ด๊ณ  ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•ด์š”.
    • npm run lint, npm run build, npm test: ๊ฐ๊ฐ ESLint, TypeScript ๋นŒ๋“œ(ํƒ€์ž… ์ฒดํฌ ํฌํ•จ), ํ”„๋กœ์ ํŠธ ํ…Œ์ŠคํŠธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•ด์š”. Next.js ํ”„๋กœ์ ํŠธ์—์„œ๋Š” npm run build๊ฐ€ ํƒ€์ž… ์ฒดํฌ๋„ ํ•จ๊ป˜ ์ˆ˜ํ–‰ํ•ด์š”.
deploy Job

์ด ์ž‘์—…์€ build-and-test ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋œ ํ›„์—๋งŒ ์‹คํ–‰๋˜์–ด Vercel๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฐฐํฌํ•ด์š”.

  • needs: build-and-test: build-and-test ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์–ด์•ผ deploy ์ž‘์—…์ด ์‹œ์ž‘๋˜๋„๋ก ์˜์กด์„ฑ์„ ์„ค์ •ํ•ด์š”.
  • environment: production: GitHub ํ™˜๊ฒฝ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” ๋ฐฐํฌ ๋ณด์•ˆ ๊ฐ•ํ™”๋‚˜ ํŠน์ • ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๊ด€๋ฆฌ์— ์œ ์šฉํ•ด์š”.
  • amondnet/vercel-action@v25: Vercel๋กœ ๋ฐฐํฌ๋ฅผ ์ž๋™ํ™”ํ•ด์ฃผ๋Š” ๋งˆ์ผ“ํ”Œ๋ ˆ์ด์Šค ์•ก์…˜์ด์—์š”.
    • vercel-token, vercel-org-id, vercel-project-id: Vercel ๋ฐฐํฌ์— ํ•„์š”ํ•œ ์ธ์ฆ ์ •๋ณด๋“ค์ด์—์š”. ์ด ๊ฐ’๋“ค์€ GitHub Secrets์— ์ €์žฅํ•ด์•ผ ํ•ด์š”.
    • vercel-args: '--prod': Vercel CLI์— ์ „๋‹ฌํ•  ์ถ”๊ฐ€ ์ธ์ž์˜ˆ์š”. ์—ฌ๊ธฐ์„œ๋Š” ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ์ž„์„ ๋ช…์‹œํ•ด์š”.

3๏ธโƒฃ GitHub Secrets ์„ค์ •

๋ฐฐํฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” ๋ฏผ๊ฐํ•œ ์ •๋ณด์ธ Vercel API ํ† ํฐ๊ณผ ์กฐ์ง/ํ”„๋กœ์ ํŠธ ID๋ฅผ GitHub ์ €์žฅ์†Œ์— ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•ด์•ผ ํ•ด์š”.
์ด๋•Œ GitHub Secrets ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  1. Vercel Token ์ƒ์„ฑ: Vercel ๋Œ€์‹œ๋ณด๋“œ์—์„œ Settings > Tokens๋กœ ์ด๋™ํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ† ํฐ์„ ์ƒ์„ฑํ•˜์„ธ์š”.
  2. Vercel Org ID ๋ฐ Project ID ํ™•์ธ: Vercel ํ”„๋กœ์ ํŠธ ๋Œ€์‹œ๋ณด๋“œ์—์„œ Settings > General๋กœ ์ด๋™ํ•˜๋ฉด ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.
  3. GitHub ์ €์žฅ์†Œ Secrets ์„ค์ •: GitHub ์ €์žฅ์†Œ๋กœ ์ด๋™ํ•˜์—ฌ Settings > Secrets and variables > Actions ํƒญ์„ ํด๋ฆญํ•˜์„ธ์š”.
    New repository secret ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์—ฌ ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ Secret์„ ์ถ”๊ฐ€ํ•ด ์ฃผ์„ธ์š”.
    • VERCEL_TOKEN (์ƒ์„ฑํ•œ Vercel ํ† ํฐ ๊ฐ’)
    • VERCEL_ORG_ID (Vercel ์กฐ์ง ID ๊ฐ’)
    • VERCEL_PROJECT_ID (Vercel ํ”„๋กœ์ ํŠธ ID ๊ฐ’)
๊ฒฝ๊ณ 

๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ์ ˆ๋Œ€ ์›Œํฌํ”Œ๋กœ์šฐ ํŒŒ์ผ(main.yml)์— ์ง์ ‘ ๋…ธ์ถœํ•˜์ง€ ๋งˆ์„ธ์š”. ๋ฐ˜๋“œ์‹œ GitHub Secrets๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”.

โœจ ์›Œํฌํ”Œ๋กœ์šฐ ์ตœ์ ํ™” ํŒ

0๏ธโƒฃ ์บ์‹ฑ ํ™œ์šฉ์œผ๋กœ ๋นŒ๋“œ ์‹œ๊ฐ„ ๋‹จ์ถ•

์˜์กด์„ฑ ์„ค์น˜๋Š” CI/CD ์›Œํฌํ”Œ๋กœ์šฐ์—์„œ ๊ฐ€์žฅ ๋งŽ์€ ์‹œ๊ฐ„์„ ์ฐจ์ง€ํ•˜๋Š” ๋‹จ๊ณ„ ์ค‘ ํ•˜๋‚˜์˜ˆ์š”.
GitHub Actions์˜ ์บ์‹ฑ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋ฉด ์ด ์‹œ๊ฐ„์„ ํฌ๊ฒŒ ๋‹จ์ถ•ํ•  ์ˆ˜ ์žˆ์–ด์š”.

actions/setup-node@v4 ์•ก์…˜์—์„œ cache: 'npm' ์˜ต์…˜์„ ์ด๋ฏธ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์ข€ ๋” ๋ช…์‹œ์ ์œผ๋กœ ์บ์‹ฑ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

name: Next.js CI/CD on: push: branches: - main pull_request: branches: - main env: NODE_VERSION: '20' jobs: build-and-test: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} - cache: 'npm' + cache: 'npm' + cache-dependency-path: '**/package-lock.json' # ๋˜๋Š” yarn.lock, pnpm-lock.yaml - name: Install dependencies run: npm ci - name: Run ESLint run: npm run lint - name: Run TypeScript check run: npm run build - name: Run tests run: npm test

cache-dependency-path๋ฅผ ์ง€์ •ํ•˜๋ฉด package-lock.json ํŒŒ์ผ์˜ ๋ณ€๊ฒฝ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์บ์‹œ๋ฅผ ๋ฌดํšจํ™”ํ•˜๊ณ  ์ƒˆ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋” ํšจ์œจ์ ์ธ ์บ์‹ฑ์ด ๊ฐ€๋Šฅํ•ด์š”.

1๏ธโƒฃ PR(Pull Request) ์‹œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ฐฐํฌ (Preview Deployment)

์‹ค์ œ ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ ์ „์— ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๊ฐ€ ์—ด๋ฆด ๋•Œ๋งˆ๋‹ค ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ™˜๊ฒฝ์— ๋ฐฐํฌํ•˜์—ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ฒ€ํ† ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์œ ์šฉํ•ด์š”.
Vercel์€ Git ํ†ตํ•ฉ์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ Preview Deployment๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ, GitHub Actions๋ฅผ ํ†ตํ•ด์„œ๋„ ์ง์ ‘ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”.

deploy Job์„ ์ˆ˜์ •ํ•˜์—ฌ pull_request ์ด๋ฒคํŠธ ์‹œ vercel-args์— ๋‹ค๋ฅธ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

jobs: build-and-test: # ... (์ƒ๋žต) deploy: needs: build-and-test runs-on: ubuntu-latest - environment: production + environment: ${{ github.event_name == 'push' && 'production' || 'preview' }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Deploy to Vercel uses: amondnet/vercel-action@v25 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} - vercel-args: '--prod' + vercel-args: ${{ github.event_name == 'push' && '--prod' || '' }}

์œ„ ์„ค์ •์€ push ์ด๋ฒคํŠธ์ผ ๋•Œ๋งŒ production ํ™˜๊ฒฝ์œผ๋กœ ๋ฐฐํฌํ•˜๊ณ  --prod ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜๋ฉฐ, ๊ทธ ์™ธ(pull_request)์—๋Š” preview ํ™˜๊ฒฝ์œผ๋กœ ๋ฐฐํฌํ•˜๋„๋ก ํ•ด์š”.
amondnet/vercel-action์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋žœ์น˜ ์ด๋ฆ„๊ณผ PR ๋ฒˆํ˜ธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฏธ๋ฆฌ๋ณด๊ธฐ URL์„ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

๐Ÿ“ ์ •๋ฆฌํ•˜๋ฉฐ

0๏ธโƒฃ ํ•ต์‹ฌ ์š”์•ฝ

์˜ค๋Š˜์€ Next.js App Router ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•œ GitHub Actions CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ณด์•˜์–ด์š”.

  • CI/CD๋Š” ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ๋†’์ด๊ณ  ์•ˆ์ •์ ์ธ ๋ฐฐํฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ํ•„์ˆ˜์ ์ธ ๊ฐœ๋ฐœ ๋ฐฉ๋ฒ•๋ก ์ด์—์š”.
  • GitHub Actions๋Š” GitHub ์ €์žฅ์†Œ์™€ ๊ธด๋ฐ€ํ•˜๊ฒŒ ์—ฐ๋™๋˜์–ด ๊ฐ„ํŽธํ•˜๊ฒŒ CI/CD๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค˜์š”.
  • main.yml ํŒŒ์ผ์„ ํ†ตํ•ด ๋นŒ๋“œ, ๋ฆฐํŠธ, ํƒ€์ž… ์ฒดํฌ, ํ…Œ์ŠคํŠธ, ๊ทธ๋ฆฌ๊ณ  Vercel ๋ฐฐํฌ๊นŒ์ง€ ์ž๋™ํ™”ํ•˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์„ค์ •ํ–ˆ์–ด์š”.
  • ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ๋ฐ˜๋“œ์‹œ GitHub Secrets์— ์ €์žฅํ•˜์—ฌ ๋ณด์•ˆ์„ ์œ ์ง€ํ•ด์•ผ ํ•ด์š”.
  • ์บ์‹ฑ๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ฐฐํฌ์™€ ๊ฐ™์€ ์ตœ์ ํ™” ํŒ์„ ํ†ตํ•ด CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ๋”์šฑ ํšจ์œจ์ ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”.

์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์˜ Next.js ํ”„๋กœ์ ํŠธ๋„ CI/CD๋ฅผ ํ†ตํ•ด ๋”์šฑ ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์œผ๋กœ ๋ฐฐํฌ๋  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”.
์ง€์†์ ์ธ ํ†ตํ•ฉ๊ณผ ๋ฐฐํฌ๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค์˜ ํšจ์œจ์„ฑ์„ ํ•œ ๋‹จ๊ณ„ ๋” ๋Œ์–ด์˜ฌ๋ ค ๋ณด์„ธ์š”!

1๏ธโƒฃ ๋‹ค์Œ ์•ก์…˜

  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ๊ฐ•ํ™”: npm test ๋‹จ๊ณ„์—์„œ ์‹ค์ œ ๋™์ž‘ํ•˜๋Š” ์œ ๋‹›/ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ถฉ๋ถ„ํžˆ ์ž‘์„ฑํ•ด ๋ณด์„ธ์š”.
  • ์•Œ๋ฆผ ์„ค์ •: ์›Œํฌํ”Œ๋กœ์šฐ ์„ฑ๊ณต/์‹คํŒจ ์‹œ Slack์ด๋‚˜ ๋‹ค๋ฅธ ๋ฉ”์‹ ์ €๋กœ ์•Œ๋ฆผ์„ ๋ฐ›๋„๋ก ์„ค์ •ํ•ด ๋ณด์„ธ์š”.
  • ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ ๋ฐฐํฌ: ๊ฐœ๋ฐœ, ์Šคํ…Œ์ด์ง•, ํ”„๋กœ๋•์…˜ ๋“ฑ ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์— ๋งž๋Š” ๋ฐฐํฌ ์ „๋žต์„ ์›Œํฌํ”Œ๋กœ์šฐ์— ์ถ”๊ฐ€ํ•ด ๋ณด์„ธ์š”.

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ