IaC/CI CD Tool

대형 Git 리포지터리에서 CI/CD 시간을 절반으로 줄이는 법: Git Sparse Checkout 실전 적용기

Somaz 2025. 6. 9. 12:55
728x90
반응형

Overview

대규모 Git 리포지터리를 다루는 개발자라면 누구나 겪는 공통적인 문제 중 하나는 느린 git clone 속도와 불필요한 데이터 다운로드이다.
특히 GitLab CI/CD 환경에서는 매번 새로운 환경에서 작업이 시작되기 때문에, 전체 프로젝트를 모두 clone하는 과정 자체가 병목이 되곤 한다.

 

이 글에서는 Git의 `sparse-checkout` 과 `--filter=blob:limit` 기능을 활용해,
필요한 폴더만 빠르게 clone하고 불필요한 파일 다운로드를 최소화하는 방법을 소개한다.


GitLab CI/CD 환경에서 직접 적용한 실전 YAML 예시도 함께 제공하니, 대용량 프로젝트를 운영 중인 팀이라면 반드시 참고해볼 만한 내용이다.

 

 

 

 

 


 

 

1. 문제 상황

CI/CD 파이프라인을 구성할 때, 리포지터리 용량이 크면 단순한 `git clone` 만으로 수 분~수십 분이 소요된다.
특히 바이너리 리소스, 이미지, AI 모델 등이 많은 프로젝트는 빌드보다 clone 시간이 더 오래 걸리는 경우도 있다.

 

 

 

 

2. 기존 접근 방식의 한계

  • `GIT_DEPTH=1` 을 써서 `shallow clone` 을 하더라도 전체 디렉터리를 clone한다.
  • 필요 없는 폴더, 수천 개의 파일을 받아야 하니 시간 낭비가 심하다.

 

 

 

3. 해결 전략: Sparse Checkout + Blob 제한

Git은 v2.25부터 `--sparse` + `--filter=blob:limit=N` 기능을 지원한다.
이를 통해 특정 폴더만 clone하고, N바이트 이하의 blob만 다운로드할 수 있다.

 
git clone --filter=blob:limit=1k --sparse <repo_url>
cd repo
git sparse-checkout init --cone
git sparse-checkout set Assets/Data
  • 이렇게 하면 Git은 실제 필요한 폴더만 받아오고, 거대한 리포지터리 전체를 clone하지 않아도 된다.

 

 

 

4. GitLab CI/CD 적용 예시

script:
  - git clone --filter=blob:limit=1k --sparse http://user:token@gitlab.example.com/myproject.git repo
  - cd repo
  - git sparse-checkout init --cone
  - git sparse-checkout set Assets/Data

 

 

 

 

5. 성능 비교

항목 기존 방식 (full clone) 개선 후 (sparse)
clone 시간 약 5분 약 15초
디스크 사용량 1.2GB 12MB
네트워크 트래픽 수백 MB 수십 KB

체감 속도 10배 이상 개선

 

 

 

 

 

Sparse Checkout 실전 팁

아래 명령어는 리포지터리 `clone` 없이도 `sparse-checkout` 을 테스트하거나,
원하는 디렉토리만 정확히 지정할 수 있게 도와준다.

 

 

 

사용 가능한 `sparse-checkout` 디렉토리 목록 확인

git ls-tree -d HEAD

 

clone 없이 sparse 적용 테스트

git init test && cd test
git remote add origin <your-repo-url>
git sparse-checkout init --cone
git sparse-checkout set some/folder
git pull origin master
  • 이 방법을 통해 선택한 폴더만 clone 되는지 사전에 검증할 수 있다.
  • CI/CD에 적용하기 전에 테스트하는 데 매우 유용하다.

 

 

 

gitlab-ci.yml 예시

stages:
  - update_cs

variables:
  STATIC_DATA_PROJECT_ID: $project_id
  GENERATE_JOB_ID: $job_id
  CHANGED_CS: $changed_cs
  GIT_STRATEGY: none

update_cs:
  stage: update_cs
  image: harbor.somaz.link/library/alpine:latest
  interruptible: false
  retry:
    max: 1
    when:
      - runner_system_failure
      - unknown_failure
      - data_integrity_failure
    exit_codes:
      - 137
  tags:
    - build-image
  before_script:
    - echo [INFO] STATIC_DATA_PROJECT_ID is $STATIC_DATA_PROJECT_ID
    - echo [INFO] GENERATE_JOB_ID is $GENERATE_JOB_ID
    - echo [INFO] CHANGED_CS is $CHANGED_CS
    - apk update && apk add --no-cache unzip git curl
  script:
    # 1. 아티팩트 다운로드
    - 'curl --location --output artifacts.zip --header "PRIVATE-TOKEN: ${CICD_ACCESS_TOKEN}" "http://gitlab.somaz.link/api/v4/projects/${STATIC_DATA_PROJECT_ID}/jobs/${GENERATE_JOB_ID}/artifacts"'
    - unzip -o artifacts.zip
    
    # 2. Git 설정
    - git config --global user.email "cicd@somaz.link"
    - git config --global user.name "cicd"
    
    # 3. 저장소 clone
    - git clone --filter=blob:limit=1k --sparse http://cicd:${CICD_ACCESS_TOKEN}@gitlab.somaz.link/game/somaz-project.git repo
    - cd repo
    - git sparse-checkout init --cone
    - git sparse-checkout set Assets/Data
    
    # 4. CS 파일 복사 및 커밋
    - |
      echo "$CHANGED_CS" | while read -r file; do
        if [ ! -z "$file" ]; then
          echo "Copying cs/${file}.cs to Assets/Data/"
          cp ../cs/${file}.cs Assets/Data/
        fi
      done
    
    # 5. 변경사항 확인 및 푸시
    - |
      if [ -n "$(git status --porcelain)" ]; then
        git add Assets/Data/
        git commit -m "feat(data): update ${CHANGED_CS} data mediator [skip ci]"
        git push origin master
      else
        echo "No changes detected"
      fi
  rules:
    - if: '$CI_PIPELINE_SOURCE == "trigger"'

 

 

 

GitLab에서 CI 실행을 생략하는 두 가지 방법

CI/CD 실행이 필요 없는 단순 커밋일 경우, 아래 방법 중 하나로 파이프라인 실행을 건너뛸 수 있다

 

 

 

 

`[skip ci]` 방식
커밋 메시지에 [skip ci] 또는 [ci skip]를 포함하면 GitLab 뿐만 아니라 GitHub Actions, Jenkins 등 다른 CI 환경에서도 무시된다.

  • 장점: 표준적이고 의도가 명확하게 보임
  • 단점: 커밋 메시지가 길어지거나 어색할 수 있음

 

 

 

 

`-o ci.skip` 방식
GitLab 전용 옵션으로, 커밋 메시지에 직접 [skip ci]를 쓰지 않고도 동일한 효과를 준다.

git commit -o ci.skip -m "update some file silently"
  • 장점: 커밋 메시지를 깔끔하게 유지 가능
  • 단점: Git CLI에서만 가능하며 Git GUI 툴에서는 사용할 수 없는 경우도 있음
 
 
 
 
위 전략을 통해 자동 생성 커밋이나 CI가 불필요한 단순 push에서 리소스를 절약할 수 있다.

 

 

 

 

 

 


 

 

 

 

마무리 및 팁

  • 대용량 리포지터리에서는 Sparse Checkout은 거의 필수다.
  • Git LFS 사용 중이라면 `GIT_LFS_SKIP_SMUDGE=1` 도 함께 고려
  • 실제 빌드용 코드만 있는 별도 리포 분리도 장기적으론 좋은 구조

 

Git 리포지터리의 크기는 계속해서 커지고 있고, 그만큼 CI/CD 파이프라인의 효율성은 점점 더 중요해지고 있다.
이번에 소개한 `sparse-checkout` 과 `blob:limit` 전략은 복잡한 설정 없이도 간단하게 적용할 수 있는, 즉각적인 성능 개선 효과를 가진 실전 솔루션이다.

 

특정 폴더만 받아오는 방식은 단순히 clone 시간을 줄이는 것에 그치지 않고,
네트워크 트래픽 절감, Runner 리소스 절약, 보다 빠른 피드백 루프라는 측면에서도 큰 의미가 있다.

 

복잡한 프로젝트일수록 “전체를 항상 받는다”는 습관을 벗어나
필요한 만큼만, 똑똑하게” 가져오는 패턴으로 전환할 필요가 있다.



 

 

 

 

 

 

 


Reference

https://git-scm.com/docs/git-sparse-checkout

https://git-scm.com/docs/partial-clone

https://github.blog/2020-12-21-getting-started-with-git-sparse-checkout/

https://docs.gitlab.com/ee/ci/variables/#git_strategy

https://docs.gitlab.com/runner/configuration/advanced-configuration.html

https://medium.com/@mattosaurus/speeding-up-git-clone-with-sparse-checkout-c2f2be6a5d44

https://stackoverflow.com/questions/18935539/git-clone-very-slow-on-large-repo

728x90
반응형