Jenkins 제거와 GitHub Actions CI/CD 마이그레이션
사내 하네스 인프라 개선 작업의 핵심 과제 중 하나는 오래된 레거시였던 Jenkins 서버 제거 였습니다. 수많은 기업들이 관성적으로 Jenkins를 사용합니다. 우리 역시 마찬가지였습니다. 하지만 "우리가 과연 Jenkins의 기능을 현재 상황에 맞게 활용하고 있는가?", "이 도구가 지금 우리 비즈니스 규모에 맞는가?"라는 근본적인 의구심이 들기 시작했고, 결국 서버리스 CI/CD인 GitHub Actions 로의 전환을 결단했습니다.
그 결단의 배경과 비용 최적화, 그리고 배포 파이프라인을 고도화한 과정을 공유합니다.
The Problem: 비용 대비 효율이 낮은 인프라와 핫픽스 병목
과거 우리 팀은 여러 프로젝트의 배포를 처리하기 위해 Jenkins 서버 2대를 운영하고 있었습니다. 서버당 월 10만 원씩, 총 매월 20만 원의 고정 유지비 가 발생했습니다.
비용도 문제였지만, 더 큰 문제는 '개발자 경험'의 하락이었습니다. 여러 프로젝트가 같은 Jenkins 서버에 묶여 있었기 때문에, 여러 프로젝트를 동시에 업데이트해도 하나의 프로젝트 배포가 끝난 뒤 다음 프로젝트가 배포되는 순차 처리 병목이 있었습니다. 서버 스펙상 slave를 늘리기도 어려웠고, Jenkins 서버 자체가 죽으면 배포가 지연되는 상황도 발생했습니다.
The Solution: 서버리스 전환과 파이프라인 고도화
더 이상 Jenkins를 고집할 이유가 없었습니다. 고정비가 없고 병렬 빌드가 자유로운 GitHub Actions 로 모든 파이프라인을 옮기기 시작했습니다. 마이그레이션 자체는 까다롭지 않았습니다. 자체 슬랙 봇을 연동하는 데 1시간 남짓 소요되었을 뿐, 배포의 논리적 흐름은 동일했기 때문입니다. 오히려 저는 단순히 툴을 바꾸는 것을 넘어, 배포 속도와 스크립트의 유지보수성을 고도화 하는 데 집중했습니다.
1. npm ci와 캐싱을 통한 빌드 속도 최적화
매번 무거운 모듈을 새로 다운로드하는 시간을 줄이기 위해 Actions의 actions/cache를 적극 도입했습니다. package-lock.json의 해시값을 키로 삼아 node_modules와 Next.js 빌드 캐시를 저장하고, npm ci 명령어를 통해 캐시 적중률을 높여 빌드 시간을 줄였습니다.
2. 셸 스크립트의 범용화 및 추상화
기존에는 서버마다, 프로젝트마다 압축을 풀고 PM2를 재시작하는 하드코딩된 .sh 파일이 파편화되어 존재했습니다. 이를 하나의 공통 server-deploy.sh로 통합하고, GitHub Actions에서 실행 시 인자값 으로 DEPLOY_DIR, TAR_FILE, APP_NAME, APP_TYPE(pm2/static)을 주입하도록 리팩토링했습니다. 이제 새로운 프로젝트가 추가되더라도 서버의 스크립트를 건드릴 필요 없이 파이프라인 설정만으로 즉각 대응이 가능한 유연한 구조를 완성했습니다.
The Result & Retrospective
현재 Jenkins에서 GitHub Actions로의 전환 작업을 점진적으로 진행 중이지만, 이미 그 효과는 명확합니다. 가장 직관적인 성과는 Jenkins 서버 2대 제거 또는 제거 예정으로 매월 20만 원의 인프라 유지 비용을 절감 할 수 있게 된 것입니다. 나아가 Jenkins의 물리적 스펙 한계에 갇혀 있던 순차 배포 병목에서 벗어나, 프로젝트별 GitHub Actions workflow 실행 구조로 핫픽스 대기 시간을 줄일 수 있을 것으로 기대하고 있습니다.
관성적으로 쓰던 도구를 버리고 현재의 비즈니스 체급과 비용에 가장 알맞은 아키텍처를 새로 그리는 것, 이것이 진정한 의미의 DevOps이자 인프라 최적화임을 깨달았습니다.