← 통합 포탈 서비스

07 / 09

CI/CD & 배포

Jenkins 기반 프론트엔드 CI/CD, monorepo npm workspace 빌드, S3 sync 배포, CloudFront Invalidation

JenkinsS3CloudFrontnpm workspace
개요 & 아키텍처전체 아키텍처 / DR 대비보안 관련 요소비용 관련 요소성능 관련 요소DNS & 도메인CI/CD & 배포데이터베이스운영 모니터링

CI/CD 전환 배경

통합 포탈 서비스는 기존 백엔드(auth) 서비스용 Jenkins 파이프라인을 기반으로 프론트엔드 배포 파이프라인을 새로 구성하였습니다. auth는 백엔드에서, 통합 포탈 서비스는 프론트엔드에서 사용하는 구조이기 때문에 기존 파이프라인의 Docker/ECR/ECS 관련 스텝을 제거하고, S3 + CloudFront 기반 정적 배포로 전환하였습니다.

기존 파이프라인 (백엔드)

×

Docker build / run

×

컨테이너 포트 3000 설정

×

PROD ECR 이미지 Push

×

ECS 서비스 업데이트

전환된 파이프라인 (프론트엔드)

npm workspace 기반 React 빌드

S3 sync --delete 배포

CloudFront Invalidation

환경별 (dev/prod) 분기

기존 파이프라인에서 제거/변경된 포인트

기존 Jenkins 파이프라인은 백엔드 서비스(auth) 배포를 위해 Docker 빌드 → ECR Push → ECS 업데이트 흐름으로 구성되어 있었습니다. 포탈 서비스는 프론트엔드 SPA이므로 이 흐름이 불필요하며, 배포 핵심이 S3 sync + CloudFront Invalidation으로 변경됩니다.

기존 스텝변경 사항사유
Docker build / run제거프론트엔드는 정적 빌드 산출물만 필요
컨테이너 포트 3000 설정제거컨테이너 실행 불필요
ECR 이미지 Push제거Docker 이미지 불필요
ECS 서비스 업데이트제거백엔드 전용 스텝
빌드 산출물 처리S3 sync로 변경정적 파일을 S3에 직접 배포
배포 후 반영CloudFront Invalidation 추가CDN 캐시 갱신 필요

프론트엔드 CI/CD 파이프라인 구조

monorepo 구조 + npm workspace를 사용하며, @connect-portal/react 패키지의 빌드 산출물(packages/react/dist)을 S3에 배포합니다.

배포 흐름

ENV 선택React 빌드S3 syncCF Invalidation
01

ENV (dev/prod) 선택

Jenkins 파라미터로 배포 대상 환경을 선택합니다. 환경에 따라 S3 버킷과 CloudFront Distribution ID가 분기됩니다.

02

선택한 환경에 맞게 React 빌드

npm workspace 기반으로 @connect-portal/react 패키지만 빌드합니다. 환경별 .env 파일이 적용되어 API 엔드포인트 등이 분기됩니다.

03

S3 sync --delete 배포

빌드 산출물(packages/react/dist)을 대상 S3 버킷에 동기화합니다. --delete 옵션으로 이전 버전의 불필요한 파일을 자동 정리합니다.

04

CloudFront Invalidation

배포 완료 후 CloudFront 캐시를 무효화하여 사용자에게 즉시 최신 버전이 제공되도록 합니다.

Jenkinsfile 핵심 구조

전제: monorepo 구조 + npm workspace 사용. 빌드 대상은 @connect-portal/react 패키지이며, 산출물은 packages/react/dist 디렉토리입니다.

pipeline {
  agent any
  parameters {
    choice(name: 'ENV', choices: ['dev', 'prod'],
           description: '배포 환경 선택')
  }
  environment {
    S3_BUCKET_DEV  = 'connect-portal-dev'
    S3_BUCKET_PROD = 'connect-portal-prod'
    CF_DIST_DEV    = 'EXXXXXXXXXXXDEV'
    CF_DIST_PROD   = 'EXXXXXXXXXXXPROD'
  }
  stages {
    stage('Install') {
      steps { sh 'npm ci' }
    }
    stage('Build') {
      steps {
        sh "npm run build -w @connect-portal/react"
      }
    }
    stage('Deploy to S3') {
      steps {
        script {
          def bucket = params.ENV == 'prod'
            ? env.S3_BUCKET_PROD : env.S3_BUCKET_DEV
          sh """
            aws s3 sync packages/react/dist \
              s3://${bucket} --delete
          """
        }
      }
    }
    stage('CloudFront Invalidation') {
      steps {
        script {
          def distId = params.ENV == 'prod'
            ? env.CF_DIST_PROD : env.CF_DIST_DEV
          sh """
            aws cloudfront create-invalidation \
              --distribution-id ${distId} \
              --paths "/*"
          """
        }
      }
    }
  }
}

dev 브랜치 전용 배포 파이프라인

dev 환경은 별도의 파이프라인으로 분리하여, dev 브랜치에 push 시 자동으로 빌드 및 배포가 수행되도록 구성하였습니다. prod 배포는 수동 트리거(Jenkins 파라미터 선택)로만 실행됩니다.

dev 환경

• dev 브랜치 push 시 자동 트리거

• dev S3 버킷 + dev CloudFront 배포

• 빠른 피드백 루프

prod 환경

• 수동 트리거 (Jenkins 파라미터)

• prod S3 버킷 + prod CloudFront 배포

• 배포 전 확인 절차

배포 후 Smoke Test (보류)

배포 후 자동 smoke test 단계를 추가하여 주요 페이지 접근 가능 여부, API 연동 상태 등을 검증하는 방안을 검토 중입니다. 현재는 수동 확인으로 대체하고 있으며, 향후 자동화 예정입니다.

Summary

통합 포탈 서비스의 CI/CD는 기존 백엔드 파이프라인에서 Docker/ECR/ECS 관련 스텝을 제거하고, monorepo + npm workspace 기반 React 빌드 → S3 sync → CloudFront Invalidation으로 전환하였습니다. 환경별 분기(dev/prod)를 통해 안전한 배포 흐름을 확보하였으며, dev 브랜치는 자동 배포, prod는 수동 트리거로 운영합니다.

DNS & 도메인데이터베이스