Heroku 애플리케이션을 GitLab CI/CD로 스테이징 및 프로덕션 환경에 배포하기

이전 기사에서는 GitLab CI/CD를 사용하여 Heroku에 자동으로 배포하는 방법을 탐구했습니다. 그 설정은 우리가 main 브랜치에 코드를 푸시할 때마다 앱을 프로덕션 환경으로 배포했습니다.

이 기사에서는 약간 더 복잡한 접근 방식을 고려해 보겠습니다: 여러 환경이 있는 경우는 어떨까요? 대부분의 엔지니어링 조직은 적어도 세 가지 환경을 사용합니다: 로컬 개발 환경, 스테이징 환경, 그리고 프로덕션 환경.

또한, 일부 엔지니어링 팀은 Gitflow 브랜칭 전략을 따르며, dev 브랜치와 main 브랜치를 가지고 있습니다. 이 전략은 이제 인기가 사라지고 트렁크 베이스 개발로 대체되었지만, 여전히 이러한 관행을 따르는 조직을 찾아볼 수 있습니다.

오늘 우리는 dev 브랜치에 push할 때 스테이징 환경으로 우리 앱을 배포하고, main 브랜치에 push할 때 프로덕션 환경으로 우리 앱을 배포하는 GitLab CI/CD를 설정하는 방법을 살펴보겠습니다.

시작하기

시작하기 전에 우리는 두 가지 필요합니다: Heroku 계정과 GitLab 계정.

Heroku는 앱을 호스팅하고 배포하는 데 매우 좋은 장소입니다. 플랫폼 어썸 서비스(PaaS)로서 Heroku는 많은 인프라 복잡성을 추상화하여 재미있는 것을 만드는 데 집중할 수 있게 해줍니다. 여기서 Heroku 계정을 생성할 수 있습니다.

GitLab는 코드를 저장하는 데 매우 좋은 장소입니다. 단순한 소스 코드 관리 도구를 넘어, GitLab는 내장된 CI/CD 기능을 제공하여 다른 세 번째 당사 도구가 필요 없이 테스트하고 코드를 배포할 수 있는 파이프라인을 설정할 수 있습니다. 여기서 GitLab 계정을 생성할 수 있습니다.

이 기사에서 보여드리는 데모 앱은 GitLab과 Heroku를 모두 사용합니다. 모든 코드를 GitLab 레포에서 찾을 수 있습니다.

로컬에서 앱 실행

로컬에서 앱을 실행하려면 리포지토리를 클론하고 의존성을 설치한 후 시작 명령어를 실행하세요. 터미널에서 다음을 수행하세요:

$ git clone https://gitlab.com/tylerhawkins1/heroku-gitflow-staging-production-gitlab-cicd-demo.git
$ cd heroku-gitflow-staging-production-gitlab-cicd-demo
$ npm install
$ npm start

앱을 시작한 후, 브라우저에서 이 로컬 호스트를 방문하면 로컬에서 실행 중인 앱을 볼 수 있습니다:

데모 헤로枯 앱

우리 앱을 헤로枯에 배포

이제 앱이 로컬에서 실행 중이므로, 어디서든 액세스할 수 있도록 헤로枯에 배포해 보겠습니다.

우리는 앱을 스테이징 환경과 프로덕션 환경 모두에 배포할 것을 기억하세요. 이는 동일한 GitLab 리포지토리를 기반으로 두 개의 헤로枯 앱이 만들어진다는 뜻입니다.

이미 헤로枯 CLI가 설치되어 있지 않다면, 진행하기 전에 설치해야 합니다.

헤로枯 CLI를 설치한 후, 터미널에서 다음 명령어를 실행하여 main 브랜치를 체크아웃하고 새로운 프로덕션 헤로枯 앱을 생성하고 프로덕션 환경에 배포한 후 브라우저에서 열기:

$ git checkout main
$ heroku create heroku-gitlab-ci-cd-production --remote heroku-production
$ git push heroku-production main
$ heroku open --remote heroku-production

이제 헤로枯 URL에서 실행 중인 동일한 앱을 볼 수 있어야 합니다. 잘 했어요 — 헤로枯 앱을 프로덕션에 배포했습니다!

하지만 아직 끝이 아닙니다. 스테이징 앱을 구성하고 배포해야 합니다. 이를 위해 아래와 같은 유사한 명령어를 실행하세요:

$ git checkout dev
$ heroku create heroku-gitlab-ci-cd-staging --remote heroku-staging
$ git push heroku-staging main
$ heroku open --remote heroku-staging

이제 다시 같은 앱을 배포할 것입니다, 하지만 이번에는 스테이징 환경으로 사용할 다른 URL로 배포합니다. 이제 생산 환경과 스테이징 환경 모두 설정이 완료되었습니다!

생산 앱과 스테이징 앱을 위한 명령어의 차이점과 유사성을 주의해 보세요:

  1. 생산 앱은 main 브랜치를 사용하며, 스테이징 앱은 dev 브랜치를 사용합니다.
  2. 생산 앱은 heroku-gitlab-ci-cd-production라고 불리며, 스테이징 앱은 heroku-gitlab-ci-cd-staging라고 불립니다.
  3. 생산 앱의 git 리모트는 heroku-production라고 불리며, 스테이징 앱의 git 리모트는 heroku-staging라고 불립니다.
  4. 생산 앱과 스테이징 앱의 git 리모트는 모두 main 브랜치를 사용합니다. 그 이유는 허루는 코드가 메인 브랜치로 푸시될 때만 앱을 배포하기 때문입니다.

이 점을 기억하세요: main 브랜치는 당신의 maindev 브랜치와는 다릅니다. 여기 푸시하는 main 브랜치는 당신의 git 리모트 — 이 경우 허루 — 의 main 브랜치입니다.

당신이 로컬 main 브랜치에서 git push heroku-production main 명령을 실행할 때, 당신은 Heroku 프로덕션 앱의 main 브랜치로 로컬 main 브랜치를 푸시하고 있습니다. 또한, 로컬 dev 브랜치에서 git push heroku-staging main 명령을 실행할 때, 당신은 Heroku 스테이징 앱의 main 브랜치로 로컬 dev 브랜치를 푸시하고 있습니다.

우리 앱에 변경을加える

이제 Heroku 앱이 실행 중이니, 변경을 하고 싶다면 어떻게 하나요? Gitflow 브랜칭 전략의 대략적인 근사치를 따르면 다음과 같이 할 수 있습니다:

  1. dev 브랜치를 체크아웃
  2. 코드에 변경을加える
  3. 변경을 추가하고 커밋하고 dev 브랜치로 푸시
  4. 스테이징 Heroku 앱에 변경을 배포하기 위해 git push heroku-staging main 명령을 실행
  5. main 브랜치를 체크아웃
  6. dev 브랜치를 main 브랜치로 머지
  7. 프로덕션 Heroku 앱에 변경을 배포하기 위해 git push heroku-production main 명령을 실행

(진정으로 Gitflow를 따르면 기능 브랜치를 만들어 dev 브랜치로 머지하고, 릴리스 브랜치를 만들어 main 브랜치로 머지했을 것입니다. 하지만 단순하게 유지하기 위해 이 단계들을 생략했습니다.)

이제, 두 환경 중 어느 환경으로 배포를 자동화할 수 있다면 항상 수동으로 배포할 필요 없이 좋지 않을까요?

이때 GitLab CI/CD가 등장합니다.

지속적 통합/지속적 배포

지속적 통합(CI)은 자주 커밋하고 언제나 빌드를 좋은 상태로 유지하는 것에 관한 것입니다. 일반적으로 빌드가 좋은 상태인지 확인하기 위해 CI 파이프라인에서 검사를 수행합니다. 이 검사는 라인트 checking, 단위 테스트, 그리고/또는 엔드 투 엔드 테스트를 포함할 수 있습니다.

지속적 배포(CD)는 자주 배포하는 것에 관한 것입니다. CI 파이프라인의 검사가 통과하면 빌드가 배포됩니다. CI 파이프라인의 검사가 실패하면 빌드는 배포되지 않습니다.

GitLab CI/CD를 사용하면 이와 정확히 같은 작업을 수행할 수 있습니다 — 테스트를 실행한 후 모든 테스트가 통과하면 우리의 앱을 Heroku에 배포합니다. 우리의 설정에 가장 중요한 점은 CI 파이프라인 내에서 앱이 배포되어야 할 위치를 지정할 수 있는 규칙을 설정할 수 있다는 것입니다.

GitLab CI/CD 설정

GitLab에서 CI 파이프라인을 프로그래밍적으로 생성하려면 .gitlab-ci.yml 파일을 사용할 수 있습니다. 우리의 파일은 다음과 같습니다:

YAML

 

image: node:20.10.0

cache:
  paths:
    - node_modules/

before_script:
  - node -v
  - npm install

stages:
  - test
  - deploy

unit-test-job:
  stage: test
  script:
    - npm test

deploy-job:
  stage: deploy
  variables:
    HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
      variables:
        HEROKU_APP_NAME: $HEROKU_APP_NAME_PRODUCTION
    - if: $CI_COMMIT_REF_NAME =~ /dev/
      variables:
        HEROKU_APP_NAME: $HEROKU_APP_NAME_STAGING
  script:
    - apt-get update -yq
    - apt-get install -y ruby-dev
    - gem install dpl
    - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY

GitLab CI 파이프라인은 단계와 작업으로 구성됩니다. 각 단계는 하나 이상의 작업을 포함할 수 있습니다. 우리의 파이프라인에서는 두 단계: testdeploy가 있습니다. test 단계에서는 unit-test-job에서 단위 테스트를 실행합니다. deploy 단계에서는 deploy-job에서 앱을 Heroku에 배포합니다.

이전 단계의 모든 작업이 통과해야만 다음 단계로 진행할 수 있습니다. 즉, 단위 테스트가 실패하면 앱이 배포되지 않습니다. 이는 좋은 일입니다! 앱이 좋지 않은 상태에서 배포되는 것을 원치 않습니다.

Deploy 단계에서는 rules 섹션에 일부 조건부 논리가 구현되어 있습니다. 이 부분에서 우리의 앱을 어떤 환경에 배포할지 지정합니다. main 브랜치에 있으면 생산 환경 앱을 배포하며, dev 브랜치에 있으면 스테이징 앱을 배포합니다.또한 deploy 단계는 $HEROKU_APP_NAME_PRODUCTION, $HEROKU_APP_NAME_STAGING, $HEROKU_API_KEY라는 여러 가지 변수를 참조하고 있습니다. 이러한 변수들은

GitLab 내의 CI/CD 변수로 저장됩니다.

Heroku API key

자신의 GitLab 계정에서 이를 설정하려면, 먼저 Heroku 계정에서 API 키를 찾아야 합니다. Heroku 계정 설정 내에 API 키 섹션이 보이는 곳에서, API 키를 생성하지 않았다면 지금 생성하십시오.다음으로 GitLab 프로젝트에서 Settings > CI/CD > Variables을 클릭합니다. 이 섹션을 확장하고 세 가지 새로운 변수를 추가합니다:

  1. $HEROKU_API_KEY의 값은 Heroku 계정에서 가져온 API 키입니다.
  2. $HEROKU_APP_NAME_PRODUCTION의 값은 생산 환경 Heroku 앱의 이름입니다. 제 생산 앱의 이름은 heroku-gitlab-ci-cd-production이지만, Heroku 앱 이름은 전 세계적으로 고유하기 때문에, 여러분의 이름은 다를 것입니다.
GitLab CI/CD variables

$HEROKU_APP_NAME_STAGING의 값은 스테이징 Heroku 앱의 이름이 됩니다. 제 스테이징 앱의 이름은 ‘heroku-gitlab-ci-cd-staging’입니다. 다시 한 번 말하지만, Heroku 앱 이름은 전 세계적으로 고유해야 하므로, 당신의 이름은 다를 것입니다.

이제 GitLab CI 파이프라인은 준비가 되었습니다! 테스트해 보겠습니다.

스테이징 환경으로 Heroku 앱을 배포해 보겠습니다.

이제 ‘dev‘ 브랜치를 확인하고 앱의 코드에 변경을加하겠습니다. 저는 헤딩 텍스트를 간단히 변경하고 UI 텍스트에 몇 개의 새로운 줄을 추가했습니다. 당신도 코드에서 비슷한 변경을 할 수 있습니다.

GitLab CI pipeline build for the dev branch

이제 변경을 추가하고, 커밋하고 ‘dev‘ 브랜치로 푸시하여 GitLab CI 파이프라인을 시작합니다. GitLab 내에서 파이프라인을 확인하고 실시간으로 진행 상황을 볼 수 있습니다.

Demo Heroku app with updated copy

모든 것이 잘되면, ‘test‘와 ‘deploy‘ 단계가 통과되었음을 볼 수 있습니다. 이제 스테이징 환경 URL에서 호스팅된 Heroku 앱을 확인해 보세요. GitLab CI 파이프라인이 앱을 배포해 주므로, 스테이징 환경에서 변경 사항이 실제로 적용된 것을 볼 수 있습니다!

이제 생산 환경 앱 URL을 확인해 보세요. 여전히 최근 변경 사항이 없는 이전 UI가 표시되는 것을 알 수 있습니다. 이는 GitLab CI 파이프라인이 변경 사항을 스테이징 환경에만 배포했기 때문입니다. 생산 환경에는 배포되지 않았습니다.

우리의 스테이징 환경에서 코드가 잘 작동하는 것을 확인했습니다. 이제 생산 환경으로 이동시키겠습니다.

Our Heroku App를 생산 환경에 배포하다

먼저 main 브랜치를 확인한 후 dev 브랜치를 main 브랜치로 병합해 보겠습니다. 이 작업은 풀 리퀘스트를 통해 veya git merge dev 명령어를 실행한 후 git push 명령어를 통해 수행할 수 있습니다.

이로 인해 GitLab CI 파이프라인이 다시 시작되며, 이번에는 생산 앱 배포를 준비합니다.

GitLab CI pipeline build for the main branch

GitLab의 파이프라인 페이지에서 모든 파이프라인 실행을 확인할 수 있어 devmain 브랜치의 다양한 빌드를 볼 수 있습니다:

All GitLab CI pipeline builds

파이프라인이 완료되면, 생산 환경의 Heroku 앱 URL을 방문하여 변경 사항이 생산 환경에 배포되었는지 확인해 보세요. 훌륭한 작업입니다!

결론

A good CI pipeline allows you to ship new features quickly and confidently without manually managing the deployment process. Having multiple environments configured for local development, staging, and production gives you more control over where and when code is released.

Heroku와 GitLab CI/CD를 사용하면 이 모든 과정을 자동화하여 DevOps 프로세스를 쉽게 만들 수 있습니다!

Source:
https://dzone.com/articles/deploying-heroku-apps-to-staging-and-production