์ด๋ณด์๋ฅผ ์ํ GitHub Actions๋ก Node.js ํ๋ก์ ํธ ์๋ ํ ์คํธยท๋ฐฐํฌ (๊ธฐ๋ณธ ์ํฌํ๋ก์ฐ YAML ์์ฑ๋ถํฐ)
์ด๋ณด์๋ฅผ ์ํ GitHub Actions๋ก Node.js ํ๋ก์ ํธ ์๋ ํ ์คํธยท๋ฐฐํฌ (๊ธฐ๋ณธ ์ํฌํ๋ก์ฐ YAML ์์ฑ๋ถํฐ) โ์ปค๋ฐํ๋๋ฐ ํ ์ค...
์ด๋ณด์๋ฅผ ์ํ GitHub Actions๋ก Node.js ํ๋ก์ ํธ ์๋ ํ ์คํธยท๋ฐฐํฌ (๊ธฐ๋ณธ ์ํฌํ๋ก์ฐ YAML ์์ฑ๋ถํฐ)
โ์ปค๋ฐํ๋๋ฐ ํ ์คํธ๋ ๋๊ฐ ๋๋ฆฌ์ง?โ, โ๋ฐฐํฌ๋ ๋ ์๋์ผ๋ก ํด์ผ ํด?โ Node.js ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด ๊ฒฐ๊ตญ ๋ฐ๋ณต ์์ ์ด ๋ฐ๋ชฉ์ ์ก์ต๋๋ค. GitHub Actions๋ฅผ ์ฐ๋ฉด ํธ์/PR๋ง์ผ๋ก ํ ์คํธ๊ฐ ์๋ ์คํ๋๊ณ , ์กฐ๊ฑด์ด ๋ง์ผ๋ฉด ๋ฐฐํฌ๊น์ง ํ ๋ฒ์ ์ด์ด์ง๊ฒ ๋ง๋ค ์ ์์ด์. ์ค๋์ ์ด๋ณด์๋ ๊ทธ๋๋ก ๋ฐ๋ผ ํ ์ ์๋ ๊ธฐ๋ณธ ์ํฌํ๋ก์ฐ YAML์ ์ค์ฌ์ผ๋ก, ์ค๋ฌด์์ ๋ฐ๋ก ์ฐ๋ ํํ๋ก ์ ๋ฆฌํฉ๋๋ค.
1) ์ค๋น๋ฌผ: ํ๋ก์ ํธ์ ๊ผญ ํ์ํ ์ต์ ์กฐ๊ฑด
์ฒดํฌ๋ฆฌ์คํธ
- package.json์ ํ ์คํธ ์คํฌ๋ฆฝํธ๊ฐ ์์ด์ผ ํฉ๋๋ค.
- ์: "test": "jest" ๋๋ "test": "vitest run" ๋ฑ
- Node ๋ฒ์ ์ LTS ๊ธฐ์ค์ผ๋ก ์์ํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค(์: 20).
- ๋ฐฐํฌ๋ ์์๋ก โ์๋ฒ์ SSH๋ก ์ ์ํด ๋ฐฐํฌ ์คํฌ๋ฆฝํธ ์คํโ ํ๋ฆ์ ์ฌ์ฉํฉ๋๋ค. (๊ฐ์ฅ ๋ฒ์ฉ์ )
์์ package.json (ํต์ฌ๋ง)
{
"scripts": {
"test": "npm run lint && npm run unit",
"lint": "eslint .",
"unit": "vitest run",
"build": "tsc -p ."
}
}
2) ์๋ ํ ์คํธ ์ํฌํ๋ก์ฐ ๋ง๋ค๊ธฐ (๊ฐ์ฅ ๋จผ์ ์ถ์ฒ)
๋ ํฌ์งํ ๋ฆฌ ๋ฃจํธ์ ์๋ ๊ฒฝ๋ก๋ก ํ์ผ์ ๋ง๋ญ๋๋ค.
- .github/workflows/ci.yml
๊ธฐ๋ณธ CI ์ํฌํ๋ก์ฐ (ํ ์คํธ ์๋ ์คํ)
name: CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
ํฌ์ธํธ ์ ๋ฆฌ
- on: pull_request๋ฅผ ๋ฃ์ผ๋ฉด PR ์ฌ๋ฆด ๋ ์๋ ๊ฒ์ฆ์ด ๋ฉ๋๋ค.
- npm install ๋์ npm ci๋ฅผ ์ฐ๋ฉด ๋ฝํ์ผ ๊ธฐ์ค์ผ๋ก ๋ ์์ ์ ์ผ๋ก ์ค์น๋ฉ๋๋ค.
- cache: "npm" ๋๋ถ์ ์ฌ์คํ์ด ๋นจ๋ผ์ง ์ ์์ต๋๋ค.
3) โํ ์คํธ ํต๊ณผํ๋ฉด ๋ฐฐํฌโ๋ก ์ด์ด ๋ถ์ด๊ธฐ
์ฌ๊ธฐ์๋ถํฐ๊ฐ ์ง์ง ์๋ํ์ ๋ง์ ๋๋ค. ๊ตฌ์กฐ๋ ๊ฐ๋จํฉ๋๋ค.
- CI(ํ ์คํธ)๊ฐ ์ฑ๊ณตํ๋ฉด
- CD(๋ฐฐํฌ)๊ฐ ์คํ๋๋๋ก ์ฐ๊ฒฐ ๊ฐ์ ํ์ผ์ ๋ฐฐํฌ Job์ ์ถ๊ฐํด๋ ๋๊ณ , ๋ถ๋ฆฌํด๋ ๋ฉ๋๋ค. ์ฒ์์ ํ ํ์ผ์ด ์ดํดํ๊ธฐ ์ฌ์์.
ํ ์คํธ ์ฑ๊ณต ํ ๋ฐฐํฌ(Job ์ฐ๊ฒฐ)
name: CI-CD
on:
push:
branches: [ "main" ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "npm"
- run: npm ci
- run: npm test
- run: npm run build
deploy:
needs: test
runs-on: ubuntu-latest
if: ${{ success() }}
steps:
- name: Deploy via SSH
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER
4) Secrets ์ค์ : ๋น๋ฐ๋ฒํธ๋ฅผ ์ฝ๋์ ์ฐ์ง ์๋ ๋ฐฉ๋ฒ
์ ๋ฐฐํฌ ์์๋ secrets๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ ํฌ์งํ ๋ฆฌ ์ค์ ์์ ์๋ ๊ฐ์ ๋ฑ๋กํด์ผ ํด์.
- SSH_HOST : ์๋ฒ ์ฃผ์
- SSH_USER : ์ ์ ์ฌ์ฉ์
- SSH_KEY : ๊ฐ์ธํค(๋ณดํต PEM ํ์) ์ฌ๊ธฐ์ ์ค์ํ ๊ฑด ๊ฐ์ธํค๋ ์ ๋ ์ ์ฅ์์ ์ฌ๋ฆฌ์ง ์๋ ๊ฒ์ ๋๋ค. ๋ํ ์๋ฒ์๋ ํด๋น ํค์ ๊ณต๊ฐํค๊ฐ ๋ฑ๋ก๋์ด ์์ด์ผ SSH ์ ์์ด ๋ฉ๋๋ค.
5) ์ด๋ณด์๊ฐ ์์ฃผ ๋งํ๋ ์ง์ 3๊ฐ์ง
1) โํ ์คํธ๊ฐ ์์ด์ ์คํจํด์โ
npm test๊ฐ ์ค์ ๋ก ์คํํ ํ ์คํธ๊ฐ ์์ผ๋ฉด ์คํจํ ์ ์์ต๋๋ค. ๋น์ฅ ํ ์คํธ๋ฅผ ๋ชป ์ฐ๋๋ผ๋, ์์๋ก๋ผ๋ test ์คํฌ๋ฆฝํธ๋ฅผ ์ ๋ฆฌํด ๋๋ ๊ฒ ์ข์์.
2) โmain ๋ง๊ณ develop์์๋ง ๋๋ฆฌ๊ณ ์ถ์ด์โ
๋ธ๋์น๋ง ๋ฐ๊พธ๋ฉด ๋ฉ๋๋ค.
on:
push:
branches: ["develop"]
3) โ๋ฐฐํฌ๊ฐ ์ํํด ๋ณด์ฌ์โ
์ฒ์์ ๋ฐฐํฌ Job์ ์ฃผ์ ์ฒ๋ฆฌํ๊ณ , CI๋ง ์์ ํํ ๋ค ๋ฐฐํฌ๋ฅผ ๋ถ์ด์ธ์. ๋๋ workflow_dispatch(์๋ ์คํ)๋ก ๋ฐฐํฌ๋ฅผ ์์ํ๋ ๊ฒ๋ ์์ ํฉ๋๋ค.
6) ์ค๋์ ์ ๋ฆฌ: ์ด ์์๋ก ํ๋ฉด ์คํจ ํ๋ฅ ์ด ๋ฎ์ต๋๋ค
- ci.yml๋ก ํ ์คํธ ์๋ํ๋ถํฐ ๋ถ์ธ๋ค
- npm ci + ์บ์๋ก ์คํ์ ์์ ํํ๋ค
- needs: test๋ก ํ ์คํธ ์ฑ๊ณต โ ๋ฐฐํฌ ํ๋ฆ์ ๋ง๋ ๋ค
- ๋ฏผ๊ฐ ์ ๋ณด๋ secrets๋ก ๊ด๋ฆฌํ๋ค ์ด ์ ๋๋ง ๊ตฌ์ถํด๋, ์ปค๋ฐํ๋ ์๊ฐ๋ถํฐ ํ๋ก์ ํธ๊ฐ ํจ์ฌ โํ์ฒ๋ผโ ๊ตด๋ฌ๊ฐ๊ธฐ ์์ํฉ๋๋ค. ๋ค์ ๋จ๊ณ๋ก๋ ํ ์คํธ ๋งคํธ๋ฆญ์ค(์ฌ๋ฌ Node ๋ฒ์ ), ํ๊ฒฝ๋ณ ๋ฐฐํฌ(dev/staging/prod), ์ํฐํฉํธ ์ ๋ก๋ ๊ฐ์ ํ์ฅ๋ ์์ฐ์ค๋ฝ๊ฒ ์ด์ด๊ฐ ์ ์์ด์.
โฌ๏ธ ์ด ๊ธ์ด ๋์์ด ๋์ จ๋ค๋ฉด, ์๋ ๊ด๊ณ ๋ฅผ ํ ๋ฒ๋ง ํด๋ฆญํด์ฃผ์ธ์! ์ ์๊ฒ ํฐ ํ์ด ๋ฉ๋๋ค ๐โโ๏ธ โฌ๏ธ