GitLab의 중요한 기능 중 하나는 코드 빌드, 테스트 및 배포 과정을 자동화할 수 있는 CI/CD 파이프라인입니다. 그러나 프로젝트가 커지면 Job 수, 단계 수, 스크립트 및 의존성 수 등 많은 요소로 인해 파이프라인이 느려질 수 있습니다. 느린 파이프라인은 개발 프로세스에 부정적인 영향을 미칠 수 있으며, 시장 진입 시간이 증가하고 귀중한 자원을 낭비할 수 있습니다. 이번 포스트에서는 GitLab 파이프라인 속도를 향상하는 데 사용할 수 있는 여러 방법과 그중 가장 간단하고 효과적인 방법인 GitLab CI/CD 캐시에 대해 알아보겠습니다.

photo | 인포그랩 GitLab | 인포그랩 GitLab

왜 CI/CD 파이프라인 속도가 느려질까요?

GitLab CI/CD 파이프라인의 속도에 영향을 미치는 여러 요소가 있습니다. 의존성 다운로드와 빌드, 비효율적인 파이프라인 디자인, 코드베이스 크기, 의존성 복잡성 및 리소스 할당 등이 있습니다. 이러한 요소를 이해하고 파이프라인을 최적화하면 파이프라인의 속도를 높이고 전반적인 생산성을 향상할 수 있습니다.

  • 의존성을 다운로드하고 빌드하는 데 걸리는 시간 : 각 파이프라인이 실행될 때마다 처음부터 모든 의존성 패키지 및 라이브러리를 다운로드하고 빌드하는 경우, 특히 코드베이스나 의존성이 복잡한 경우 매우 시간이 걸릴 수 있습니다. 이때 GitLab CI 캐시가 유용합니다. 파일, 의존성 및 기타 아티팩트를 파이프라인 실행 간에 캐시함으로써 매번 처음부터 모든 것을 다운로드하고 다시 빌드하는 데 필요한 시간을 절약할 수 있습니다. 이렇게 하면 파이프라인을 크게 빠르게 할 수 있습니다.

  • 비효율적인 파이프라인 디자인 : 불필요한 단계가 있거나 특정 사용 사례에 최적화되지 않은 경우 전체 프로세스가 느려질 수 있습니다. 파이프라인에서 병목현상을 식별하고 그에 따라 최적화하는 것이 중요합니다. 예를 들어 파이프라인을 작은 작업으로 분할하거나 일부 단계를 병렬 처리하여 특정 단계를 빠르게 할 수 있습니다.

  • 코드베이스 크기 : 리포지토리에 많은 양의 코드가 포함되어 있으면 빌드 및 테스트에 더 많은 시간이 걸릴 수 있습니다. 이 경우 코드베이스를 작은 모듈로 분할하고 각 모듈을 별도의 파이프라인으로 구성하는 것이 좋습니다.

  • 의존성 복잡성 : 의존성이 복잡할수록 빌드 및 테스트에 더 많은 시간이 걸릴 수 있습니다. 이 경우 의존성을 최소화하고 필요한 의존성만 사용하는 것이 좋습니다.

  • 리소스 할당 : 파이프라인에 충분한 리소스가 할당되지 않은 경우 완료하는 데 더 많은 시간이 걸릴 수 있습니다. 파이프라인을 실행하는 데 필요한 리소스를 파악하고 적절한 리소스를 할당하는 것이 중요합니다.

어떻게 하면 CI/CD 파이프라인 속도를 향상할 수 있나요?

GitLab CI/CD 파이프라인 속도를 향상하는 방법에는 여러 가지가 있습니다. 이러한 방법을 사용하면 파이프라인을 빠르게 할 수 있습니다.

  • 캐싱 사용 : 캐시를 사용하면 파이프라인 실행 간의 의존성을 캐싱할 수 있으므로 불필요한 다운로드 및 설치를 피할 수 있습니다. Node.js 또는 Ruby 프로젝트와 같이 많은 의존성을 포함하는 경우에 특히 유용할 수 있습니다. GitLab에서 캐싱을 활성화하려면 캐시 할 디렉터리 또는 파일을 지정하는 cache 블록을 .gitlab-ci.yml 파일에 추가하면 됩니다.

  • 파이프라인 병렬화 : 파이프라인 단계가 서로 의존하지 않는 경우 파이프라인을 완료하는 데 필요한 총시간을 크게 줄일 수 있도록 Job을 병렬로 실행할 수 있습니다. .gitlab-ci.yml 파일에 동시성 값을 지정하여 단계를 병렬로 실행하도록 GitLab을 구성할 수 있습니다.

  • 더 작은 이미지 사용 : Docker 컨테이너를 사용하여 파이프라인 Job을 실행하는 경우 더 작은 기본 이미지를 사용하는 것이 좋습니다. 이렇게 하면 컨테이너를 다운로드하고 가동하는 데 필요한 시간을 줄일 수 있습니다. 예를 들어 alpine 기반의 이미지를 사용할 수 있습니다. 다단계 빌드(Multi-Stage builds)를 사용하여 더 작은 최종 이미지를 만들 수도 있습니다.

  • 코드 최적화 : 파이프라인에 코드 빌드 및 테스트가 포함되면 코드를 최적화하여 빌드 및 테스트 시간을 줄일 수 있습니다. 예를 들어 종속성 수를 줄이고 빌드 프로세스를 간소화하거나 테스트를 병렬화할 수 있습니다. 컴파일된 코드를 캐시 하거나 빌드 아티팩트를 재사용하도록 빌드 도구를 구성할 수도 있습니다.

  • 더 빠른 하드웨어 사용 : GitLab Runner가 느리거나 오래된 하드웨어에서 실행되는 경우 더 빠른 하드웨어로 업그레이드하거나 필요에 따라 확장 또는 축소할 수 있는 클라우드 기반 GitLab Runner를 사용하는 것이 좋습니다. 필요한 경우 더 많은 CPU 또는 메모리가 있는 Runner를 사용하도록 GitLab을 구성할 수도 있습니다.

  • GitLab Runner의 오토스케일링(Autoscaling) 기능 사용 : GitLab은 파이프라인 수요에 따라 러너를 자동으로 추가하거나 제거할 수 있는 자동 크기 조정 기능을 제공합니다. 이렇게 하면 파이프라인을 신속하게 처리할 수 있는 충분한 러너를 항상 확보할 수 있습니다. 필요에 따라 확장 또는 축소할 수 있는 클라우드 기반 러너를 사용하도록 GitLab을 구성할 수 있습니다.

GitLab CI/CD 캐시란?

GitLab 캐시는 CI/CD 파이프라인에서 Job 간에 특정 파일과 디렉터리를 캐싱하여 빌드 프로세스 속도를 높일 수 있는 기능입니다. 캐시는 GitLab Runner가 설치된 곳에 저장되며 분산 캐시가 활성화된 경우 AWS S3와 같은 캐시 저장소에 업로드됩니다.

캐싱은 의존성이 큰 프로젝트나 자주 빌드하고 테스트하는 프로젝트에 특히 유용할 수 있습니다. 이러한 파일과 디렉터리를 캐싱하면 코드를 빌드하고 테스트하는 데 걸리는 시간을 크게 줄여 개발 프로세스를 보다 효율적으로 만들 수 있습니다.

  • cache 키워드를 사용하여 Job 별로 캐시를 정의합니다. 그렇지 않으면 비활성화됩니다.
  • 후속 파이프라인은 캐시를 사용할 수 있습니다.
  • 의존성이 동일한 경우 동일한 파이프라인의 후속 Job에서 캐시를 사용할 수 있습니다.
  • 다른 프로젝트는 캐시를 공유할 수 없습니다.
  • 기본적으로 보호된 브랜치와 보호되지 않은 브랜치는 캐시를 공유하지 않습니다. 그러나 이 동작은 프로젝트의 Settings > CI/CD 메뉴에서 변경할 수 있습니다.

캐시는 어떻게 사용하나요?

Node.js 의존성 캐시

Node.js 기반 프로젝트에서 npm을 사용하여 의존성을 설치하는 경우 .gitlab-ci.yml 파일에 다음과 같은 캐시 섹션을 추가할 수 있습니다. 다음 예제는 모든 작업이 이를 상속하도록 전역적으로 cache를 정의합니다. 기본적으로 npm은 홈 폴더(~/.npm)에 캐시 데이터를 저장합니다. 그러나 프로젝트 디렉터리 외부에 있는 항목은 캐시 할 수 없습니다. 대신 npm에 ./.npm 경로를 사용하도록 지시하고 브랜치 별로 캐시 합니다.

image: node:lts-alpine

cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .npm/
- node_modules/

build:
stage: build
before_script:
- npm ci --cache .npm --prefer-offline
script:
- npm run build
잠금 파일에서 캐시 키 계산

cache:key:files를 사용하여 package-lock.json 또는 yarn.lock와 같은 잠금 파일에서 캐시 키를 계산하고 많은 Job에서 재사용할 수 있습니다.

cache:
key:
files:
- package-lock.json
paths:
- .npm/
- node_modules/

Maven 의존성 캐시

Java 기반 프로젝트에서 Maven으로 의존성을 관리하는 경우 .gitlab-ci.yml 파일에 다음과 같이 캐시를 설정할 수 있습니다. 기본적으로 Maven은 홈 폴더(~/.m2)에 캐시 데이터를 저장합니다.
-Dmaven.repo.local=.m2/repository와 같이 매개변수를 사용하여 ./.m2/repository 경로에 저장하도록 지시하고 브랜치 별로 캐시 합니다.

variables:
MAVEN_OPTS: >-
-Dhttps.protocols=TLSv1.2
-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository
-Dorg.slf4j.simpleLogger.showDateTime=true
-Djava.awt.headless=true
MAVEN_CLI_OPTS: >-
--batch-mode
--errors
--fail-at-end
--show-version
--no-transfer-progress
-DinstallAtEnd=true
-DdeployAtEnd=true

image: maven:3.8-eclipse-temurin-17-alpine

cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .m2/repository

build:
stage: build
script:
- mvn $MAVEN_CLI_OPTS clean compile

참고 : MAVEN_OPTS 환경 변수는 Maven이 실행될 JVM을 시작하는 데 사용되는 매개변수가 포함되어 있으며, 추가 옵션을 제공하는 데 사용할 수 있습니다. 이 환경 변수에 포함된 매개변수는 Maven이 실행될 때 항상 적용됩니다.

Gradle 의존성 캐시

Gradle로 의존성을 관리하는 경우 다음과 같은 캐시 섹션을 추가할 수 있습니다. 기본적으로 Gradle은 홈 폴더(~/.gradle)에 캐시 데이터를 저장합니다.
Gradle에는 빌드 환경을 구성할 수 있는 여러 속성들이 있으며, GRADLE_OPTS 환경 변수에 이 속성들을 설정하여 Gradle에 전달할 옵션을 지정할 수 있습니다. GRADLE_USER_HOME 환경변수는 Gradle 사용자 홈 디렉터리를 지정합니다.

variables:
GRADLE_OPTS: '-Dorg.gradle.caching=true -Dorg.gradle.daemon=false'
GRADLE_USER_HOME: $CI_PROJECT_DIR/.gradle

image: gradle:7.6-jdk17-alpine

cache:
key: $CI_COMMIT_REF_SLUG
paths:
- .gradle/

build:
stage: build
script:
- gradle clean classes

캐시 정책

캐시의 업로드 및 다운로드 동작을 변경하면 불필요한 작업을 피할 수 있습니다. cache:policy 키워드를 사용하여 캐시 정책을 설정할 수 있습니다.

3가지 정책이 있습니다.

  • pull-push (기본값) : 작업이 시작될 때 캐시를 다운로드하고 작업이 끝나면 변경사항을 캐시에 업로드합니다.
  • pull : 작업이 시작될 때만 캐시를 다운로드하고 작업이 완료되면 변경 사항을 업로드하지 않습니다.
  • push : 작업이 완료될 때만 캐시를 업로드하고 작업이 시작될 때 캐시를 다운로드하지 않습니다.
prepare-dependencies-job:
stage: build
cache:
key: gems
paths:
- vendor/bundle
policy: push
script:
- echo "This job only downloads dependencies and builds the cache."
- echo "Downloading dependencies..."

faster-test-job:
stage: test
cache:
key: gems
paths:
- vendor/bundle
policy: pull
script:
- echo "This job script uses the cache, but does not update it."
- echo "Running tests..."

맺음말

지금까지 GitLab CI/CD 파이프라인이 느려지는 이유와 속도를 높이기 위한 몇 가지 방법과 캐시를 사용하는 방법에 대해 알아보았습니다. GitLab CI/CD 캐시는 빌드 속도를 높이고 빌드 비용을 줄일 수 있는 강력한 기능입니다. 파일, 종속성 및 기타 아티팩트를 캐시함으로써 불필요한 리소스 사용을 피하고 CI/CD 파이프라인을 최적화할 수 있습니다.

지속적 통합(Continuous Integration, CI) 및 지속적 배포(Continuous Delivery, CD)는 현대 소프트웨어 개발 관행의 중요한 측면입니다. 코드 변경사항을 빠르고 효율적으로 빌드, 테스트 및 배포하는 기능은 고품질 소프트웨어 제품을 제공하는 데 매우 중요합니다. GitLab은 완전한 CI/CD 솔루션을 제공하는 DevOp 플랫폼입니다.

인포그랩은 GitLab 및 DevOps에 대한 맞춤 기술 지원을 제공합니다.
GitLab(Omnibus/Cloud Native Hybrid) 구축 관련한 지원이 필요하시면 문의하기 로 연락 주십시오.