[Day 11] CI/CD란 무엇인가? (GitHub Actions 기본)

짱효·2026년 4월 28일

프론트엔드 기초 다시 쌓기 챌린지 11일차.
Week 3 "실전 배포 흐름"의 첫 번째 수업.
지금까지 빌드·배포·서버·pm2·Nginx·로그까지 배웠다면,
오늘은 "이걸 왜 매번 수동으로 하고 있었지?" 라는 질문에서 시작한다.


🤖 오늘의 비유: "자동 주방 관리 로봇"

지금까지의 배포 과정을 떠올려보면 이렇다.

1. 코드 수정 완료
2. SSH로 서버 접속
3. git pull (코드 가져오기)
4. yarn build (빌드)
5. pm2 restart (재시작)
6. 잘 되나 확인

하루에 한 번이면 괜찮은데, 하루에 5번 배포하면? 실수할 확률이 엄청 올라간다.

레스토랑 비유로 하면 셰프가 매번 직접 시장 가서 재료 사고, 손질하고, 세팅하고, 불 켜는 것이다.

CI/CD는 "자동 주방 관리 로봇"을 도입하는 것이다.
새 레시피를 레시피북에 적어 넣으면(git push), 로봇이 알아서 다 해준다.


🔄 CI와 CD, 각각 뭔가?

CI: Continuous Integration (지속적 통합)

"코드를 합칠 때마다 자동으로 검사한다"

레스토랑 비유로 하면 자동 품질 검사 시스템이다.

  • 셰프가 새 레시피를 제출하면
  • 자동으로 맛 테스트 (코드 테스트)
  • 자동으로 위생 검사 (린트 검사)
  • 자동으로 재료 손질 가능한지 확인 (빌드 성공 여부)
  • 통과하면 ✅, 실패하면 ❌ 알림

핵심: "문제를 빨리 발견하는 것"

CD: Continuous Deployment / Delivery (지속적 배포)

"검사 통과하면 자동으로 배포까지 한다"

여기서 Delivery와 Deployment의 차이가 중요하다.

구분레스토랑 비유실제
CI새 레시피 → 자동 맛 테스트 + 위생 검사push → 자동 빌드 + 테스트
CD (Delivery)검사 통과 → 주방 앞까지 갖다 놓음 (셰프가 직접 불 켬)배포 직전까지 자동 + 사람이 최종 승인
CD (Deployment)검사 통과 → 자동으로 불까지 켜짐배포까지 전부 자동

Delivery vs Deployment 차이는 딱 하나:

마지막 "배포 실행" 버튼을 사람이 누르느냐, 자동이냐.

많은 회사에서 Delivery를 쓰는 이유는, 프로덕션에 자동으로 바로 올라가면 무서우니까
"마지막 확인은 사람이 하자" 라는 안전장치를 두는 것이다.
쇼핑몰 같은 서비스는 결제 몰리는 시간에 배포하면 안 되니까.


⚙️ GitHub Actions란?

CI/CD를 해주는 도구는 여러 개 있다. Jenkins, CircleCI, GitLab CI 등.
그 중 GitHub Actions는 GitHub에 내장된 CI/CD 도구다.

레스토랑 비유로 하면 레스토랑에 설치된 "자동 주방 관리 로봇"이다.
레시피북(GitHub 저장소)에 새 레시피가 추가되면, 로봇이 자동으로 일을 시작한다.

핵심 용어 4가지

📦 Workflow (워크플로우) = "자동화 작업 전체 계획서"
   → 로봇에게 주는 작업 지시서

📋 Event (이벤트) = "언제 시작할지"
   → "새 레시피가 들어오면 시작해" (push, pull request 등)

🔧 Job (잡) = "큰 작업 단위"
   → "1번: 재료 검사하기, 2번: 요리하기"

👣 Step (스텝) = "잡 안의 세부 단계"
   → "1-1: 재료 꺼내기, 1-2: 신선도 확인, 1-3: 손질하기"

워크플로우 파일은 어디에?

프로젝트 루트에 .github/workflows/ 폴더 안에 YAML 파일로 만든다.

내 프로젝트/
├── .github/
│   └── workflows/
│       └── deploy.yml    ← 이 파일이 "작업 지시서"
├── pages/
├── package.json
└── ...

📄 실제 GitHub Actions 파일 읽어보기

아직 직접 만들 필요는 없다. 읽을 수 있으면 된다.

# .github/workflows/deploy.yml
name: 배포 자동화          # 워크플로우 이름

on:                        # 📋 Event: "언제 실행할지"
  push:
    branches: [main]       # main 브랜치에 push하면 실행

jobs:                      # 🔧 Job 목록
  build-and-deploy:        # Job 이름
    runs-on: ubuntu-latest # 어떤 컴퓨터에서 실행할지

    steps:                 # 👣 세부 단계들
      # 1단계: 코드 가져오기
      - name: 코드 체크아웃
        uses: actions/checkout@v4

      # 2단계: Node.js 설치
      - name: Node.js 설치
        uses: actions/setup-node@v4
        with:
          node-version: '18'

      # 3단계: 패키지 설치
      - name: 의존성 설치
        run: yarn install

      # 4단계: 빌드
      - name: 빌드
        run: yarn build

      # 5단계: 서버에 배포
      - name: 서버에 배포
        run: |
          ssh -i ${{ secrets.SSH_KEY }} ubuntu@${{ secrets.SERVER_IP }} << 'EOF'
            cd /var/www/my-project
            git pull origin main
            yarn install
            yarn build
            pm2 restart my-app
          EOF

레스토랑 비유로 한 줄씩 해석

name: 배포 자동화        → 작업 지시서 이름: "신메뉴 자동 세팅"
on: push, branches: main → "메인 레시피북에 새 레시피 들어오면 시작"
runs-on: ubuntu-latest   → "임시 작업 공간에서 실행"
코드 체크아웃             → 재료 창고에서 재료 꺼내오기
Node.js 설치             → 조리 도구 준비
yarn install             → 재료 진열
yarn build               → 재료 손질 + 소스 만들기
서버에 배포              → 완성된 걸 진짜 주방으로 옮기고 불 켜기

🔐 GitHub Secrets

위 파일에서 ${{ secrets.SSH_KEY }} 부분이 있다.

SSH 키나 서버 IP 같은 비밀 값을 코드에 직접 쓰면 전 세계에 공개된다.
그래서 GitHub 저장소의 Settings → Secrets에 저장해두고 필요할 때만 꺼내 쓴다.

레스토랑 비유: 로봇에게 열쇠(SSH 키)를 주려면 금고(Secrets)에 넣어두고 필요할 때만 꺼내 쓰게 하는 것. 레시피북(코드)에 열쇠를 붙여놓으면 누구나 볼 수 있으니까.


🧪 CI에서 자동으로 돌리는 검사 3가지

1. 코드 규칙 검사 (Lint)

레스토랑 비유: "레시피 맞춤법 검사"

// ❌ lint 에러: 세미콜론 빠짐, 안 쓰는 변수
const name = "hello"
const unused = 123

// ✅ 통과
const name = "hello";

ESLint 같은 도구가 "코드 스타일이 규칙에 맞는지" 자동 검사해준다.

2. 빌드 테스트

레스토랑 비유: "재료 손질이 제대로 되는지 확인"

yarn build가 성공하는지 확인하는 것. 단순하지만 엄청 중요하다.
TypeScript 타입 에러가 있으면 빌드가 깨지는데, 서버에서 발견하면 이미 늦는다. CI에서 미리 잡아준다.

3. 유닛 테스트 / 컴포넌트 테스트

레스토랑 비유: "자동 맛 테스트 로봇"

// "장바구니에 상품 추가하면 수량이 1 증가해야 한다"
test('장바구니 추가', () => {
  const cart = addItem(cart, item);
  expect(cart.length).toBe(1);  // 1이면 ✅, 아니면 ❌
});

실행 순서:

git push → lint 검사 → 빌드 테스트 → 유닛 테스트
  → 전부 ✅ → 배포 진행
  → 하나라도 ❌ → 배포 중단 + 알림

모든 회사가 3개 다 하는 건 아니다. 작은 팀이나 초기 프로젝트에서는 lint + 빌드만 돌리는 경우도 많다.


📊 CI/CD 없을 때 vs 있을 때

상황CI/CD 없이 (수동)CI/CD 있을 때 (자동)
배포할 때SSH 접속 → git pull → build → restartgit push만 하면 끝
빌드 에러서버에서 발견 (이미 늦음)push하자마자 알림 ❌
실수 가능성높음 (명령어 빠뜨리기 등)낮음 (항상 같은 순서)
배포 시간10~20분 (사람이 직접)5~10분 (자동, 다른 일 가능)
야근 중 배포집중력 떨어져서 더 위험로봇은 피곤하지 않음

🍳 레스토랑 비유 업데이트

레스토랑서버
자동 주방 관리 로봇GitHub Actions
작업 지시서Workflow (YAML 파일)
"새 레시피 들어오면 시작"Event (on: push)
큰 작업 (재료검사, 요리)Job
세부 단계 (꺼내기, 손질)Step
로봇의 금고 (열쇠 보관)GitHub Secrets

🎯 오늘 배운 것 최종 정리

  1. CI/CD란: git push만 하면 빌드·테스트·배포가 자동으로 돌아가는 시스템
  2. CI (Continuous Integration): 코드 합칠 때 자동 검사 (lint → 빌드 → 테스트)
  3. CD Delivery: 배포 직전까지 자동, 마지막은 사람이 승인
  4. CD Deployment: 배포까지 전부 자동
  5. GitHub Actions: .github/workflows/에 YAML 파일로 작성
  6. 4가지 핵심 개념: Workflow → Event → Job → Step
  7. Secrets: SSH 키 같은 비밀 값은 GitHub Secrets에 보관
  8. CI 검사 3가지: lint(코드 규칙) → 빌드 테스트 → 유닛 테스트

🧪 이해도 체크

Q1. CI/CD를 레스토랑 비유로 설명하면?
→ 정답: 레시피북에 새 레시피 넣으면 자동으로 재료 손질 + 맛 테스트 + 주방 세팅까지 되는 것

Q2. Delivery와 Deployment의 차이는?
→ 정답: 마지막 배포 버튼을 사람이 누르느냐(Delivery), 자동이냐(Deployment)

Q3. 비밀 값(SSH 키 등)을 GitHub Actions에서 쓰려면?
→ 정답: GitHub 저장소의 Secrets에 저장. 코드에 직접 쓰면 전 세계에 공개됨


💭 회고

지금까지 Day 7에서 SSH, Day 8에서 pm2, Day 9에서 Nginx를 배우면서
수동으로 서버에 접속하고, 빌드하고, 재시작하는 흐름을 익혔다.

오늘은 "이걸 왜 매번 수동으로 하고 있었지?" 라는 질문에 대한 답을 찾았다.
CI/CD가 별게 아니었다. 내가 수동으로 하던 과정을 로봇이 대신하는 것이다.

YAML 파일이 처음에는 낯설었는데, 한 줄씩 레스토랑 비유로 해석하니까
"아 그냥 내가 터미널에 치던 명령어를 순서대로 적어놓은 거구나" 싶었다.

특히 Delivery와 Deployment 차이가 인상적이었다.
"마지막 버튼을 사람이 누르느냐, 자동이냐" 하나 차이인데,
실제로 프로덕션 배포할 때 이 안전장치가 얼마나 중요한지 느껴진다.


📚 다음 학습 예고

Day 12: Docker 기초 — 컨테이너가 뭐야?
GitHub Actions에서 runs-on: ubuntu-latest라고 쓴 "임시 작업 공간" 개념을 더 깊이 파고든다.
레스토랑 비유: "어디에 가져다 놔도 똑같은 요리가 나오는 이동식 주방" 🚚

#프론트엔드 #CI/CD #GitHubActions #배포자동화 #2년차개발자 #기초다시쌓기

profile
✨🌏확장해 나가는 프론트엔드 개발자입니다✏️

0개의 댓글