Study/Side Proejct / / 2025. 2. 28. 20:05

[Smart Ad] Google Cloud Platform 환경 구축 - 2편(CI/CD, 무중단 배포)

안녕하세요! [Smart Ad] 프로젝트의 Google Cloud Platform (GCP) 환경 구축 과정 두 번째 편입니다. 이번 포스팅에서는 Cloud Build를 사용하여 Cloud Run으로 자동 배포하는 과정과 무중단 배포가 어떻게 이루어지는지 자세히 설명하겠습니다.

🔄 왜 자동 배포인가?

수동 배포는 번거롭고 실수하기 쉽습니다. 특히, 코드가 빈번하게 변경되는 환경에서는 더욱 그렇습니다. 자동 배포는 이러한 문제를 해결하고 개발 효율성을 높여줍니다.

기존에는 코드작성 -> 이미지 빌드 -> 이미지 푸쉬 -> 기존 인스턴스 종료 -> 신규 인스턴스 생성을 반복해야 했고, 시간 또한 오래 걸렸습니다.  

  • 시간 절약: 코드 변경 후 수동으로 빌드, 배포하는 과정을 자동화하여 시간을 절약
  • 실수 방지: 사람의 개입을 최소화하여 휴먼 에러 제거
  • 빠른 피드백: 코드 변경 사항을 빠르게 배포하여 피드백

🚀 Cloud Build를 이용한 자동 배포

Cloud Build는 GCP에서 제공하는 CI/CD 서비스입니다. GitHub, GitLab, Bitbucket 등 다양한 소스 저장소와 연동하여 코드 변경을 감지하고 자동으로 빌드, 테스트, 배포를 수행이 가능합니다. 지금부터 간단한 방법으로 Cloud Build를 만드는 방법을 소개하겠습니다.

1. Cloud Build 트리거 설정

Cloud Build 트리거는 특정 이벤트(예: GitHub 저장소에 코드 푸시)가 발생했을 때 Cloud Build를 실행시키는 역할을 합니다.

  1. GCP Console에서 Cloud Build > 트리거 메뉴로 이동합니다.
  2. "트리거 만들기"를 클릭합니다.
  3. 다음 정보를 입력하고 "만들기"를 클릭합니다.
    • 이름: 트리거 이름 (예: trigger)
    • 이벤트: "저장소로 푸시" 선택
    • 저장소: GitHub 저장소 선택 (예: devMtn30/smart-ad-api)
    • 분기: ^master$ (master 브랜치에 푸시될 때 트리거)
    • 구성: "Cloud Build 구성 파일(yaml 또는 json)" 선택
    • Cloud Build 구성 파일 위치: cloudbuild.yaml 
    • 길지만, 구성에서 저장소와 브랜치만 선택하고 프로젝트 root에 cloudbuild를 생성하면 끝입니다.

2. cloudbuild.yaml 파일 작성

cloudbuild.yaml 파일은 Cloud Build가 수행할 작업을 정의하는 파일입니다.

serviceAccount: "cloudbuild-runner-sa@smart-ad-451409.iam.gserviceaccount.com"
options:
  logging: CLOUD_LOGGING_ONLY
steps:
# 1) Docker 이미지 빌드
- name: 'gcr.io/cloud-builders/docker'
  args: [
    'build',
    '-t', 'asia-northeast3-docker.pkg.dev/$PROJECT_ID/smart-ad-artifacts/smart-ad-api:$SHORT_SHA',
    '.'
  ]
# 2) Docker 이미지 푸시
- name: 'gcr.io/cloud-builders/docker'
  args: [
    'push',
    'asia-northeast3-docker.pkg.dev/$PROJECT_ID/smart-ad-artifacts/smart-ad-api:$SHORT_SHA'
  ]
# 3) Cloud Run 배포
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: 'gcloud'
  args: [
    'run', 'deploy', 'smart-ad-api',
    '--image=asia-northeast3-docker.pkg.dev/$PROJECT_ID/smart-ad-artifacts/smart-ad-api:$SHORT_SHA',
    '--region=asia-northeast3',
    '--platform=managed',
    '--set-secrets=DB_PASSWORD=projects/484753512912/secrets/DB_PASSWORD/versions/latest',
  ]
images:
- 'asia-northeast3-docker.pkg.dev/$PROJECT_ID/smart-ad-artifacts/smart-ad-api:$SHORT_SHA'
  • serviceAccount: Cloud Build가 사용할 서비스 계정입니다. 이 서비스 계정은 Artifact Registry에 이미지를 푸시하고, Cloud Run에 배포할 수 있는 권한을 가지고 있어야 합니다.
  • options: Cloud Build 로깅 옵션을 설정합니다. CLOUD_LOGGING_ONLY는 Cloud Logging에만 로그를 기록하도록 합니다. 해당 옵션을 안넣는 경우 Build 시 문제가 발생하였기에 필수로 넣는게 좋아 보입니다.
  • steps: Cloud Build가 수행할 단계를 정의할 수 있습니다. 저는 기존에 사용하던 명령어를 사용했습니다.
    • 1단계: Docker 이미지를 빌드합니다.
    • 2단계: 빌드된 이미지를 Artifact Registry에 푸시합니다.
    • 3단계: Cloud Run에 이미지를 배포합니다. --set-secrets 옵션을 사용하여 Secret Manager의 Secret을 환경 변수로 주입합니다.
  • images: 빌드된 이미지의 이름을 지정합니다.

3. Dockerfile 수정 (권한 문제 해결)

Cloud Build 실행 중 gradlew 실행 권한 문제(Permission denied)가 발생할 수 있습니다. 이는 Dockerfile에서 gradlew 파일에 실행 권한을 부여하지 않았기 때문입니다.

gradlew 빌드 과정에서 Permission 문제 발생

다음과 같이 Dockerfile을 수정하여 문제를 해결합니다.

FROM amazoncorretto:17-alpine AS build
WORKDIR /app
# gradlew만 먼저 복사해서 실행 권한 부여
COPY gradlew /app/gradlew
RUN chmod +x /app/gradlew
# 나머지 프로젝트 파일 복사
COPY . /app
# Gradle 빌드
RUN ./gradlew bootJar

FROM amazoncorretto:17-alpine
WORKDIR /app
COPY --from=build /app/build/libs/api-0.0.1-SNAPSHOT.jar ./
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "api-0.0.1-SNAPSHOT.jar"]

COPY gradlew /app/gradlewRUN chmod +x /app/gradlew 를 추가하여 gradlew 파일에 실행 권한을 부여합니다.

✨ Cloud Run 무중단 배포

Cloud Run은 새로운 버전의 코드를 배포할 때 무중단 배포(Zero-downtime deployment) 를 지원합니다. 이는 새로운 리비전(Revision)이 생성되고, 이전 리비전에서 새 리비전으로 트래픽이 점진적으로 전환되는 방식으로 이루어집니다.

  • 새 리비전 생성: Cloud Run에 코드를 새로 배포하면 새로운 리비전이 생성됩니다.
  • 트래픽 전환: 새 리비전이 준비될 때까지는 이전 리비전이 계속 트래픽을 처리합니다. 새 리비전이 정상적으로 기동되면, 그 시점에 트래픽을 새 리비전으로 전환합니다. (True Rolling Update)
  • 롤백: 새 리비전에 문제가 발생하면 이전 리비전으로 즉시 롤백할 수 있습니다.

이러한 과정을 통해 사용자는 서비스 중단 없이 새로운 기능을 이용할 수 있습니다. 즉, Cloud Run에 코드를 배포하면 알아서 새 버전으로 리비전되어 거의 제로에 가까운 다운 타임이 가능합니다. 

하지만 완전히 제로는 아니기에 실제로는 콜드 스타트(Cold Start) 문제가 발생할 여지가 있습니다.

이걸 해결하려면 빌드 과정에서 웜업(Pre-Warming)과 같은 적절한 조치가 필요할 것 같습니다.

📌 정리

이번 포스팅에서는 Cloud Build를 사용하여 Cloud Run으로 자동 배포하는 과정과 Cloud Run의 무중단 배포 기능에 대해 알아보았습니다. 자동 배포는 개발 생산성을 향상시키고, 무중단 배포는 서비스 안정성을 높이는 데 중요한 역할을 합니다.

다음 편에서는, 시장 조사를 통해 사용자의 반응을 보기 위해 Kotlin 학습을 진행하도록 하겠습니다.

API 서버와 FE 개발이 끝난 뒤 Cloud Tasks, VPC, Cloud NAT 등 나머지 구성 요소에 알아보도록 하겠습니다.