CI 가 존재하는 이유 자체
CI 가 정상이 되기 전에는, 소프트웨어가 release cycle 로 ship 됐어. 팀이 feature branch 에서 몇 주, 때로는 몇 달 일했어. cycle 끝에 모든 branch 가 동시에 trunk 로 merge 하려 했지. 이게 이름이 있었어: integration hell.
Integration hell 이 실제로 어떻게 보였냐면:
- 두 엔지니어가 같은 함수를 서로 호환 안 되는 방식으로 refactor 했어. merge 날까지 둘 다 몰랐고.
- 한 팀의 database schema 변경이 다른 팀 branch 의 query 를 깨뜨렸어 — 그 branch 는 3주 동안 아무도 안 만졌는데.
- 모든 branch 가 합쳐졌을 때만 드러나는 방식으로 build 자체가 깨졌어 — 각 branch 는 isolation 에서는 green 이었거든.
- Release 가 feature 때문이 아니라 그냥 merge 하는 데 2주 써서 늦어졌어.
CI 가 이걸 어떻게 고치냐
CI 는 끝의 거대한 merge 한 번을 가는 길에 작은 merge 수백 번으로 바꿔. 각 작은 merge 가 conflict 를 즉시 — context 가 신선하고 feature 하나만 위험할 때 — 드러내. Conflict 비용이 exponential 이 아니라 linear 로 유지돼. Merge 작업이 이미 끝나 있어서 release 날짜가 예측 가능해져.
이건 옛날이 얼마나 나빴는지에 대한 향수가 아니야. Integration hell 은 오늘도 일어나 — long-lived branch 가 drift 하게 두는 팀, release branch 에만 CI 돌리는 팀, 응급 commit 때 CI 우회하는 팀. Discipline 이 빠진 자리에 패턴은 반복돼.