grep

DevOps

여기어때 CI/CD 개선기 Part 1: 문제 파악

Jupiter여기어때

2025년 9월 8일

원문에서 보기 ↗

안녕하세요 여기어때컴퍼니 DevOps팀 주피터입니다

DevOps팀은 여기어때컴퍼니 Tech 조직 내 개발자들의 업무 몰입을 위한 개발 환경과 체계를 만들어가는 조직으로 조직별로 상이한 개발 환경을 통합하고 운영하고 있습니다.

이번에 다룰 주제는 여기어때 Tech 조직의 모두를 위한 CI/CD 개선에 대한 내용이고, DevOps팀 9개월 간의 여정을 5 편에 나눠 정리하였습니다.

특히, 사내 개발자 플랫폼(IDP) 없이 CI/CD Pipeline을 구축하고 운영 중인 분들에게 도움이 되었으면 합니다.

개발자가 작성한 코드가 어떻게 하면 매끄럽게 배포될 수 있을까?

이와 같은 고민으로 출발한 DevOps팀의 여정을 공유드리고자 합니다.

현황 파악

기존 CI/CD Workflow

개선에 앞서 DevOps팀이 생기기 이전!

여기어때에서는 EKS에 서비스를 배포하기 위해 CI 도구로는 Gitlab CI를, CD 도구로는 ArgoCD를 사용하고 있습니다.

개발팀에서 배포 환경에 해당하는 dev / stage / release 브랜치에 Merge하면서 CI가 시작됩니다.

이후 ArgoCD에서 Webhook 감지를 통해 Sync를 수행하여 자동적으로 배포하도록 되어 있습니다.

하지만, 기존 구조에서는 CI 적용 시, 어떤 파일을 고쳐야 하는지 알기 어려웠습니다 (30여개 가량의 YAML 파일 존재)

Gradle 빌드 옵션 하나 차이로 새로운 템플릿 파일이 생겨나는 경우도 있었습니다.

그 결과, 30개가 넘는 CI 관련 파일이 생성되었습니다.

include:
  project: "gitlab/ci-template"
  file:
    - "workflow/....gitlab-ci.yml"
    - "gradle/AAA.gitlab-ci.yml"
    - "gradle/AAA-1gb.gitlab-ci.yml"
    - "gradle/BBB.yml"
    - "gitops/CCC.gitlab-ci.yml"

각각 어떤 Job이 실행되는지, 동작 조건은 어떤 것인지 처음 적용하는 팀은 며칠씩 분석에 매달려야 했습니다.

한편 배포 설정을 구성하는 Manifest인 Helm Chart의 상황도 비슷했습니다.

관리 주체 없이 최초 배포된 Helm Chart Template은 시간이 갈수록 각 개발팀 문화에 따라 파편화되기 시작했습니다.

그렇게 Template이라는 이름에 걸맞지 않게 서비스마다 Template이 따로 존재하게 되었습니다.

이러한 현상은 서비스 규모가 커질수록 문제를 야기했습니다.

예를 들어, Spring 에서 Pinpoint(APM 도구) 옵션 (pinpoint.profiler.profiles.active)을 release 로 선택하지 않으면 성능상의 문제가 발생하게 됩니다.

이를 일괄적으로 고치기 위해서는 몇백 개가 넘는 Manifest Template을 수정해야 했습니다.

또한, 개발팀이 굳이 알 필요 없는 ArgoCD 관련 설정이나, Node 관련 설정들도 포함되어 있었습니다.

때문에, 인프라 관련 공통 설정 변경 시 개발팀이 직접 가이드를 보며 하나씩 수정해야 했거나,

필수 설정을 누락한 경우를 일일이 찾아야 했기 때문에 문제 해결에도 반복적으로 시간이 소요되었습니다.

정리하자면 CI와 CD 코드가 모두 파편화되어 있고 관리되지 않았습니다.

DevOps팀은 개발자들의 업무 몰입을 위해 이를 해결하는 것을 우선과제로 삼아 개선하기로 하였습니다.

개선 결과

DevOps팀은 Cloud Native 환경의 숙련도 영향을 받지 않는 균일한 배포 시간을 만들어내고 싶었습니다.

개선한 결과 기본적으로 CI 코드 10줄만 적어주면 EKS에 배포할 수 있게 됩니다.

기존 CI/CD 코드와 비교하면 어떤 모듈을 사용할지 고민할 필요가 없게 되었고, 읽어야할 코드량이 현저히 줄었습니다.

실제로 EKS를 최초 적용할 때 4주가 걸리던 팀은

개선한 CI/CD 파이프라인을 이용하여 신규 입사한 인턴 분과 함께 1시간만에 EKS에 서비스를 배포할 수 있었습니다.

이러한 결과를 만들기 위해서 인지 부하 최소화 와 동일 경험 이라는 개발자를 위한 UX 원칙을 중심에 두고 개선 작업을 진행했습니다.

인지 부하 최소화

인간은 본질적으로 새로움을 두려워하게 되어있습니다.

그렇기 때문에 그 두려움을 줄여주는 것도 DevOps팀의 역할의 일부라고 생각했습니다.

( DevOps팀이 조금만 더 고생하면 개발팀이 조금 더 편하니까요! )

우선, 거부감을 줄이기 위해 기존 CI/CD에 사용하던 양식을 최대한 유지하고자 했습니다.

예를 들어, 기존 변수명은 아래와 같은 형식으로 명확하게 환경변수라는 것을 잘 알려주고 있었습니다.

variables:
  APP_NAME: <APP_NAME>
  ECR_REPOSITORY_NAME: <ECR_NAME>
  MANIFEST_PROJECT_PATH: <MANIFEST_PATH>

예전 것을 무조건 갈아치우는 게 능사는 아니기에 이를 유지하면서 변경된 Convention에 따라 이를 변경해주었습니다.

inputs:
  app-name: <APP_NAME>
  ecr-repository-name: <ECR_NAME>
  manifest-project-path: <MANIFEST_PATH>

또한, 옵션 자체만으로 문서가 필요 없도록 고려했습니다.

옵션 이름을 보고 가능한 값을 찾는 것도 부하가 발생하는 일입니다.

가능한 값이 무엇인지 가이드 문서를 찾는 것부터가 불편함과 불안함을 초래할 수 있습니다.

바로 아래와 같은 예시가 그러합니다.

include:
  - project: devops/pipeline-standard
    ...
    inputs:
      sonarqube: < true | false | enable | disable > 
      jacoco: < true | false | enable | disable >

따라서, 개발자 분들이 옵션값을 찾지 않게 하기 위해 True/False 방식의 명확한 입력 방식을 적용했습니다.

include:
  - project: devops/pipeline-standard
    ...
    inputs:
      enable-sonarqube: 'true'
      enable-jacoco: 'true'

이렇게 하면 옵션값만 보고도 사용법을 알 수 있겠죠?

다음으로는 한번 배운 내용을 계속 써먹어야 개발자 분들도 편하지 않을까? 라는 생각에서 나온 원칙입니다.

동일 경험

여기어때에서 주로 사용하는 언어는 Java & Kotlin, Python, Node입니다.

주로 사용하는 Repo 구조는 Mono-Repo와 Multi-Repo로 크게 두 가지입니다.

이 때, 발생할 수 있는 조합만 해도 6가지 입니다.

하지만 서로 다른 언어, Repo 구조에 따라 CI 구조가 크게 달라지지 않도록 구현하였습니다.

어떤 언어, Repo 구조든 상관없이 동일한 CI 코드를 반복, 재사용 할 수 있도록 하였습니다.

# Java SpringBoot의 CI
include:
  - project: devops/pipeline-standard
    ref: master
    file: java.gitlab-ci.yml
    inputs:
      app-name: example-cms-api
      ..
# python의 CI
include:
  - project: devops/pipeline-standard
    ref: master
    file: python.gitlab-ci.yml
    inputs:
      app-name: example-cms-auth
      ...

이는 배포 설정인 Helm Chart에도 동일하게 적용되었습니다.

workload:
  - kind: Deployment
    name: example-cms-api
    image: ...
    tag: ...
    ...
    
  - kind: Deployment
    name: example-cms-batch
    image: ...
    tag: ...
    ...

이렇게하면 한번 익혀둔 CI/CD Spec을 어느 팀, 어떤 프로젝트에서든 계속 활용할 수 있게 됩니다.

이러한 반복 — 재사용 가능한 코드 구조는 자동화 가능한 구조가 됩니다.

자동화/공통화된 CI/CD Pipeline은 곧 IDP와 같은 내부 플랫폼의 튼튼한 기반이 될 것 입니다.

다음으로

DevOps팀은 개발자의 발목을 잡는 CI/CD를 개선하기 위해 문제점을 분석했고 개발자를 위한 UX 원칙을 기반으로 CI/CD를 개선하고자 했습니다.

다음 편부터는 실제 어떤 코드를 활용했는지, 그리고 과정에서 어떤 어려움이 있었는지 구체적으로 풀어보겠습니다.