
작년 여름, 새벽 2시에 서버에 SSH 접속하면서 손이 떨렸다.
신기능 배포 작업 중, 데이터베이스 마이그레이션 스크립트에 1줄을 빼먹었다. 알아챘을 때는 이미 프로덕션 환경의 테이블 구조가 망가져 있었고, 서비스가 중단됐다. Slack에는 "로그인이 안 돼요", "결제 오류가 나요"라는 사용자 신고가 계속 올라왔다.
결국 롤백에 3시간이 걸렸고, 다음 날 아침 상사에게 불려갔다.
"왜 이런 일이 생긴 거야?"
솔직하게 대답했다. "수동으로 하다가 실수했습니다"
그날부터 나는 CI/CD를 진지하게 배우기 시작했다.
당시 내 배포 절차는 이랬다:
이 절차, 뭐가 문제인지 알겠는가?
모든 것이 인간의 기억과 주의력에 의존하고 있다
나는 체크리스트를 만들었지만, 그래도 실수는 일어났다. 왜냐하면:
쿠팡이 빠르게 성장하던 초기, 백엔드 팀도 같은 문제를 겪었다.
개발자는 서버에 SSH로 접속해 수동으로 코드 빌드, DB 마이그레이션을 실행해야 했다. 작은 실수 하나도 시스템 다운을 초래할 수 있었다. 엔지니어는 코드 커밋을 주저하고, 매니저는 릴리스를 재촉하고, 사용자는 버그를 발견했다.
CI/CD 도입 이후, 팀은 자동화된 테스트와 배포 파이프라인을 구축하여 매일 안정적으로 배포할 수 있게 되었다.
CI/CD는 "Continuous Integration / Continuous Deployment"의 약자.
한국어로 하면 "지속적 통합 / 지속적 배포".
하지만 이 설명만으로는 무슨 말인지 모르겠다.
내 방식으로 설명하면, 코드를 커밋하면 나머지는 전부 자동으로 해주는 구조다.
구체적으로:
즉, 인간이 하는 일은 "코드를 작성해서 푸시하는 것"뿐.
나머지는 전부 기계가 알아서 해준다.
내가 처음 도입한 것은 GitHub Actions였다.
이유는 간단하다. GitHub를 쓰고 있었으니까. 추가 도구를 설치할 필요 없이, YAML 파일 하나만 작성하면 작동한다.
처음 만든 워크플로우는 이런 느낌:
name: CI-CD
on:
push:
branches: ["main"]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Build Docker image
run: docker build -t app .
- name: Deploy to Production
run: ./deploy.sh
이 YAML 파일을 .github/workflows/에 두기만 하면, main 브랜치에 푸시할 때마다 자동으로 테스트와 배포가 실행된다.
처음에는 반신반의했지만, 실제로 작동했을 때는 감동했다.
"이거, 정말 자동으로 해주네..."
CI/CD를 도입하고 깨달은 것은, API 관리가 자동화의 성패를 가른다는 것.
백엔드 개발에서는 API 사양 변경이 자주 일어난다.
이런 변경이 있을 때마다 프론트엔드나 QA 팀에 수동으로 연락한다면, 자동화의 의미가 없다.
여기서 도움이 된 것이 Apidog였다.
참고
Apidog는 API 설계·문서 생성·Mock 서버·자동 테스트를 할 수 있는 도구입니다. 백엔드 개발의 CI/CD 파이프라인과 결합하면 API 관리와 테스트를 효율화할 수 있습니다.

Apidog를 사용하면:
즉, API 관리도 자동화의 일부로 통합할 수 있다.
CI/CD 파이프라인에 Apidog를 통합한 후, 프론트엔드와의 연계가 매끄러워졌다.
CI/CD를 도입해도, 데이터베이스 마이그레이션은 여전히 무서웠다.
왜냐하면, 데이터베이스 변경은 돌이킬 수 없기 때문이다.
코드 롤백은 쉽지만, 데이터베이스 롤백은 어렵다.
특히 프로덕션 환경에 대량의 데이터가 있는 경우, 마이그레이션에 실패하면 복구에 시간이 걸린다.
내가 배운 안전한 마이그레이션 방법은:
up(적용)과 down(롤백)을 모두 준비예를 들어, 컬럼을 삭제하는 경우:
이렇게 하면, 중간에 롤백해도 문제가 생기지 않는다.
CI/CD를 도입한 후, 나는 몇 가지 지표를 추적하게 됐다.
| 지표 | 설명 | 이상값 |
|---|---|---|
| Deployment Frequency | 배포 빈도 | ≥ 3회/일 |
| Change Failure Rate | 배포 실패율 | <5% |
| MTTR (Mean Time to Recovery) | 장애 복구 시간 | <15분 |
| Lead Time | 커밋부터 릴리스까지 | 몇 분~1시간 |
처음에는 주 1회 배포였지만, 지금은 하루에 3~5회 배포하고 있다.
배포 실패율도 20%에서 5% 미만으로 떨어졌다.
무엇보다, 배포가 무섭지 않게 됐다.
예전에는 "오늘 배포해? 진짜?"라는 느낌이었지만, 지금은 "잠깐 배포하고 올게" 정도의 감각.
"CI/CD는 대기업용 아닌가?"라고 생각할 수 있다.
하지만 소규모 팀이야말로 CI/CD가 필요하다고 생각한다.
왜냐하면, 인력이 적기 때문에 자동화로 효율을 높여야 하니까.
내가 소속된 팀은 3명이었지만, 30일 만에 CI/CD를 도입할 수 있었다.
| 기간 | 작업 |
|---|---|
| 1주차 | Git 브랜치 전략 수립, GitHub Actions 도입 |
| 2주차 | API 자동 테스트 도입 (Apidog 활용) |
| 3주차 | Docker 패키징, 자동 테스트 환경 구축 |
| 4주차 | Graceful 릴리스, 롤백 & DB 안전 마이그레이션 |
첫 1주일은 학습 비용이 들었지만, 2주차부터 효율이 오르기 시작했다.
4주차에는 배포 작업이 거의 자동화됐다.
CI/CD를 도입해도, 장애는 일어난다.
중요한 것은, 장애가 일어났을 때 빠르게 복구할 수 있는가다.
내가 도입한 롤백 전략은:
특히 Feature Flag는 편리했다.
신기능을 릴리스해도, 처음에는 10% 사용자에게만 공개. 문제가 없으면 점차 100%로 확대.
만약 문제가 생겨도, 코드를 롤백하지 않고 Feature Flag를 끄기만 하면 대응할 수 있다.
CI/CD를 도입한 지 1년이 지났다.
지금 돌이켜보면, CI/CD는 단순한 도구가 아니라 개발 문화라고 느낀다.
쿠팡(Coupang)의 사례를 봐도, CI/CD는 한국 시장에서도 충분히 실용적이다.
소규모 팀도 저비용으로 도입할 수 있다.
만약 당신이 새벽 2시에 서버에 SSH 접속해서 식은땀을 흘리고 있다면, 지금 당장 CI/CD를 배우기 시작하길 바란다.
내가 그랬듯이, 당신의 개발 경험도 극적으로 바뀔 것이다.
이 글이 도움이 되었다면 꼭 공유해주세요.
질문이나 댓글이 있다면 부담 없이 남겨주세요.
Q1: CI/CD란 무엇인가요?
A: 코드의 통합·테스트·배포를 자동화하여, 개발부터 프로덕션까지 안전하게 흐르게 하는 방법입니다. 수동 작업을 줄이고, 배포 빈도와 품질을 향상시킵니다.
Q2: 백엔드용 추천 도구는?
A: GitHub Actions, Jenkins, GitLab CI가 주요합니다. 소규모 팀이라면 GitHub Actions가 도입하기 쉽고, 대규모라면 Jenkins나 GitLab CI가 유연성이 높습니다.
Q3: CI/CD로 신뢰성이 향상되나요?
A: 네. 자동 테스트와 작은 릴리스를 반복하면 장애 발생률과 복구 시간을 대폭 단축할 수 있습니다. 우리 팀은 장애 발생률이 20%에서 5% 미만으로 떨어졌습니다.
Q4: CI/CD에서 추적해야 할 지표는?
A: 배포 빈도, 변경 리드타임, 변경 실패율, 평균 복구 시간(MTTR) 4가지입니다. 이것들을 추적하면 CI/CD의 효과를 정량적으로 측정할 수 있습니다.
Q5: 데이터베이스 마이그레이션도 안전하게 할 수 있나요?
A: 네. 호환성 있는 마이그레이션, 스테이징에서의 검증, 롤백 스크립트로 안전하게 실시할 수 있습니다. 단계적 릴리스를 염두에 두는 것이 중요합니다.
이 글은 수동 배포의 위험성과 CI/CD의 중요성을 생생하게 보여주는 경험담입니다. 작년 여름, 새벽 2시에 SSH로 서버에 접속해 배포하던 중 마이그레이션 스크립트에서 한 줄을 빠뜨려 서비스가 중단되고, 사용자 불만이 폭주한 사건을 계기로 작성자는 CI/CD를 진지하게 배우기 시작합니다. nel net