본문 바로가기
IT/Cloud

[Cloud] GitLab CI/CD, 월 300달러 린트 비용 낭비 막는 법

by 수누다 2026. 5. 27.

안녕하세요, 13년차 인프라 엔지니어 '13년차의 서버실'입니다. 오늘은 많은 분들이 공감하실 만한, 하지만 간과하기 쉬운 CI/CD 비용 문제에 대해 이야기해보려고 해요. 특히 GitLab CI/CD 비용 최적화와 관련해서 제가 직접 겪었던 뼈아픈 경험과 그 해결 과정을 공유합니다. 사실 저도 처음엔 CI/CD를 구축하고 나면 다 끝난 줄 알았거든요. 그런데 시간이 지나면서 예상치 못한 곳에서 비용이 새고 있더라고요. 바로 불필요하게 돌아가는 린트(Lint) 비용이었죠. 한 달에 무려 300달러나 되는 돈이 린트 때문에 나가고 있었다니, 처음엔 믿을 수가 없었어요. 오늘은 이 낭비를 어떻게 막았는지, 그 노하우를 풀어볼게요!

GitLab CI/CD 린트 비용 낭비 및 최적화 전후 비교 다이어그램

GitLab CI/CD 파이프라인에서 불필요한 린트(Lint) 작업으로 인해 비용이 낭비되고, 이를 최적화하여 절감하는 과정을 시각적으로 보여주는 다이어그램.

CI/CD 린트(Lint)가 왜 비용 낭비의 주범이 될까요?

CI/CD(Continuous Integration/Continuous Deployment, 지속적 통합/지속적 배포)는 정말 신기한 도구거든요. 코드를 푸시할 때마다 자동으로 테스트하고 배포하니까요. 이 과정에서 린트(Lint, 코드 스타일 및 잠재적 오류 검사)는 코드 품질을 유지하는 데 정말 중요한 역할을 합니다. 문제가 크기 전에 미리 잡아주니 정말 고맙죠.

그런데 여기서 문제가 발생합니다. 대부분의 CI/CD 설정은 코드가 변경될 때마다, 즉 <code>git push 할 때마다 모든 파이프라인 작업을 실행하도록 되어 있더라고요. 작은 오타 수정이나 README 파일 업데이트 같은 사소한 변경에도 린트 작업을 포함한 모든 CI 작업이 돌아가는 거죠. 린트 작업 자체는 비교적 가볍다고 생각하기 쉽지만, 이게 수십, 수백 번 반복되면 이야기가 달라집니다. 특히 GitLab.com 같은 SaaS(Software as a Service) 환경에서는 사용량에 따라 CI/CD Runner minutes(러너 사용 시간) 비용이 발생하거든요. 제가 운영하는 홈랩에서도 처음엔 이런 비용을 크게 신경 쓰지 않았는데, 프로젝트가 많아지고 커밋이 잦아지면서 슬금슬금 비용이 올라가는 걸 보고 깜짝 놀랐습니다.

비용 낭비의 핵심 원인:

  • 잦은 커밋: 개발 과정에서 수많은 중간 커밋이 발생합니다.
  • 불필요한 실행: 코드를 변경하지 않는 파일(예: 주석, 문서)의 변경에도 린트가 실행됩니다.
  • 모든 브랜치 실행: 개발 브랜치, 피처 브랜치 등 모든 브랜치에 푸시될 때마다 린트가 실행됩니다.

이런 상황을 제가 직접 겪어보니, "아, 이건 뭔가 바꿔야겠다!" 싶더라고요. 그래서 CI/CD 최적화 방안을 진지하게 고민하기 시작했습니다.

GitLab CI/CD 비용 최적화를 위한 핵심 전략: 조건부 실행 (Conditional Execution)

GitLab CI/CD에서 비용을 절감하는 가장 효과적인 방법 중 하나는 조건부 실행(Conditional Execution)입니다. 말 그대로 특정 조건이 충족될 때만 CI/CD 작업을 실행하도록 하는 거죠. 린트 작업의 경우, 모든 커밋에 대해 실행하기보다는 특정 상황에서만 실행하도록 제한할 수 있습니다.

제가 주로 활용한 전략은 다음과 같습니다:

  1. 머지 리퀘스트(Merge Request) 시에만 실행: 피처 브랜치에서 개발할 때는 린트 작업을 건너뛰고, 메인 브랜치로 머지하기 위한 MR이 생성될 때만 린트 검사를 실행합니다. 이렇게 하면 불필요한 중간 커밋에 대한 린트 실행을 대폭 줄일 수 있거든요.
  2. 코드 변경이 있는 파일에 대해서만 실행: 정말 필요한 경우에만 린트 작업을 실행하도록 조건을 더 세분화할 수 있습니다. 예를 들어, 특정 코드 파일이 변경되었을 때만 린트 작업을 실행하는 방식이죠.

GitLab CI/CD는 rules 키워드를 통해 이런 조건부 실행을 강력하게 지원합니다. 처음엔 only/except 문법을 사용하기도 했는데, rules가 훨씬 유연하고 강력하더라고요. rules를 사용하면 여러 조건을 조합해서 원하는 시나리오를 만들 수 있습니다.

실전 구현: `.gitlab-ci.yml`에 조건부 린트 잡(Job) 추가하기

자, 그럼 이제 제가 실제로 어떻게 GitLab CI 비용 절감을 이뤄냈는지 `.gitlab-ci.yml` 설정과 함께 설명해 드릴게요. 핵심은 린트 작업을 위한 잡(Job)에 rules를 적용하는 겁니다.

1. 머지 리퀘스트(MR) 시에만 린트 실행하기

가장 기본적이고 효과적인 방법입니다. 개발 브랜치에 푸시할 때는 린트를 건너뛰고, MR이 생성되거나 업데이트될 때만 린트를 실행합니다. 이렇게 하면 개발 중 발생하는 수많은 중간 커밋의 CI 비용을 아낄 수 있거든요.


lint_job:
  stage: lint
  image: python:3.9-slim # 린트 도구에 맞는 이미지 사용
  script:
    - pip install flake8 # 예시: Python flake8 린터 설치
    - flake8 .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # MR이 생성되거나 업데이트될 때만 실행
      when: on_success
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' # 기본 브랜치(master/main)에 푸시될 때 실행 (최종 검증)
      when: on_success

위 코드에서 $CI_PIPELINE_SOURCE == "merge_request_event"는 머지 리퀘스트 파이프라인에서만 이 잡(Job)을 실행하라는 의미입니다. 그리고 $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH는 메인 브랜치(보통 main 또는 master)에 직접 푸시될 때도 린트가 실행되도록 해서 최종적인 코드 품질을 보장합니다. 이렇게 설정하니 월 300달러나 나가던 린트 비용이 확 줄어들더라고요! 🎉

GitLab CI/CD 린트 조건부 실행을 위한 .gitlab-ci.yml rules 설정

GitLab CI/CD 설정 파일(.gitlab-ci.yml)에서 'rules' 키워드를 사용하여 린트(Lint) 작업을 조건부로 실행하도록 구성된 YAML 코드 스니펫.

2. 특정 파일 변경 시에만 린트 실행하기 (고급)

좀 더 세밀한 제어가 필요하다면 rules:changes를 활용할 수 있습니다. 예를 들어, Python 코드 파일(.py)이 변경되었을 때만 Python 린트를 실행하고, JavaScript 파일(.js)이 변경되었을 때만 JavaScript 린트를 실행하는 식이죠.


python_lint_job:
  stage: lint
  image: python:3.9-slim
  script:
    - pip install flake8
    - flake8 .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - "**/*.py" # .py 파일 변경 시에만 실행
      when: on_success
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      changes:
        - "**/*.py"
      when: on_success

javascript_lint_job:
  stage: lint
  image: node:16-slim # Node.js 린터에 맞는 이미지 사용
  script:
    - npm install eslint
    - npx eslint .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - "**/*.js" # .js 파일 변경 시에만 실행
      when: on_success
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      changes:
        - "**/*.js"
      when: on_success

이 방식은 파이프라인을 더욱 효율적으로 만들지만, rules:changes는 GitLab Runner가 변경된 파일을 확인하는 과정에서 약간의 오버헤드가 발생할 수 있거든요. 하지만 특정 언어의 린트가 매우 무겁거나, 모노레포(Monorepo)처럼 여러 프로젝트가 한 레포지토리에 있을 때는 정말 유용하게 활용할 수 있습니다. 제가 홈랩에서 여러 마이크로서비스를 한 레포에 넣어두고 관리할 때 이 방법을 써봤는데, 확실히 비용 절감 효과가 좋았어요.

⚠️ 주의사항 및 트러블슈팅: 꼼꼼함이 핵심!

GitLab CI/CD 최적화는 비용 절감이라는 큰 장점이 있지만, 몇 가지 주의할 점도 있습니다. 제가 삽질 좀 하면서 겪었던 시행착오들을 공유해 드릴게요.

  1. 조건 설정의 오작동: rules 문법이 생각보다 까다로울 수 있거든요. 조건을 너무 복잡하게 설정하면 예상치 못하게 잡(Job)이 실행되지 않거나, 반대로 불필요하게 실행될 수 있어요. 항상 테스트를 통해 의도한 대로 동작하는지 확인해야 합니다. rules:ifrules:changes를 함께 사용할 때는 특히 주의해야 합니다.
  2. 개발자의 실수: 머지 리퀘스트 파이프라인에서만 린트를 실행하도록 했는데, 개발자가 실수로 로컬에서 린트를 돌리지 않고 MR을 올리는 경우가 생길 수 있거든요. 이렇게 되면 MR 파이프라인에서 린트 에러가 발생하고, 다시 수정해서 커밋해야 하는 번거로움이 생기죠. 이를 방지하기 위해 프리-커밋 훅(Pre-commit Hook) 같은 도구를 도입하여 로컬에서도 린트 검사를 강제하는 것을 고려해볼 수 있습니다. 저도 이 문제 때문에 초기에는 좀 곤란했는데, huskylint-staged 같은 도구를 도입해서 해결했어요.
  3. 초기 러너 비용: rules:changes를 사용할 때, GitLab Runner는 변경된 파일 목록을 가져오기 위해 Git 히스토리를 확인해야 합니다. 이 과정에서 필요한 최소한의 Git 클론(clone) 작업이 발생하므로, 아주 미미하지만 초기 러너 사용 시간이 발생할 수 있거든요. 대부분의 경우 무시할 만한 수준이지만, 극단적인 최적화를 목표로 한다면 고려할 만한 요소입니다.

가장 중요한 건, 변경 사항을 적용한 후에 GitLab CI/CD 파이프라인을 여러 시나리오(새 브랜치 푸시, MR 생성, 메인 브랜치 푸시 등)로 테스트해보고, CI/CD Analytics(분석) 탭에서 러너 사용 시간을 주기적으로 확인하는 겁니다. 저도 처음엔 설정이 제대로 됐는지 확신이 없어서 파이프라인 로그를 꼼꼼히 뜯어봤거든요. 💡

결과 검증: 실제로 비용이 줄었는지 확인하기

그럼 이제 가장 중요한 부분이죠. 이렇게 설정하고 나면 정말 비용 절감이 되는지 어떻게 확인할까요? GitLab은 친절하게도 CI/CD 사용량에 대한 통계를 제공하더라고요. 저는 주로 Settings → CI/CD → Usage Quotas 섹션과 Analytics → CI/CD Analytics를 활용했습니다.

제 경험으로는, 조건부 린트 잡을 적용하기 전과 후의 Runner minutes(러너 사용 시간) 그래프가 확연히 달라지는 것을 확인할 수 있었습니다. 특히 월말에 청구되는 금액을 비교해보니, 월 300달러 가까이 나가던 CI/CD 비용이 100달러 미만으로 줄어드는 것을 보고 정말 뿌듯했습니다. 🎉 이 정도면 꽤 괜찮은 성과 아닌가요?

GitLab CI/CD 러너 사용 시간 및 비용 최적화 효과 차트

GitLab CI/CD Usage Quotas 또는 CI/CD Analytics 대시보드에서 러너 사용 시간(Runner minutes)이 최적화 전후로 극적으로 감소한 것을 보여주는 차트 또는 그래프.

✅ 핵심 검증 포인트:

  • Runner minutes 감소: 월별, 주별 러너 사용 시간이 줄어들었는지 확인.
  • 파이프라인 실행 횟수 감소: 불필요한 린트 잡의 실행 횟수가 줄었는지 확인.
  • 청구서 확인: 실제 청구되는 금액이 줄었는지 최종적으로 확인.

마무리: 작은 변화가 큰 절약을 만듭니다

오늘은 GitLab CI/CD 비용 최적화, 특히 불필요한 린트 비용을 절감하는 방법에 대해 제 경험을 바탕으로 이야기해 봤습니다. 사실 린트 작업 하나에 월 300달러라는 비용이 나가는 건 좀 과하다 싶었거든요. 하지만 조건부 실행(Conditional Execution)이라는 작은 변화를 통해 예상보다 훨씬 큰 비용 절감 효과를 볼 수 있었습니다.

이러한 비용 최적화는 린트 작업뿐만 아니라, 빌드(Build), 테스트(Test) 등 다른 CI/CD 잡에도 확장해서 적용할 수 있습니다. 예를 들어, 프론트엔드 코드만 변경되었을 때는 백엔드 테스트를 건너뛰는 식으로요. 항상 "이 잡이 지금 꼭 실행되어야 하는가?"라는 질문을 던져보면 최적화 포인트를 찾기 쉬울 겁니다.

결국, CI/CD 최적화는 단순히 비용을 줄이는 것을 넘어, 파이프라인의 효율성을 높이고 개발자들이 더 빠르고 정확하게 피드백을 받을 수 있도록 돕는 중요한 과정입니다. 저도 이 과정을 통해 CI/CD에 대한 이해를 한 단계 더 높일 수 있었어요. 여러분도 이 글을 통해 비용 절감과 효율적인 CI/CD 운영에 도움이 되셨기를 바랍니다!

GitLab CI/CD 비용 절감 전략 요약 인포그래픽

GitLab CI/CD 비용 절감 전략을 요약하고, 지속적인 최적화의 중요성을 강조하는 인포그래픽 또는 비교표.

다음 글에서는 GitHub Actions에서도 유사한 비용 최적화 전략을 어떻게 적용할 수 있는지 알아보는 시간을 가져볼게요. 궁금한 점이 있다면 언제든지 댓글로 남겨주세요!