Skip to content

๐Ÿค– Github Action๋กœ CI CD ์ž๋™ํ™”ํ•˜๊ธฐ

๊น€๋„ํ˜„ edited this page Dec 6, 2022 · 4 revisions

๐Ÿ˜Ž Knoticle ์„œ๋น„์Šค๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹ฟ๊ธฐ๊นŒ์ง€

์ €ํฌ ๊ฐœ๋ฐœํŒ€์€ ์™„์„ฑ๋„ ์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ ์—ด์‹ฌํžˆ ๊ฐœ๋ฐœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ค ๊ณผ์ •์„ ํ†ตํ•ด์„œ ์ €ํฌ ์„œ๋น„์Šค๊ฐ€ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ๊ณต๊ฐœ๋ ๊นŒ์š”?

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

๐Ÿ™๐Ÿป KnoticleํŒ€์€ CI/CD ์ž๋™ํ™”๊ฐ€ ํ•„์š”ํ•ด์š”

์•ž์„œ ๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ๊ฐœ๋ฐœ๋œ ์ฝ”๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ณผ์ •์„ ํ†ตํ•ด์„œ ์‚ฌ์šฉ์ž๋“ค์—๊ฒŒ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋งค์ฃผ ๋ฐ๋ชจ ์‹œ์—ฐ๊ณผ ์‚ฌ์šฉ์ž ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ ์ผ์ฃผ์ผ์—๋„ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐฐํฌํ•ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๋ฐฐํฌํ•  ๋•Œ๋งˆ๋‹ค ์•ž์„  ๊ณผ์ •์„ ์ˆ˜๋™์œผ๋กœ ๋ฐ˜๋ณตํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด ๋ถ€๋‹ด๋˜๋Š” ์ž‘์—…์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฐฐํฌ ๊ณผ์ •์„ GitHub Action ์ž๋™ํ™”์— ์œ„์ž„ํ•˜๊ณ , ์ €ํฌ๋Š” ๊ฐœ๋ฐœ์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ์–ด๋–ค์‹์œผ๋กœ GitHub Action์„ ํ™œ์šฉํ•ด์„œ CI/CD๋ฅผ ์ž๋™ํ™”ํ–ˆ๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

โš™๏ธ ํ”„๋ก ํŠธ์—”๋“œ์˜ CI

ํ”„๋ก ํŠธ์—”๋“œ์˜ CI๋Š” main ๋ธŒ๋žœ์น˜์™€ develop ๋ธŒ๋žœ์น˜์— PR์„ ์˜ฌ๋ฆฐ ์ƒํƒœ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

name: Frontend CI

on:
  pull_request:
    branches: [main, develop]
    paths:
      - 'frontend/**'

์ดํ›„ Eslint ๊ฒ€์‚ฌ, Lighthouse ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

jobs:
  lint:
    ...
  lighthouse:
    ...

GitHub Action์—์„œ job์€ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋Š” ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. job์— ๋“ค์–ด์žˆ๋Š” ์ž‘์—…๋“ค์€ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋‘ ๊ณผ์ •์„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•ด์„œ CI ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜๊ณ ์žํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๊ณผ์ •์„ ํ•˜๋‚˜์”ฉ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

lint:
  name: Lint CI

  runs-on: ubuntu-latest

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

    - name: Cache Dependencies
      uses: actions/cache@v3
      id: frontend-cache
      with:
        path: frontend/node_modules
        key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.OS }}-build-
          ${{ runner.OS }}-

    - if: ${{ steps.frontend-cache.outputs.cache-hit != 'true' }}
      name: Install Dependencies
      run: npm install
      working-directory: frontend

    - name: Check Lint
      run: npm run lint
      env:
        CI: true
      working-directory: frontend

์šฐ์„  ๋ฆฐํŠธ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ ๋ฆฐํŠธ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” Check Lint ์Šคํ… ๊ฐ™์•„๋ณด์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์•ž์„  ์Šคํ…๋“ค์€ ๋ฌด์—‡์ผ๊นŒ์š”?

Checkout ์Šคํ…์—์„œ๋Š” ์ฝ”๋“œ ์ €์žฅ์†Œ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ CI ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์„œ๋ฒ„๋กœ ๋‚ด๋ ค๋ฐ›์Šต๋‹ˆ๋‹ค.

์ดํ›„ Install Dependencies ์Šคํ…์—์„œ ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๋ชจ๋“ˆ๋“ค์€ ์„ค์น˜ํ•˜๋Š”๋ฐ ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ธฐ๋„ ํ•˜๊ณ , ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์บ์‹ฑํ•ด๋†“๊ธฐ ์ ์ ˆํ•ด๋ณด์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์„ค์น˜ ๊ณผ์ • ๋ฐ”๋กœ ์ง์ „ ์Šคํ…์ธ Cache Dependencies์—์„œ ๋ชจ๋“ˆ ์บ์‹ฑ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•˜๋ฉด ๋ณ€๊ฒฝ๋˜๋Š” package-lock.json ํŒŒ์ผ ๋‚ด์šฉ์„ ํ‚ค๋กœ ๋งŒ๋“ค์–ด์„œ ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•˜๊ณ , ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด GitHub์— ์ €์žฅํ•ด๋†“์€ ๋ชจ๋“ˆ ์„ค์น˜ ํŒŒ์ผ์„ ๊บผ๋‚ด๋‹ค ์”๋‹ˆ๋‹ค.

lighthouse:
  name: Lighthouse CI

  runs-on: ubuntu-latest

  steps:

    ... (์ƒ๋žต)

    - name: Run Lighthouse CI
      env:
        LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
      run: |
        npm install -g @lhci/cli
        lhci autorun
      working-directory: frontend

    - name: Format Lighthouse Score
      id: format_lighthouse_score
      uses: actions/github-script@v3
      with:
        github-token: ${{secrets.GITHUB_TOKEN}}
        script: |
          const fs = require('fs');

          const results = JSON.parse(fs.readFileSync('frontend/lighthouse_reports/manifest.json'));

          const summaryTotal = {};

          results.forEach((result) => {
            const { summary } = result;

            const formatResult = (res) => Math.round(res * 100);

            Object.keys(summary).forEach((key) => {
              if (key in summaryTotal) summaryTotal[key] += formatResult(summary[key]);
              else summaryTotal[key] = formatResult(summary[key]);
            });
          });

          Object.keys(summaryTotal).forEach((key) => {
            summaryTotal[key] = Math.round(summaryTotal[key] / results.length);
          });

          const score = (res) => (res >= 90 ? '๐ŸŸข' : res >= 50 ? '๐ŸŸ ' : '๐Ÿ”ด');

          const comment = [
            `โšก๏ธ Lighthouse report!`,
            `| Category | Score |`,
            `| --- | --- |`,
            `| ${score(summaryTotal.performance)} Performance | ${summaryTotal.performance} |`,
            `| ${score(summaryTotal.accessibility)} Accessibility | ${summaryTotal.accessibility} |`,
            `| ${score(summaryTotal['best-practices'])} Best Practices | ${summaryTotal['best-practices']} |`,
            `| ${score(summaryTotal.seo)} SEO | ${summaryTotal.seo} |`,
            `| ${score(summaryTotal.pwa)} PWA | ${summaryTotal.pwa} |`,
          ].join('\n');

          core.setOutput('comment', comment)

    - name: Comment Lighthouse Report
      uses: unsplash/comment-on-pr@v1.3.0
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        msg: ${{ steps.format_lighthouse_score.outputs.comment}}

๋‹ค์Œ์€ Lighthouse ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

Run Lighthouse CI ์Šคํ…์—์„œ Lighthouse ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

// .lighthouserc.js

module.exports = {
  ci: {
    collect: {
      startServerCommand: 'npm run start',
      url: ['http://localhost:3000'],
      numberOfRuns: 3,
    },
    upload: {
      target: 'filesystem',
      outputDir: './lighthouse_reports',
      reportFilenamePattern: '%%PATHNAME%%-%%DATETIME%%-report.%%EXTENSION%%',
    },
  },
};

์œ„์™€ ๊ฐ™์ด ์‚ฌ์ „์— ์ •์˜ํ–ˆ๋˜ ๋ฐฉ๋ฒ•๋Œ€๋กœ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ๋งŒ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๊ณ , numberOfRuns ์— ๋”ฐ๋ผ ์„ธ ๋ฒˆ์˜ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์š”์•ฝ ๋ณด๊ณ ์„œ ํŒŒ์ผ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// lighthouse_reports/manifest.json

[
  {
    "url": "http://localhost:3000/",
    "isRepresentativeRun": false,
    "htmlPath": "/Users/dohyeon/Development/knoticle/frontend/lighthouse_reports/_-2022_11_26_12_40_53-report.html",
    "jsonPath": "/Users/dohyeon/Development/knoticle/frontend/lighthouse_reports/_-2022_11_26_12_40_53-report.json",
    "summary": {
      "performance": 0.98,
      "accessibility": 0.94,
      "best-practices": 0.92,
      "seo": 0.8,
      "pwa": 0.3
    }
  },

  ...
]

์ด๋Ÿฐ ๋ณด๊ณ ์„œ๋ฅผ PR ์ฝ”๋ฉ˜ํŠธ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ž‘์—… ๊ณผ์ •๋งˆ๋‹ค ์ง€ํ‘œ๋กœ ์‚ผ์„ ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

๋’ค์— Format Lighthouse Score ์Šคํ…๊ณผ Comment Lighthouse Report ์Šคํ…์—์„œ๋Š” ๋ณด๊ณ ์„œ๋ฅผ ํฌ๋งคํŒ…ํ•ด์„œ ์ฝ”๋ฉ˜ํŠธ๋กœ ๋‚จ๊ฒจ์ฃผ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

image

โš™๏ธ ๋ฐฑ์—”๋“œ์˜ CI

๋ฐฑ์—”๋“œ์˜ CI๋Š” ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ main ๋ธŒ๋žœ์น˜์™€ develop ๋ธŒ๋žœ์น˜์— PR์„ ์˜ฌ๋ฆฐ ์ƒํƒœ์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

name: Backend CI

on:
  pull_request:
    branches: [main, develop]
    paths:
      - 'backend/**'

jobs:
  lint:
    ...

  build:
    ...

๋™์ผํ•œ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ถ”๊ฐ€๋กœ ์„ค๋ช…๋“œ๋ฆฌ์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ์˜ CD

ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ ๋ชจ๋‘ CI ๊ณผ์ •์„ ๊ฑฐ์น˜๊ณ  ๋‚˜๋ฉด CD ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

nCloud ์„œ๋น„์Šค์— ์ ‘์†ํ•ด์„œ ๋นŒ๋“œํ•˜๊ณ , PM2 reload๋ฅผ ํ†ตํ•ด์„œ ๋ฌด์ค‘๋‹จ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ์™€ ๋ฐฑ์—”๋“œ๊ฐ€ ๋™์ผํ•œ CD ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ก ํŠธ์—”๋“œ ๊ธฐ์ค€์œผ๋กœ๋งŒ ์„ค๋ช…๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

name: Frontend CD

on:
  push:
    branches: [main]
    paths:
      - 'frontend/**'

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Generate Environment Variables
        run: |
          echo "$FRONTEND_ENV" >> .env.production
        env:
          CI: false
          FRONTEND_ENV: '${{ secrets.FRONTEND_ENV }}'

      - name: Transfer Environment Variables with SCP
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          port: ${{ secrets.SSH_PORT }}
          source: '.env.production'
          target: 'knoticle/frontend'

      - name: Deploy
        uses: appleboy/ssh-action@v0.1.4
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          port: ${{ secrets.SSH_PORT }}
          script: ${{ secrets.SSH_FRONTEND_SCRIPT }}

Generate Environment Variables ์Šคํ…์—์„œ๋Š” GitHub Secrets์— ์ €์žฅ๋œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

์ดํ›„ Transfer Environment Variables with SCP ์Šคํ…์—์„œ SCP(Secure Copy)๋ฅผ ํ†ตํ•ด nCloud ์„œ๋ฒ„์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋ณด๋‚ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ์›๊ฒฉ ์ €์žฅ์†Œ์— ์ €์žฅ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฐ์‹์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ Deploy ์Šคํ…์—์„œ nCloud์— ์ ‘์†ํ•ด์„œ ์ฝ”๋“œ๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ๋ฌด์ค‘๋‹จ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

๐Ÿค”ย ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์€ ์ 

  • Lighthouse ์ง€ํ‘œ ์™ธ์— ๋‹ค๋ฅธ ์ง€ํ‘œ๋„ ๋ฐ›์•„๋ณด๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
    • ๊ตฌ๊ธ€ Page Speed Insight๋Š” ์›น ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉ์ž์˜ ํ™˜๊ฒฝ ํ’ˆ์งˆ์— ๋Œ€ํ•œ ํ‰๊ฐ€ ์ ์ˆ˜๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. PR ์ฝ”๋ฉ˜ํŠธ์— ํ•ด๋‹น ๋ฆฌํฌํŠธ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
  • CI ๊ณผ์ •์—์„œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •๋„ ํ•„์š”ํ•ด๋ณด์ž…๋‹ˆ๋‹ค.
    • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์ž‘์„ฑ๋˜๋ฉด ์ด ๊ณผ์ •๋„ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.
Clone this wiki locally