Accelerate
이 글은 Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations를 번역, 의역, 재구성한 글입니다.
[데브옵스(DevOps)의 중요성]
시장에서 성공하려면, 사업은 반드시 두 가지 요소를 남들보다 탁월하게 수행해야 한다.
(1) 빠르게 고객의 요구를 인지하고 이해하기 위해 시장에서 적극적인 활동을 수행하는 것
(2) 규제 및 법안이나 경제적 변화나 보안 위협과 같이 사업의 운영에 큰 영향을 미치는 잠재적 위험에 대한 예측과 대응
현대 사회에서 이 두 가지 요소를 수행하는 데에 있어서 중요한 역할을 수행하고 있는 것이 바로 소프트웨어 혹은 기술이다. 소프트웨어는 사업 운영 보조를 넘어 그 자체로 제품의 역할을 수행하게 되면서, 소프트웨어를 만들고 관리하는 것의 중요성은 더더욱 커지고 있다. 불안정한 소프트웨어 개발 및 배포의 과정은 사업의 근간을 흔들 수 있을 정도로 그 영향력은 막강해지고 있다.
데브옵스(DevOps)는 위와 같은 맥락으로 등장했다. “어떻게 해야 확장성 있는 방식으로, 보안이 뛰어나면서 탄력적이며 빠르게 발전하는 분산 시스템을 구축하여 소프트웨어를 개발할 수 있을까?”라는 고질적인 물음이 반복되면서 말이다. 데브옵스는 신속하게 소프트웨어 애플리케이션을 개발하고 운영할 수 있게 하여, 비즈니스 가치를 높이고 여러 위험에 대한 대응 능력을 개선하는 환경과 문화를 의미한다.
데브옵스의 목적 자체는 소프트웨어의 개발 효율성과 사업적 효과를 늘리기 위한 것이었지만, 많은 조직들이 스스로의 데브옵스 역량에 대해 과대평가하거나, 잘못 이해하는 등으로 사업의 발목을 잡기도 한다. 그렇다면 조직의 데브옵스 역량은 어떻게 더 정확히 측정될 수 있으며, 이를 어떻게 활용할 수 있을까?
[많은 개발 조직이 고통받는 이유 1: 고착화된 성숙도(maturity) 기반 모델의 한계]
오랜 시간동안 소프트웨어 업계는 성숙도 기반 모델을 중심으로 운영되어 왔다. 성숙도 기반 모델이란, 완성 혹은 목표 상태를 달성하면 프로젝트나 과정을 마무리하는 것을 의미한다. 즉, 단계별(lock-step) 혹은 선형적인(linear) 접근 방식을 취해, 팀이나 조직이 동질적인 기술, 도구, 역량을 기초로 순차적인 과정을 거쳐나가는 것이다.
하지만 현실은 그렇게 작동하지 않는다. 기술, 시장, 고객들은 이전보다 더 빠른 속도로 변화하며, 기업은 이렇게 변화무쌍한 요소들을 기민하게 인지해야 한다. 또한, 제품을 만드는 과정에 참여하는 사람들은 단계별로 달라질 수 있을 뿐만 아니라, 업무의 형태도 사업의 필요에 따라 천차만별로 달라진다. 그렇기에 대부분의 성숙도 기반 모델은 단순히 ‘만드는 것’에 집중하거나 ‘만드는 도구’ 자체에 집중하여 허울뿐인 지표로 전락하는 경우가 많다.
역량 기반 모델은 이렇듯 기술 및 비즈니스 환경이 끊임없이 변화한다는 것을 전제로 하며, 지속적인 개선의 원칙을 기반으로 ‘완료’의 개념에서 벗어나 꾸준히 더 나아질 수 있는 방법을 찾는 데에 초점을 맞춘다. 즉, 만드는 것 자체에 집착하는 것으로 벗어나, 실질적으로 조직에 어떤 성과를 가져오는지에 대한 ‘성과’에 집중하는 것이다.
즉, 역량 기반 모델은 변화하는 환경에 유연하게 대응하여, 조직이 실질적으로 어떤 부분을 개선해야하는지 그리고 어떤 역량을 새롭게 취해야하는지 등 필요에 맞춘 방식으로 빠르게 조직을 움직여나갈 수 있도록 이끌어준다. 지금 당장 최고의 수준이라고 해서 1년 후에도 최고의 수준을 유지하는 세상은 이미 지나갔다. 최고의 성과를 내는 조직은 해마다 지속적인 성장을 찾아나가며, 어제의 성취에 집착하지 않는다.
[많은 개발 조직이 고통받는 이유 :) 잘못된 ‘생산성(productivity)’에 대한 집착]
수많은 개발 조직들은 ‘생산성’이라는 이름 하에 측정하는 것들이 많다. 하지만 ‘생산성’이 무엇을 의미하는 걸까? 하지만 그들 중 대부분은 정말 상품을 많이 찍어내듯이 코드를 많이 찍어내면 되는 것처럼 행동하는 경우가 많다. 이러한 이유로 조직적 성과보다는 ‘어디에 쓰일지는 모르겠는 무언가를 얼마나 많이 만들어 냈는지’에 집착한다. 이런 상황을 만들어내는 대표적인 지표들은 (1) 코드 라인 수, (2) 개발 속도(velocity), (3) 시스템 활용률(utilization)이다.
(1) 코드 라인 수
특히, 코드 라인 수는 매우 오랜 기간 활용된 지표로, 예전 일부 기업에서는 개발자가 주당 작성한 코드 라인 수를 기록하도록 하기도 했다. 하지만 상식적으로는 같은 기능이라면 1,000줄의 코드보다 몇 줄의 코드로 해결할 수 있는 것이 훨씬 효율적이다. ‘코드 라인 수’에 집착하는 조직은 그렇게 그 조직은 불필요하게 코드가 비대해지고, 유지보수나 변경에 있어서 대혼란을 빚는다.
가능하다면, 코드 수를 줄이고, 심지어는 간단한 사업 프로세스 변경을 통해 코드를 아예 작성하지 않는 상황을 만들어내는 것이 이상적이다. 물론, 그렇다고 해서 아무도 이해하지 못할 코드를 만들어내야 한다는 말은 아니다. 최적화된 방식으로, 협업에 있어서 서로 이해하기 쉽고, 유지보수가 용이한 수준으로 지속가능한 코드 작성이 필요하다는 것이다.
(2) 개발 속도
애자일 방법론이 유행하면서 개발 속도에 대한 측정이 인기가 많아졌다. 개발 속도란, 특정 팀이 스프린트마다 얼마나 많은 작업을 완료할 수 있는지를 나타내는 지표다. 일반적으로 사용자 스토리(User Story)에 대해 스토리 포인트를 할당하고, 한 스프린트에서 완료한 총 스토리 포인트를 벨로시티로 측정하는 것이다. 예를 들어, 첫 번째 스프린트에서 30포인트, 두 번째 스프린트에서 25포인트를 완료했다면 벨로시티는 평균 27.5포인트 정도가 된다. 그리고 남은 작업이 100포인트라면, 약 4번의 스프린트가 필요할 것임을 알 수 있다.
개발 속도는 팀의 작업 역량을 예측하는 도구이자 심지어는 팀 간 비교를 위한 지표로도 사용하기 시작되었다. 하지만 개발 속도는 생산성 지표로 사용하는 데에 본질적으로 문제가 많다. 먼저, 개발 속도는 절대적인 수치가 아니라 팀의 역량, 개발물의 맥락과 난이도 등 서로 다른 환경과 맥락에 영향을 받는 지표다. 그리고 이를 팀간 비교 지표로 삼거나 인센티브로 사용할 경우, 의도적으로 자신의 팀의 속도를 높이기 위해 타 팀에게 악영향을 끼치거나 지표를 왜곡하여 보고하는 등의 현상이 발생할 확률이 크다. 즉, 생산성을 높이기는 커녕 팀 간의 협업도 박살내는 비극을 초래한다.
(3) 활용률
활용률이란, 사용 가능 시간 중 실제로 작업에 사용된 시간의 비율을 나타내는 것이다. 즉, ‘개인이 얼마나 바쁘고 빡세게 일하고 있는가?’를 측정하는 지표다. 예를 들어, 한 사람이 8시간 근무하는데 6시간을 실제 업무에 사용했다면 75%의 활용률을 보이는 것이다. 개발 생산성에서 지칭하는 활용률이란, 개발자가 근무 시간을 해당 개발에 얼만큼의 시간을 투입했는지를 의미한다.
작업 시간을 온전히 100%를 꽉 채우면 생산성이 높을 것이라고 생각하겠지만, 많은 사례에서 틀렸음이 증명되고 있다. 현실에서는 작업 하나만이 존재하지 않는다. 여러 맥락에서 수많은 일들이 예측할 수 없이 발생하며, 여러 작업들이 대기 상태에 있기 마련이다.
수학의 대기 이론(Queueing Theory)에 따르면 활용률이 증가하면 대기열은 길어지고, 대기열이 길어지면 총 처리 시간(lead time, 작업 요청부터 실제 작업 완료까지 걸린 시간)도 길어진다. 즉, 활용률이 극도로 높아지면, 팀이 어떤 작업을 완료하는 데에 걸리는 시간이 기하급수적으로 높아진다. 그렇기에 ‘진짜 생산성’을 고려하는 조직이라면, 단순히 활용률뿐만 아니라 업무들의 총 처리 시간까지 고려한 효과적인 운영이 필요하다.
[잘못된 지표로 인한 비극, 그리고 그 비극을 막으려면 어떻게 해야하는가?]
위와 같은 잘못된 생산성 지표들을 사용하면 벌어지는 비극은 다음과 같다. 이러한 지표들을 목표로 삼는 조직들은 개발팀에게는 ‘처리량(throughput)’, 운영팀에게는 ‘사업 안정성(stability)’이라는 것을 성과 지표로 삼는다.
개발팀은 코드 양만 늘리면 되기 때문에 제대로 작동하지 않거나 유지 보수에 있어서 비효율적인 코드들을 남발하기 시작한다. 이에 반해, 사업 운영팀은 이런 코드 남발을 막으려고 이상하고 복잡한 체계를 갖추며 어떻게든 새로운 배포를 막기 위한 혼란의 벽(wall of confusion)을 세운다.
개발 조직의 성과를 성공적으로 측정하려면 두 가지 핵심 요소를 고려해야 한다. (1) 개발 산출물 자체가 아니라 실질적인 영향에 집중하는 것이며, (2) 개별 팀의 성과가 아닌 조직 전체적인 성과에 초점을 맞추는 것이다. 단순히 많은 작업을 했다는 것을 자랑하는 것이 아니라, 조직 목표 달성에 실질적으로 기여하는지에 대해 집중하는 것이다.
[그렇다면 무엇을 측정해야 하는가?]
(1) 개발 작업 소요 시간 (delivery lead time)
소프트웨어 제품 개발에서는 크게 두 가지의 총 작업 소요시간이 존재한다. 첫 번째는 제품 또는 기능을 설계하고 검증하는 ‘설계 기간’이며, 기능을 구현하고 제공하는 ‘개발 기간’이다. 설계 단계는 작업 시작 시점을 명확히 정의하기 어렵고 변동성이 큰 반면, 개발 기간은 측정이 상대적으로 쉽고 변동성이 적다.
따라서 소프트웨어 제품 성과를 측정할 때는 개발 요청부터 고객에게 배포하는 시간을 중심으로 평가하는 것이 효과적이다. 짧은 총 작업 소요시간은 빠른 피드백을 가능하게 하여 개발 방향을 신속하게 수정할 수 있게 해준다. 구체적으로 정의하자면, 개발 총 작업 소요 시간이란 "코드가 커밋된 시점부터 프로덕션에서 정상적으로 실행될 때까지 걸리는 시간"으로 정의한다.
(2) 배포 빈도 (deployment frequency)
배치(batch)란, 여러 개의 작업을 한꺼번에 묶어서 처리하는 단위를 의미한다. 배치 크기를 줄이면 작업 처리 시간(cycle time)이 줄어들며, 작업 변동성(variability in flow)가 감소한다. 또한, 빠른 피드백으로 잠재적인 위험과 추가 소요 자원(overhead)를 줄여 전체적인 효율성을 향상시킨다.
소프트웨어 개발 작업 자체에서는 배치 크기를 일률화하여 명확히 규정하기 힘들기에, 이에 대한 대안으로 ‘배포 빈도’가 효과적일 수 있다. 배포를 짧은 주기로 한다는 것은, 소프트웨어의 작업을 효율적인 형태로 나눈다는 것을 간접적으로 의미할 수 있기 때문이다. 개발 작업 총 작업 소요 시간과 배포 빈도는 소프트웨어 개발의 실질적인 속도(tempo)를 측정하는 지표로 사용될 수 있다.
(3) 서비스 복구 시간 (time to restore service)
팀이 성과를 개선하는 과정에서 시스템 안정성을 희생시키고 있지는 않은지도 확인해야 한다. 전통적으로 신뢰성(reliability)은 서비스가 제대로 작동하지 않는 때의 간격인 ‘고장 간 평균 시간(mean time between failures)’으로 측정됐다. 하지만 현대 소프트웨어 시스템은 복잡하고 빠르게 변화하므로 "실패를 피할 수 있느냐"보다 "얼마나 빨리 복구할 수 있느냐"가 핵심이다. 따라서 서비스 장애(예: 예기치 않은 다운, 성능 저하) 발생 시 주요 애플리케이션 또는 서비스가 복구되는 데 걸리는 시간을 측정하는 것이 적합하다.
(4) 변경 실패율 (change fail rate)
변경 실패율이란, 프로덕션 변경(예: 소프트웨어 릴리스, 인프라 구성 변경 등) 중 실패한 비율을 의미한다. 린(Lean) 관점에서 보면, 이는 "완료된 작업 중 정확하게 수행된 비율"과 동일하며, 핵심 품질 지표다. 즉, 조직의 주요 서비스에서 배포된 변경 사항 중, (1) 서비스 성능 저하 또는 장애 발생, (2) 추후 수정이 필요한 경우 (예: 핫픽스, 롤백, 패치, fix-forward 등)과 같은 문제가 발생한 비율을 측정하는 것이다.
[역량 기반 모델에 기초한 데브옵스의 영향]
연구에 따르면, 데브옵스는 조직의 개발 역량에 있어서의 조직간 차이의 격차를 더욱 심화시키는 것으로 파악된다. 2017년 연구에 따르면, 데브옵스는 다음과 같은 영향을 보여줬다.
(1) 코드 배포 빈도 46배 증가
(2) 개발 총 작업 소요시간 440배 단축
(3) 서비스 복구 평균 시간 170배 단축
(4) 변경 실패율 5배 감소
오랜 기간 동안 IT 업계에서 속도와 안정성 둘 중 하나를 선택해야 한다고 생각해왔지만, 이러한 믿음과 달리 품질을 프로세스에 내재화하면, 속도와 안정성 모두를 동시에 확보할 수 있음을 알 수 있다. 즉, 올바른 역량을 향상시키고 이에 집중한다면, 소프트웨어 개발에 있어서 성과는 더더욱 커질 것이다.