기술

GitLab CI/CD로 main → dev 브랜치 자동 역방향 머지(Merge-Back) 구현하기

스타스토리. 2025. 6. 23. 23:06
반응형
핵심 요약: 본 문서는 GitLab CI/CD를 활용하여 `main` 브랜치에 변경 사항이 머지될 때, 해당 내용이 `dev` 브랜치로 자동으로 역방향 머지(Merge-Back)되는 파이프라인을 구축하는 방법을 설명한다. 이 자동화를 통해 브랜치 간의 정합성을 유지하고, 수동 작업으로 인한 실수를 줄여 개발 워크플로우를 크게 개선할 수 있다.

많은 개발팀이 Git-Flow와 같은 브랜치 전략을 사용한다. `feature` 브랜치에서 개발한 기능이 `dev`를 거쳐 최종적으로 `main`(또는 `master`) 브랜치에 반영되는 흐름이다. 하지만 운영 중에 발생하는 긴급한 핫픽스(Hotfix)는 `main` 브랜치에 직접 적용되는 경우가 많다. 이 경우, `main` 브랜치의 최신 코드가 `dev` 브랜치에 누락되어 브랜치 간의 코드 불일치가 발생하게 된다. 이러한 문제를 해결하기 위해 도입할 수 있는 것이 바로 '자동 역방향 머지' 파이프라인이다.

1. 자동 머지가 필요한 이유: 브랜치 정합성 유지

개발 프로세스에서 `dev` 브랜치는 다음 릴리즈를 위한 기능들이 통합되는 중심 브랜치 역할을 한다. 만약 `main` 브랜치에 적용된 핫픽스가 `dev`에 즉시 반영되지 않으면, 다음 배포 시점에 충돌이 발생하거나 중요한 수정 사항이 누락될 위험이 있다. 개발자가 수동으로 이 과정을 챙기는 것은 번거롭고 실수가 발생하기 쉽다.

따라서 `main` 브랜치로의 푸시(Push) 이벤트를 감지하여 자동으로 `dev` 브랜치에 머지하는 CI/CD 파이프라인을 구축하면, 다음과 같은 이점을 얻을 수 있다.

  • 일관성 확보: `dev` 브랜치가 항상 `main` 브랜치의 최신 상태를 유지한다.
  • 인적 오류 감소: 개발자가 역방향 머지를 잊어버리는 실수를 원천적으로 방지한다.
  • 개발 경험 향상: 단순 반복적인 작업을 자동화하여 개발자가 핵심 기능 개발에 더 집중할 수 있도록 돕는다.

2. GitLab CI/CD 파이프라인 스크립트 전문

아래는 `main`에서 `dev`로의 자동 머지를 수행하는 .gitlab-ci.yml 파일의 전체 내용이다.

merge-back-to-dev:
  stage: merge-back
  image: alpine:latest
  before_script:
    - apk add --no-cache git curl jq
    - git --version
    - git config --global user.email "XXXXXX@gmail.com"
    - git config --global user.name "xxx"
    - git config --global init.defaultBranch main
    - git remote set-url origin https://oauth2:${GITLAB_API_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git
  script:
    - echo "Starting auto merge process..."
    - git fetch origin
    - echo "Available branches:"
    - git branch -r
    - echo "Checking out dev branch..."
    - git checkout dev
    - echo "Current branch:"
    - git branch --show-current
    - echo "Merging main into dev..."
    - git merge origin/main --no-ff -m "Auto merge from main to dev [skip ci]"
    - echo "Pushing to dev branch..."
    - git push origin dev
    - echo "Successfully merged main to dev"
  rules:
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"'
  allow_failure: true

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "web"
      when: always
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
      when: always
    - when: never

3. 스크립트 상세 분석

3.1. 실행 환경 준비 (`before_script`)

스크립트의 핵심 로직이 실행되기 전, 필요한 환경을 설정하는 단계이다.

  • `apk add ...`: 경량화된 `alpine` 이미지 위에서 `git`, `curl`, `jq` 등 필요한 패키지를 설치한다.
  • `git config ...`: 자동 머지 시 생성될 커밋(commit)의 작성자 정보를 설정한다. 이 정보가 없으면 git 작업이 실패할 수 있다.
  • `git remote set-url ...`: CI/CD 파이프라인이 원격 저장소에 `push` 할 수 있도록 인증 정보를 설정하는 가장 중요한 부분이다.
🧐 인증 토큰 설정 (`GITLAB_API_TOKEN`)
${GITLAB_API_TOKEN}은 GitLab CI/CD 설정의 'Settings > CI/CD > Variables'에서 미리 정의해야 하는 변수이다. 'Project Access Token'을 생성하여 `api`, `write_repository` 권한을 부여한 후, 해당 토큰 값을 변수로 등록해야 한다. 스크립트에 토큰을 직접 하드코딩하지 않고 변수를 사용하는 것은 보안상 매우 중요한 원칙이다.

3.2. 핵심 머지 로직 (`script`)

실제 자동 머지가 일어나는 단계로, 각 명령어는 다음과 같은 역할을 수행한다.

  • `git fetch origin`: 원격 저장소의 최신 정보를 가져온다.
  • `git checkout dev`: 머지의 대상이 될 `dev` 브랜치로 이동한다.
  • `git merge origin/main ...`: `main` 브랜치의 내용을 현재 브랜치(`dev`)로 머지한다.
📌 권장 사항: 머지 옵션의 이해
  • --no-ff: 'No Fast-forward'의 약자로, 머지 히스토리를 명확하게 남기기 위해 항상 새로운 머지 커밋을 생성하는 옵션이다. 이를 통해 "언제 `main`의 내용이 `dev`로 자동 병합되었는지"를 히스토리에서 명확히 추적할 수 있다.
  • [skip ci]: 커밋 메시지에 이 문자열을 포함하면, 이 커밋으로 인한 `push` 이벤트가 또 다른 CI/CD 파이프라인을 트리거하지 않도록 방지한다. 이것이 없으면 자동 머지가 또 다른 자동 머지를 호출하는 무한 루프에 빠질 수 있으므로 반드시 필요하다.
  • `git push origin dev`: 로컬에서 머지된 `dev` 브랜치를 원격 저장소로 `push`하여 최종적으로 반영한다.

3.3. 실행 규칙 정의 (`rules` 및 `workflow`)

이 파이프라인이 언제, 어떤 조건에서 실행될지를 정의한다.

  • `rules`: `merge-back-to-dev` 잡(job)은 오직 `main` 브랜치에 `push` 이벤트가 발생했을 경우에만 실행된다.
  • `workflow`: 프로젝트 전체의 파이프라인 실행 규칙을 정의한다. 웹 UI에서 수동으로 실행하거나, `main` 브랜치에 푸시될 때만 파이프라인이 생성되도록 제한하여 불필요한 리소스 낭비를 막는다.
  • `allow_failure: true`: 이 잡이 실패하더라도 전체 파이프라인의 최종 상태를 '실패'로 만들지 않는다. 자동 머지는 핵심 배포 프로세스가 아니므로, 실패 시 알림을 받되 전체 배포를 막지 않도록 설정하는 것이 일반적이다.

결론

단순해 보이는 이 자동화 스크립트 하나가 팀의 개발 문화를 크게 향상시킬 수 있다. 개발자는 더 이상 브랜치 간 동기화라는 부수적인 작업에 신경 쓰지 않아도 되며, 저장소는 항상 최상의 정합성을 유지하게 된다. GitLab CI/CD가 제공하는 강력한 자동화 기능을 활용하여, 반복적인 작업을 시스템에 맡기고 보다 창의적인 문제 해결에 집중하는 효율적인 개발 환경을 구축해 보길 바란다.

반응형