배포한 웹사이트 CI/CD 구현하기

코딩로그·2025년 4월 3일
0

CI/CD 기본 개념

CI / CD (Continuous Integration, Continuous Deployment)

  • 테스트(Test), 통합(Merge), 배포(Deploy) 과정을 자동화하는 것

CI/CD 과정

Develop → Commit → Build → Test → Deploy

  • 특정 기능을 개발하고 Commit을 하면 Build 실행
  • 빌드가 완료되면 작성된 테스트 코드가 실행
    • 단, 테스트 코드가 없는 서비스에서는 이 과정을 생략
  • 테스트를 통과하면 실제 서버에 최신 코드가 자동으로 배포

CI/CD 구축 시 사용할 GitHub Actions

사용할 수 있는 대표적인 CI/CD 도구들

  • GitHub Actions
    → 현업에서 가장 많이 사용되며, 무료로 제공되는 서비스
  • Jenkins
  • Circle CI
  • Travis CI 등

💡 GitHub Actions vs Jenkins 비교

항목GitHub ActionsJenkins
설치 필요 여부없음 (클라우드 기반)별도 서버 설치 필요
비용무료 (Private 리포지토리 포함)서버 운영 비용 발생
설정 편의성GitHub와 자연스럽게 연동되어 간편설정이 복잡하고 세팅 시간이 필요
사용 환경GitHub 리포지토리와 통합 운영독립된 서버에서 관리 및 설정 필요
  • Jenkins는 별도의 서버 구축이 필수
  • 비용 절감과 시간 단축을 위해 GitHub Actions를 사용

GitHub Actions vs Jenkins: 장단점 비교

항목GitHub ActionsJenkins
장점- GitHub와 완벽하게 통합
- 클라우드 기반으로 서버 불필요
- yaml 기반 설정으로 간편
- 퍼블릭 리포지토리에서는 무료
- 다양한 Marketplace 액션 제공
- 플러그인 기반 커스터마이징에 강함
- 복잡한 파이프라인 구현 가능
- 내부망 환경에서도 안정적으로 운영
- GitHub 외 다양한 VCS 연동 가능
- Job 관리 및 시각화 우수
단점- GitHub에 의존적
- GitHub 외 플랫폼과의 연동은 제한적
- 복잡한 파이프라인에서는 한계가 있을 수 있음
- 서버 구축 및 유지관리 필요
- 인프라 비용 및 관리 리소스 필요
- UI나 플러그인의 버전 이슈가 발생 가능
- 초기 진입 장벽이 있음

상황별 적합한 선택 도구

상황추천 도구
GitHub 리포 기반 + 빠른 구축이 필요한 경우GitHub Actions
사내 인프라 환경 + 복잡한 커스터마이징이 필요한 경우Jenkins
IoT/모바일 등 특수한 환경이 필요한 경우Jenkins + 기타 도구 조합

GitHub Actions를 활용한 CI/CD

  1. 코드 작성 후 Commit
  2. GitHub에 Push
  3. Push 이벤트 감지 → GitHub Actions 워크플로우 실행
    • Build
    • Test
    • Deploy
  4. 서버에서 최신 코드로 실행

GitHub Actions을 이용한 CI/CD 구축 실습

Repository 설정

GitHub 레포지토리에 React 프로젝트 Push

GitHub Actions 설정

디렉토리 생성

  • 프로젝트 루트에 .github > workflows 디렉토리를 생성
  • workflows 디렉토리에 deploy.yml 파일을 생성하고, 아래와 같이 코드를 작성
name: Github Actions 실행시켜보기

on: 
  push: 
    branch: 
      - main
  • 위 설정은 main 브랜치에 push될 때마다 아래 작업들을 실행하도록 지정한 것
  • git push 후 GitHub Actions 탭에서 자동으로 생성된 워크플로우 항목을 확인 가능

예시 코드

name: Github Actions 실행시켜보기

on:
  push:
    branch:
      - main

jobs:
  My-Depoly-Job:
    runs-on: ubuntu-latest

    steps:
      - name: Hello World 출력하기
        run: echo "Hello World"

  • 하나의 워크플로우는 여러 개의 Job으로 구성될 수 있으며,
    하나의 Job은 여러 개의 Step으로 이루어질 수 있음

여러 명령어 실행 예시

      - name: 여러 명령어 문장 작성하기
        run: |
          echo "Good"
          echo "Morning"
          pwd

GitHub 내장 변수 출력 예시

      - name: 변수 사용하기
        run: |
          echo $GITHUB_REPOSITORY
          echo $GITHUB_SHA

Secret 변수 사용 예시

      - name: Github Actions Secret 변수 사용하기
        run: |
          echo ${{ secrets.MY_NAME }}
          echo ${{ secrets.MY_HOBBY }}
  • secret 값은 GitHub 저장소 → Settings → Secrets and variables → Actions에서 등록

  • 민감한 정보를 외부에 노출하지 않기 위해 사용
    (출력 시 ***로 마스킹됨)

React 프로젝트의 전체 CI/CD 흐름

  1. git push
  2. GitHub Actions가 Push 이벤트 감지
  3. Job 실행 → S3에 파일 업로드, 빌드 파일 전달, CloudFront 캐시 무효화
  4. 브라우저에서 최신 배포 확인

GitHub Actions가 AWS에 접근하기 위한 인증 방식

IAM이란?

  • AWS 리소스에 접근하려면 GitHub Actions가 사용할 IAM 사용자 혹은 역할(Role)이 필요
  • 액세스 키(Access Key ID)와 시크릿 키(Secret Access Key)를 발급받아 인증

IAM 사용자 생성 과정

  1. IAM → Access management → Users → Create User

  2. User 이름 입력

  3. 권한 정책 연결에서
    - 직접 정책 연결 (Attach policies directly)
    - 권한 정책 > AmazonS3FullAccess & CloudFrontFullAccess 두 개 체크 후 다음 단계로

  4. 사용자 생성 완료

액세스 키 발급

  • 생성된 사용자 → Security Credentials 탭
  • Access Keys → Create Access Key
    • 외부 애플리케이션용(Application running outside ASW) 선택
    • Description 생략 가능
    • 생성된 키는 GitHub에 등록

GitHub에 Access Key 등록

  • GitHub → Settings → Secrets and variables → Actions
  • AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 두 값을 등록

GitHub Actions 배포 코드 예시

레포지토리 불러오기

      - name: Github Repository 파일 불러오기
        uses: actions/checkout@v4

      - name: Repository 파일 출력하기
        run: ls

빌드 명령어 실행

      - name: 의존성 설치
        run: npm i

      - name: 빌드하기
        run: npm run build

      - name: Debugging
        run: |
          ls
          cd dist
          ls

S3에 파일 업로드

기존 파일 삭제

      - name : AWS Resource 접근을 위한 인증 설정
        uses : aws-actions/configure-aws-credentials@v4
        with : 
          aws-region : us-east-1
          aws-access-key-id : {{ $secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key : {{ $secrets.AWS_SECRET_ACCESS_KEY }}

      - name : S3 기존 파일들 전체 삭제
        run : |
          aws s3 rm --recursive s3://oz-practice 

  • S3에 있던 기존 파일이 삭제됨

새 파일 업로드

  • recursive : 재귀적으로 모든 하위 디렉토리까지 탐색하여 명령어를 실행하겠다는 의미
      - name: S3에 빌드된 파일 업로드
        run: aws s3 cp ./dist s3://oz-practice/ --recursive

  • S3에 새롭게 build된 파일 업로드

CloudFront 캐시 무효화

  • 무효화 생성
    • distribution-id (배포 ID)
    • Invalidation을 추가할 때 설정했던 Object paths와 마찬가지로 --path에 “/*”입력
    • /*는 모든 파일을 대상으로 무효화 처리
      - name: CloudFront 캐시 무효화
        run: aws cloudfront create-invalidation --distribution-id E27IT17HQ8DDSV --path "/*"

  • Cloud front의 무효화 리스트에 새로운 항목 추가됨

자동화 테스트

새 기능 추가 (React 코드)

{/* ✅ 날짜와 시간 표시 */}
<p>🕒 현재 시간: {dateTime.toLocaleString()}</p>

{/* ✅ 스탑 / 계속 버튼 */}
<div style={{ marginTop: '1rem' }}>
  <button onClick={() => setIsRunning(false)} style={{ marginRight: '0.5rem' }}>
    ⏸️ 스탑
  </button>
  <button onClick={() => setIsRunning(true)}>
    ▶️ 계속
  </button>
</div>

배포 확인

  • 새로운 기능 추가
    • 날짜와 시간 표시
    • 스탑 / 계속 버튼 추가
        {/* 날짜와 시간 표시 */}
        <p>🕒 현재 시간: {dateTime.toLocaleString()}</p>

        {/* 스탑 / 계속 버튼 */}
        <div style={{ marginTop: '1rem' }}>
          <button onClick={() => setIsRunning(false)} style={{ marginRight: '0.5rem' }}>
            ⏸️ 스탑
          </button>
          <button onClick={() => setIsRunning(true)}>
            ▶️ 계속
          </button>
  • git commit & push
git add .
git commit -m "새로운 기능 추가"
git push origin main
  • 사이트에 바로 적용되는지 확인
profile
hello world!

0개의 댓글