튜토리얼

GitHub Actions로 React 앱 자동 배포: CI/CD 파이프라인 구축 실전 가이드

강코의 코딩 일기 2026. 5. 11. 15:19
반응형

GitHub Actions를 활용해 React 애플리케이션을 자동으로 배포하는 CI/CD 파이프라인 구축 경험을 공유합니다. 반복적인 수동 배포 과정을 자동화하여 개발 생산성을 높이는 실전 가이드를 만나보세요.

안녕하세요, 개발자 여러분!

매번 React 애플리케이션을 개발하고 나서 수동으로 빌드하고, 서버에 접속해서 파일을 업로드하며, 캐시를 지우는 일련의 과정에 지쳐본 경험이 있으신가요? 저는 정말 많았습니다. 특히 팀 프로젝트에서는 누군가 실수로 다른 버전을 배포하거나, 배포 과정에서 예상치 못한 오류가 발생하여 서비스 중단으로 이어지는 끔찍한 상황을 마주하기도 했습니다.

이러한 문제들을 해결하고 개발 생산성을 극대화하기 위해, 저는 GitHub Actions를 활용하여 React 애플리케이션 자동 배포 CI/CD 파이프라인을 구축했습니다. 실제로 적용해 본 결과, 개발팀의 배포 스트레스가 현저히 줄어들었고, 새로운 기능 배포 속도도 눈에 띄게 빨라졌습니다. 이 글에서는 제가 직접 경험하고 구축한 과정을 상세히 공유하며, 여러분도 손쉽게 자신만의 자동 배포 파이프라인을 만들 수 있도록 돕겠습니다.

이제 지루하고 반복적인 수동 배포는 그만! CI/CD 자동화를 통해 개발에 더 집중하고, 더 가치 있는 일에 시간을 투자해 보세요.


GitHub Actions와 CI/CD 기본 이해: 왜 자동화인가?

CI/CDContinuous Integration (지속적 통합)Continuous Delivery/Deployment (지속적 배포/전달)의 약자입니다. 간단히 말해, 개발자가 작성한 코드를 중앙 저장소에 주기적으로 통합하고, 자동으로 빌드 및 테스트를 거쳐 배포 가능한 상태로 만들거나 실제 서비스 환경에 배포하는 일련의 과정을 의미합니다.

과거에는 개발자가 코드를 작성한 후, 다른 개발자들의 코드와 합치는 과정에서 수많은 충돌과 오류를 경험하곤 했습니다. 또한, 배포는 수동으로 이루어져 많은 시간과 인력을 소모하고, 사람의 실수로 인한 장애 발생 위험이 항상 존재했습니다. 하지만 CI/CD를 도입하면 이러한 문제들을 크게 개선할 수 있습니다.

CI/CD의 핵심 가치: 빠른 피드백과 안정성

  • 빠른 오류 감지 및 수정: 코드를 자주 통합하고 테스트함으로써, 문제가 발생했을 때 즉시 발견하고 수정할 수 있습니다. 이는 개발 초기 단계에서 비용이 적게 드는 장점이 있습니다.
  • 일관된 빌드 및 배포: 모든 과정이 자동화되므로, 환경에 관계없이 항상 동일한 방식으로 빌드 및 배포가 이루어집니다. "내 컴퓨터에서는 되는데..."와 같은 상황을 방지할 수 있습니다.
  • 개발자 생산성 향상: 개발자는 반복적인 수작업에서 벗어나 핵심 개발 업무에 집중할 수 있습니다. 배포에 대한 부담이 줄어들어 더 자주, 더 과감하게 새로운 기능을 시도할 수 있습니다.
  • 안정적인 서비스 운영: 자동화된 테스트를 통해 배포 전 잠재적 문제를 걸러내고, 롤백이 용이해져 서비스 안정성을 높일 수 있습니다.

GitHub Actions, 왜 선택해야 할까?

수많은 CI/CD 도구 중에서 제가 GitHub Actions를 선택한 이유는 다음과 같습니다.

  • GitHub와의 완벽한 통합: 대부분의 개발 프로젝트가 GitHub를 사용합니다. GitHub Actions는 저장소와 동일한 환경에서 작동하여 별도의 서버 구축이나 연동 설정이 필요 없습니다.
  • Yaml 기반의 간단한 설정: .yml 파일을 통해 워크플로우를 직관적으로 정의할 수 있습니다. 학습 곡선이 낮아 빠르게 도입할 수 있습니다.
  • 풍부한 마켓플레이스: 다양한 Actions가 마켓플레이스에 등록되어 있어, 복잡한 기능을 직접 구현하지 않고도 가져다 쓸 수 있습니다. AWS S3 배포, CloudFront 캐시 무효화 등 필요한 대부분의 Action을 쉽게 찾을 수 있습니다.
  • 무료 사용량 제공: 공개 저장소는 무제한, 비공개 저장소도 월별 일정 시간까지 무료로 사용할 수 있어 초기 비용 부담이 적습니다.

이러한 장점들 덕분에 GitHub Actions는 개인 프로젝트부터 소규모 팀 프로젝트까지 CI/CD 자동화를 시작하기에 최적의 도구라고 판단했습니다.


React 앱 자동 배포 파이프라인 설계

이제 본격적으로 React 애플리케이션을 위한 자동 배포 파이프라인을 어떻게 설계할지 알아보겠습니다. 목표는 개발자가 코드를 GitHub에 푸시하면, 자동으로 빌드되고 테스트를 거쳐 프로덕션 환경에 배포되는 것입니다.

이상적인 React 앱 배포 워크플로우 구성 요소

제가 구성한 React 앱 배포 워크플로우의 핵심 단계는 다음과 같습니다.

  1. 코드 푸시 (Code Push): 개발자가 main 브랜치 (또는 배포 대상 브랜치)에 코드를 푸시합니다.
  2. 워크플로우 트리거 (Workflow Trigger): GitHub Actions가 코드 푸시 이벤트를 감지하여 워크플로우를 시작합니다.
  3. 환경 설정 (Environment Setup): Node.js 환경을 설정하고, 프로젝트 의존성을 설치합니다.
  4. 코드 빌드 (Code Build): npm run build 명령어를 실행하여 React 애플리케이션을 빌드하고 정적 파일을 생성합니다.
  5. 테스트 (Optional Testing): (선택 사항이지만 강력히 권장) 유닛 테스트, 통합 테스트 등을 실행하여 코드의 안정성을 검증합니다. 저는 이 단계에서 린트 검사도 함께 진행합니다.
  6. 배포 (Deployment): 빌드된 정적 파일을 클라우드 저장소 (예: AWS S3)에 업로드합니다.
  7. 캐시 무효화 (Cache Invalidation): CDN (예: AWS CloudFront)을 사용한다면, 변경된 내용이 즉시 반영되도록 캐시를 무효화합니다.
  8. 알림 (Optional Notification): 배포 성공/실패 여부를 Slack 등으로 알립니다.

이러한 단계를 거치면, 개발자는 코드 작성에만 집중할 수 있고 배포는 시스템에 맡길 수 있습니다.

AWS S3 + CloudFront를 통한 정적 웹사이트 배포 전략

React 애플리케이션은 클라이언트 측에서 동작하는 SPA (Single Page Application)이므로, 빌드 결과물은 정적인 HTML, CSS, JavaScript 파일들입니다. 이러한 정적 파일을 호스팅하는 데 AWS S3CloudFront 조합은 매우 효과적이고 비용 효율적입니다.

  • AWS S3 (Simple Storage Service): 확장성이 뛰어나고 안정적인 객체 스토리지 서비스입니다. 웹사이트 호스팅 기능을 제공하여 정적 파일을 저장하고 웹으로 서비스할 수 있습니다.
  • AWS CloudFront: CDN (Content Delivery Network) 서비스입니다. 사용자와 가장 가까운 엣지 로케이션에서 콘텐츠를 캐싱하여, 웹사이트 로딩 속도를 향상시키고 S3에 대한 직접적인 요청 부하를 줄여줍니다. 또한, HTTPS를 쉽게 적용할 수 있어 보안성도 높일 수 있습니다.

이 전략은 높은 가용성과 성능을 제공하며, 트래픽에 따라 자동으로 확장되므로 React 애플리케이션 배포에 매우 적합합니다.


GitHub Actions 워크플로우 구축 실전 가이드

이제 위에서 설계한 파이프라인을 GitHub Actions 워크플로우 파일로 직접 구현해 보겠습니다. 프로젝트 루트 디렉터리에 .github/workflows/deploy.yml 파일을 생성합니다.

다음은 제가 실제로 사용하고 있는 React 애플리케이션 배포 워크플로우의 예시입니다. AWS S3와 CloudFront를 이용한 배포를 기준으로 작성되었습니다.

name: React App CI/CD Pipeline

on:
  push:
    branches:
      - main # main 브랜치에 푸시될 때 워크플로우 실행

env:
  NODE_VERSION: '18' # 사용할 Node.js 버전
  REACT_APP_BUILD_PATH: 'build' # React 앱 빌드 결과물이 생성될 경로

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest # 워크플로우를 실행할 가상 환경

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4 # GitHub 저장소 코드를 워크플로우 환경으로 가져옴

      - name: Setup Node.js environment
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }} # env에 정의된 Node.js 버전 사용
          cache: 'npm' # npm 캐싱 설정으로 의존성 설치 속도 향상

      - name: Install dependencies
        run: npm ci # package-lock.json에 기반하여 의존성 설치 (CI 환경에 적합)

      - name: Run tests (optional)
        run: npm test -- --watchAll=false # 테스트 실행. 실제 프로젝트에서는 더 상세한 테스트 스크립트 사용

      - name: Build React application
        run: npm run build # React 앱 빌드 명령어 실행

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # GitHub Secrets에 저장된 AWS Access Key ID
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # GitHub Secrets에 저장된 AWS Secret Access Key
          aws-region: ap-northeast-2 # AWS 리전 설정 (예: 서울 리전)

      - name: Deploy to S3
        run: aws s3 sync ${{ env.REACT_APP_BUILD_PATH }} s3://YOUR_S3_BUCKET_NAME --delete # 빌드된 파일을 S3 버킷에 동기화
        env:
          YOUR_S3_BUCKET_NAME: "your-react-app-bucket" # 실제 S3 버킷 이름으로 변경

      - name: Invalidate CloudFront Cache
        run: aws cloudfront create-invalidation --distribution-id YOUR_CLOUDFRONT_DISTRIBUTION_ID --paths "/*" # CloudFront 캐시 무효화
        env:
          YOUR_CLOUDFRONT_DISTRIBUTION_ID: "E1234567890ABC" # 실제 CloudFront 배포 ID로 변경

각 단계별로 자세히 설명해 드리겠습니다.

  • name: React App CI/CD Pipeline: 워크플로우의 이름입니다. GitHub Actions UI에서 이 이름으로 표시됩니다.
  • on: push: branches: - main: 이 워크플로우가 언제 실행될지 정의합니다. main 브랜치에 코드가 푸시될 때마다 실행됩니다. 필요에 따라 develop 등 다른 브랜치나 pull_request 이벤트로 변경할 수 있습니다.
  • env:: 워크플로우 전역에서 사용할 환경 변수를 정의합니다. NODE_VERSIONREACT_APP_BUILD_PATH를 설정했습니다.
  • jobs: build-and-deploy:: 워크플로우는 하나 이상의 '작업(Job)'으로 구성됩니다. 이 작업은 build-and-deploy라는 이름으로 정의됩니다.
  • runs-on: ubuntu-latest: 이 작업이 실행될 가상 환경을 지정합니다. ubuntu-latest는 최신 Ubuntu 환경을 의미합니다.
  • steps:: 각 작업은 순차적으로 실행되는 여러 '단계(Step)'로 이루어집니다.
  • Checkout repository: actions/checkout@v4 Action을 사용하여 GitHub 저장소의 코드를 가상 환경으로 가져옵니다. 이 단계가 있어야 이후 빌드 작업을 수행할 수 있습니다.
  • Setup Node.js environment: actions/setup-node@v4 Action을 사용하여 Node.js 환경을 설정합니다. cache: 'npm'을 통해 의존성 설치 시간을 단축할 수 있습니다.
  • Install dependencies: npm ci 명령어를 사용하여 프로젝트 의존성을 설치합니다. npm cipackage-lock.json 파일을 기준으로 정확하게 의존성을 설치하므로 CI 환경에 적합합니다.
  • Run tests (optional): npm test 명령어를 실행하여 테스트를 수행합니다. --watchAll=false 옵션은 테스트가 한 번만 실행되고 종료되도록 합니다. 이 단계에서 테스트 실패 시 배포는 중단됩니다.
  • Build React application: npm run build 명령어를 실행하여 React 애플리케이션을 빌드합니다. 결과물은 build 디렉터리에 생성됩니다.
  • Configure AWS Credentials: aws-actions/configure-aws-credentials@v4 Action을 사용하여 AWS CLI가 AWS 리소스에 접근할 수 있도록 자격 증명을 설정합니다. secrets.AWS_ACCESS_KEY_IDsecrets.AWS_SECRET_ACCESS_KEYGitHub Secrets에 등록된 값입니다. 보안을 위해 하드코딩하지 않고 Secrets를 사용하는 것이 매우 중요합니다.
  • Deploy to S3: aws s3 sync 명령어를 사용하여 빌드된 파일들을 S3 버킷에 동기화합니다. --delete 옵션을 사용하면 S3 버킷에는 있지만 로컬 빌드 결과물에는 없는 파일들을 삭제하여 항상 최신 상태를 유지합니다. YOUR_S3_BUCKET_NAME을 실제 버킷 이름으로 변경해야 합니다.
  • Invalidate CloudFront Cache: aws cloudfront create-invalidation 명령어를 사용하여 CloudFront 캐시를 무효화합니다. --paths "/*"는 모든 경로의 캐시를 무효화하라는 의미입니다. YOUR_CLOUDFRONT_DISTRIBUTION_ID를 실제 CloudFront 배포 ID로 변경해야 합니다. 이 단계가 없으면 변경사항이 즉시 반영되지 않을 수 있습니다.

이 워크플로우 파일을 저장하고 main 브랜치에 푸시하면, GitHub Actions 탭에서 워크플로우가 실행되는 것을 확인할 수 있습니다.


배포 환경 구성 및 보안 강화 팁

워크플로우 파일을 작성하기 전에, AWS 환경을 올바르게 설정하고 보안을 강화하는 것이 중요합니다.

AWS S3 및 CloudFront 초기 설정

  1. S3 버킷 생성:
    • AWS S3 콘솔에서 새 버킷을 생성합니다. 버킷 이름은 전역적으로 고유해야 합니다.
    • '객체 소유권'은 'ACL 비활성화(권장)'를 선택하고, '모든 퍼블릭 액세스 차단'은 체크 해제합니다 (정적 웹사이트 호스팅을 위해).
    • 버킷 생성 후, '속성' 탭에서 '정적 웹사이트 호스팅'을 활성화하고, 인덱스 문서와 오류 문서를 지정합니다 (보통 index.html).
    • '권한' 탭에서 버킷 정책을 추가하여 퍼블릭 읽기 권한을 부여합니다.
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "PublicReadGetObject",
                  "Effect": "Allow",
                  "Principal": "*",
                  "Action": "s3:GetObject",
                  "Resource": "arn:aws:s3:::YOUR_S3_BUCKET_NAME/*"
              }
          ]
      }
  2. CloudFront 배포 생성:
    • AWS CloudFront 콘솔에서 '배포 생성'을 시작합니다.
    • '원본 도메인'으로 위에서 생성한 S3 버킷을 선택합니다. S3 웹사이트 엔드포인트가 아닌 S3 버킷 자체를 선택하고, 'S3 버킷 액세스'는 'CloudFront에서 S3 버킷 액세스 제어 업데이트'를 선택하여 OAC(Origin Access Control)를 설정하는 것이 보안상 좋습니다.
    • '뷰어 프로토콜 정책'은 'Redirect HTTP to HTTPS' 또는 'HTTPS Only'를 선택하여 보안을 강화합니다.
    • '기본 캐시 동작'에서 '대상 경로 패턴'을 /*로 설정하고, '뷰어 프로토콜 정책'을 HTTPS Only로 설정하는 것을 권장합니다.
    • 배포를 생성하면 배포 ID가 발급됩니다. 이 ID는 GitHub Actions 워크플로우에서 사용됩니다.

GitHub Secrets를 활용한 자격 증명 관리

AWS 자격 증명을 워크플로우 파일에 직접 노출하는 것은 매우 위험합니다. GitHub Secrets를 사용하면 민감한 정보를 안전하게 저장하고 워크플로우에서 사용할 수 있습니다.

  1. AWS IAM 사용자 생성:
    • AWS IAM(Identity and Access Management) 콘솔에서 새 사용자를 생성합니다.
    • '프로그래밍 방식 액세스'를 선택하고, '액세스 키'를 생성합니다. 이때 발급되는 Access Key IDSecret Access Key를 잘 보관합니다.
    • 이 사용자에게는 S3 버킷에 파일을 업로드하고, CloudFront 캐시를 무효화할 수 있는 최소한의 권한만 부여해야 합니다. (최소 권한의 원칙)
      • S3 관련 정책 예시: s3:PutObject, s3:GetObject, s3:DeleteObject, s3:ListBucket (특정 버킷에만 적용)
      • CloudFront 관련 정책 예시: cloudfront:CreateInvalidation (특정 배포 ID에만 적용)
  2. GitHub Secrets 등록:
    • GitHub 저장소로 이동하여 'Settings' -> 'Secrets and variables' -> 'Actions' 탭으로 이동합니다.
    • 'New repository secret' 버튼을 클릭하여 다음 두 가지 Secret을 추가합니다.
      • AWS_ACCESS_KEY_ID: 위에서 생성한 AWS Access Key ID 값
      • AWS_SECRET_ACCESS_KEY: 위에서 생성한 AWS Secret Access Key 값

이렇게 설정하면 워크플로우 파일에서는 ${{ secrets.AWS_ACCESS_KEY_ID }}와 같이 참조하여 안전하게 자격 증명을 사용할 수 있습니다.


자동화된 배포의 장점과 심화 활용 방안

GitHub Actions를 활용한 React 애플리케이션 자동 배포 파이프라인을 구축하고 나면, 개발 프로세스에 실질적인 변화를 가져옵니다. 제가 직접 경험한 주요 장점들을 비교 테이블로 정리해 보았습니다.

기준 수동 배포 자동화된 CI/CD 배포
시간 소요 매번 5분~30분 (빌드, 업로드, 캐시 무효화 등) 1분~5분 (워크플로우 실행 시간), 개발자 직접 개입 시간 0분
오류 발생률 높음 (사람의 실수, 환경 차이, 명령 누락 등) 낮음 (일관된 스크립트 실행, 테스트를 통한 사전 검증)
개발자 생산성 반복적인 수작업으로 인한 집중력 저하 및 시간 낭비 핵심 개발 업무에 집중, 배포 부담 해소
배포 빈도 적음 (번거로움 때문에 기능 몰아서 배포) 잦음 (작은 변경도 부담 없이 배포 가능)
팀 협업 배포 담당자 지정, 병목 현상 발생, 배포 프로세스 공유 어려움 누구나 쉽게 배포 가능, 배포 프로세스 투명화

이처럼 자동화된 CI/CD 파이프라인은 단순히 배포 과정을 편리하게 만드는 것을 넘어, 개발 문화 자체를 긍정적으로 변화시키는 강력한 도구입니다.

CI/CD 파이프라인의 지속적인 개선

여기서 멈추지 않고, 구축한 파이프라인을 더욱 고도화할 수 있습니다.

  • 테스트 확장: 현재는 npm test만 포함했지만, E2E 테스트 (예: Cypress, Playwright)를 추가하여 사용자 시나리오 기반의 테스트를 자동화할 수 있습니다.
  • 다중 환경 배포: 개발, 스테이징, 프로덕션 등 여러 환경에 따라 다른 S3 버킷이나 CloudFront 배포로 배포하도록 워크플로우를 확장할 수 있습니다. (예: if 조건문이나 다른 브랜치 트리거 사용)
  • 배포 알림: 배포 성공/실패 시 Slack, Teams, Discord 등으로 알림을 보내는 Action을 추가하여 팀원들에게 배포 상황을 실시간으로 공유할 수 있습니다.
  • 버전 관리: 배포되는 애플리케이션에 Git Commit Hash나 태그 정보를 포함하여 버전 관리를 용이하게 할 수 있습니다.
  • 성능 최적화: 빌드 캐싱, 압축 등 추가적인 최적화 단계를 포함하여 워크플로우 실행 시간을 단축할 수 있습니다.

이러한 심화 활용 방안들을 통해 여러분의 CI/CD 파이프라인은 더욱 견고하고 효율적으로 발전할 수 있습니다.


마무리하며

지금까지 GitHub Actions를 활용하여 React 애플리케이션 자동 배포 CI/CD 파이프라인을 구축하는 과정을 상세히 살펴보았습니다. 제가 직접 이 파이프라인을 도입하면서 느낀 점은, 초기 설정에 약간의 시간이 소요되지만 그 이후로는 개발팀의 생산성과 서비스 안정성에 엄청난 기여를 한다는 것입니다.

반복적이고 지루한 수동 배포 작업은 이제 과거의 일이 되었습니다. 자동화된 CI/CD를 통해 개발자들은 코드 작성과 문제 해결이라는 본연의 업무에 더욱 집중할 수 있게 되었고, 이는 결국 더 빠르고 안정적인 서비스 제공으로 이어집니다.

이 가이드가 React 애플리케이션 개발자분들이 CI/CD 자동화를 시작하는 데 도움이 되기를 바랍니다. 여러분의 프로젝트에도 GitHub Actions를 적용해 보세요. 분명 놀라운 변화를 경험하실 겁니다!

혹시 이 글을 읽고 직접 CI/CD 파이프라인을 구축해 보신 경험이 있으시다면, 어떤 점이 가장 좋았는지, 혹은 어떤 어려움을 겪으셨는지 댓글로 공유해 주시면 감사하겠습니다. 함께 더 나은 개발 문화를 만들어나가요!

📌 함께 읽으면 좋은 글

  • [생산성 자동화] 스크립트로 개발 프로젝트 관리 자동화: 효율적인 이슈 트래킹과 보고서 생성
  • [튜토리얼] gRPC 서비스 개발 환경 구축 및 클라이언트 연동 실전 가이드
  • [튜토리얼] Playwright를 활용한 웹 애플리케이션 E2E 테스트 환경 구축 및 실전 가이드

이 글이 도움이 되셨다면 공감(♥)댓글로 응원해 주세요!
궁금한 점이나 다루었으면 하는 주제가 있다면 댓글로 남겨주세요.

반응형