제품 책임자와 개발자의 관점에서 소프트웨어 개발에서의 일정·작업 추정의 필요성과 문제점, 기술 부채, 데브옵스와 흐름(Flow)의 역할을 다룬 글
URL: https://thorsell.io/2025/12/07/estimates.html
Title: Estimates – a necessary evil?
Product Owner: 안녕,
Feature F개발하는 데 얼마나 걸릴 것 같아?Developer: 글쎄요. 아직 손도 안 댔고, 옛날 이슈들이랑 얽혀서 일이 커질 것 같은데요.
추정치는 여러 가지 변장을 하고 나타나지만, 트렌치코트 속을 들여다보면 결국 질문은 항상 같다.
"X를 하는 데 얼마나 오래 걸리고, 어느 정도의 리소스가 필요할까?"
내가 _개발자 모자_를 쓰고 있을 때, 이 질문에 답하려고 하면 짜증이 날 때가 많다. 추정하는 건 어렵고(쉬우면 PO가 직접 했겠지) 대체 이 추정치가 왜 중요한지 이해하기 힘들 때도 많다.
반대로 _제품 책임자(PO) 모자_를 쓰고 있을 때, 추정치는 제품의 단기 그리고 장기 라이프사이클을 계획하기 위해 반드시 맞춰 넣어야 하는 퍼즐 조각이다.
이 글에서는 두 관점을 모두 조금 더 깊게 들여다보고 싶다. 개발자들에게는 왜 추정치가 PO에게 중요한지 이해시키고, PO에게는 왜 개발자들이 자기 일 추정하는 걸 그렇게 싫어하는지 이해시키는 데 도움이 되었으면 한다.
PO(제품 책임자)로서 나는 시장과 고객의 니즈를 파악하고, 이것을 _개발자들이 실제 제품 기능으로 구현할 수 있는 기능 요청_으로 번역하는 일을 한다. 방식은 각기 다르지만, 대부분의 조직에는 일종의 백로그가 있고, 여기에 _조치가 필요한 것들_이 개발자나 팀이 집어 들 때까지 쌓여 있다. 우리는 이런 _것들_을 유저 스토리, 이슈, 티켓, 태스크, 그리고 아마 이 외에도 수많은 이름들로 부른다… 이 글에서 중요한 건, 백로그에 있는 항목들이 우리 제품에 구현될 후보들이고, 이를 정리하고 우선순위를 정하는 것이 PO의 역할이라는 점이다.
왜 백로그에 우선순위를 매겨야 할까?
백로그로 들어오는 항목의 유입 속도는 (거의 항상) 개발자들이 그것을 처리하는 속도보다 빠르기 때문이다. 즉, PO가 계속해서 _시장과 고객의 니즈를 학습_하고 그에 맞춰 백로그에 우선순위를 매기지 않으면, 개발자들은 정작 사용자들이 원하지 않는 기능을 구현하게 될 수 있다. 최악의 경우? 기존 사용자는 이탈하고 신규 사용자는 유입되지 않아, 결국 회사가 파산할 수도 있다.
위의 이야기는 – 부디 – 이해되기를 바라지만, 아직 추정치가 구체적으로 왜 필요한지는 충분히 짚지 못했다. 안타깝게도, PO의 일은 항상 시장이 요구하는 순서대로만 우선순위를 매기면 되는 정도로 단순하지 않다. 대부분의 경우, PO는 이미 대외적으로 공지된 릴리스 날짜와 그에 따른 기대치도 함께 관리해야 한다.
나는 릴리스 날짜가 미리 공지되는 걸 정말 싫어한다. 몇 달 전에 박제된 릴리스 날짜(보고 있어요, 12주 단위 SAFe)보다 더 끔찍한 건, 릴리스 콘텐츠까지 미리 못 박아 두는 거다. 불행하게도 둘 다 흔하고, 자주 세트로 나온다.
엄청나게 큰 기능 하나가 들어 있는 백로그를 상상해 보자. 시장에서 강하게 요구되지만 구현하려면 시간과 리소스가 많이 드는 기능이다. 같은 백로그에는 그보다는 덜 요구되지만 상대적으로 작은 기능 몇 개도 같이 들어 있다. PO 입장에서는 다음 릴리스에 이 큰 기능을 포함시키고 싶다. 하지만 다음 릴리스 날짜는 그리 멀지 않다. 이런 상황에서, PO가 이 큰 기능에 우선순위를 줬는데 _이미 공지된 릴리스 날짜_까지 완료되지 못하면, 그 릴리스는 심각하게 내용이 빈약해지고 실패로 간주될 것이다. 그런 경우라면 PO는 차라리 작은 기능 몇 개를 넣는 쪽을 택할 것이다. 더 안전하지만, 그만큼 보상(가치)은 작다.
바로 이 지점이 PO에게 추정치가 그렇게 중요한 이유다. PO는 팀의 백로그에 우선순위를 매길 때마다 위와 같은 방정식을 계속 돌려야 한다. 리스크와 보상의 균형을 끊임없이 맞추는 행위다. PO는 자신이 제안하는 기능이 가져올 파급 효과를 더 잘 이해하기 위해 전문가들(개발자)에게서 도움을 받을 수밖에 없다. 만약 PO가 각기 다른 _작업 패키지_가 어느 정도 크기인지 이해하지 못하면, 자신의 일을 효과적으로 수행할 수 없다.
이제 PO가 한 명이 아니라 여러 명이라고 해 보자. 이들은 더 큰 제품의 서로 다른 _부분_을 담당하고 있고, 릴리스의 날짜 와 내용 모두를 서로 조율해야 한다. 최종 제품의 향후 기능들을 설명하는 _메인 백로그_가 있고, 각 팀이 구현과 통합을 담당해야 하는 퍼즐 조각이 배정된 _팀별 백로그_도 있을 것이다.
이 상황이 고통스러운 이유는 여러 가지가 있지만, 가장 명확한 문제는 이렇다. 제대로 동작하는 릴리스를 만들려면, PO들이 _메인 백로그_의 우선순위에 합의해야 하고, 그 결정이 다시 _팀별 백로그_의 우선순위에 영향을 주게 된다. 각 PO는 자신이 책임지는 퍼즐 조각(들)을 하나의 완성된 기능으로 구현·통합하는 데 얼마나 걸리고, 비용은 얼마나 들지에 대한 정보를 얻어야 한다. 이때 필요한 도구는?
바로 추정치다.
프로그래밍은 공예이자 예술이다. 어느 정도는 나만의 예술이다. 나는 까다로운 문제 하나에 완전히 몰입했다가, 며칠 뒤 처음엔 불가능해 보였던 문제의 해답을 들고 다시 수면 위로 올라올 때 가장 행복하다. 개발자로서 나는 가능한 최고의 제품을 만들고 싶다. 지름길을 싫어한다. 대충 때운 해결책을 싫어한다. _땜빵(fix)_을 싫어한다. 단 한 번의 지름길이나 땜빵이 제품을 망치기 때문이 아니라, 그것들이 초래하는 기술 부채(technical debt)가 시간이 지날수록 누적되어 결국 안에서부터 제품을 좀먹고, 점점 더 손대기 힘들어지게 만들고, 결국엔 망가지게 만들기 때문이다.
기술 부채는 – 내 생각에 – PO와 개발팀 사이 갈등의 가장 큰 원인이다. 기술에 익숙하지 않은 PO는 기술 부채가 제품에 얼마나 치명적인지, 그리고 기술 부채가 많은 코드베이스에서 일하는 것이 개발자에게 얼마나 고통스러운지 제대로 이해하지 못한다.
다른 말로 해 보자. 내가 어떤 신규 기능을 구현하라는 업무를 맡았는데, 코드 속에서 명백하게 구리거나, 에러를 만들 법하거나, 그냥 별로인 부분을 발견했다면, 나는 내가 손을 댄 뒤의 코드를 처음보다 더 나은 상태로 두고 싶다. 이런 부채를 _한 번_쯤은 갚지 않고 넘어간다고 해서 세상이 끝나진 않겠지만, 일반화했어야 할 부분을 하드코딩으로 대충 땜빵해 두면, 나중에 반드시 발목을 잡는다. 그리고 몇 달 동안 의존성 업데이트를 미루다가, 어느 날 갑자기 Package 1을 꼭 올려야 하는 상황에 처했는데, 이 패키지가 더 최신 버전의 Packages 2 & 3에 의존하고, 이 둘은 또 프레임워크 업그레이드를 요구한다면… 그때 작업 중인 기능의 개발 기간은 확 늘어날 거라는 점만 말해 두겠다.
PO가 “Feature F 구현하는 데 얼마나 걸릴까?”라고 물을 때, 단지 그 기능을 위한 코드를 작성하는 데 드는 시간만을 개발자에게 묻는 것이 아니다. 좋은 PO는 신규 기능 구현이 반복적인 과정이며, _통합 지옥(integration hell)_이라는 게 실제로 존재한다는 것도 이해한다. 더 좋은 PO라면, 사실상 개발팀에게 _그 기능을 구현하는 동안 얼마나 많은 예기치 못한 문제를 만나게 될지_까지도 추정해 보라고 요구하는 셈이라는 것을 이해한다.
바로 이 디테일, 즉 예기치 못한 문제들 – PO가 개발자에게 예측해 달라고 요구하지만, 정의상 예측 불가능한 것 – 이 핵심이다. 예측 불가능한 것을 예측하는 건 – 정의상 – 불가능하다.
내가 만나 본 많은 개발자는 불확실성을 싫어한다. 코딩에서 가장 좋아하는 것 중 하나가 바로 그 결정론적인 특성이다. 같은 프로그램을 여러 번 실행하면 항상 같은 결과를 돌려준다.1 하지만 우리가 코드를 작성하면서 겪는 여정은 그다지 결정론적이지 않다.
코딩을 많이 하고 특정 코드베이스에 익숙해질수록 추정치는 더 정확해지는 건 사실이다. 하지만 불과 며칠 전만 해도, 나는 어떤 이슈를 _대략 이틀_이면 끝날 거라고 추정했었다. 그런데 작업을 하다 보니, 겉보기에는 단순한 변경이 수년 전에 촘촘하게 결합돼 버린 공용 컴포넌트의 업데이트를 요구한다는 걸 깨달았다. 그 코드를 건드리는 순간 수십 개의 테스트가 동시에 깨졌고, 하나하나가 숨겨진 의존성을 드러냈다. 그것들을 고치다 보니 다시 옛날 패턴에 기대 있는 또 다른 모듈이 튀어나왔다. 작업 도중 우리는 결국 원래의 변경을 안전하게 적용하려면 전체 플로우를 리팩터링해야만 한다는 결론에 이르렀다. 내 “이틀짜리 태스크”는 순식간에 2주짜리 고고학적 소프트웨어 발굴 작업으로 변했다.
우리가 남기는 기술 부채에 크게 신경 쓰지 않고 일을 처리했다면 더 빨리 끝낼 수 있었을까? 아마도.
그 대신 미래에 2 개월짜리 발굴 작업을 맞닥뜨렸을까? 아마도.
메리엄-웹스터(Merriam-Webster) 사전에 따르면, _estimate_는 다음과 같이 정의된다.
어떤 것의 가치, 중요성 등을 잠정적이거나 대략적으로 판단하는 것.
_추정치(estimate)_의 정의 자체가 그것이 본질적으로 잠정적(tentative) 이거나 _대략적(approximate)_이라는 뜻이다. 개발자로서 나는 이 정의의 _or(또는)_를 "둘 다일 수도 있다"고 해석하고 싶다.
내가 커리어를 소프트웨어 개발자로 시작했을 때, 사실 추정치에 큰 불만이 없었다. 우리는 백로그를 정제(refine)했고, 나는 기꺼이 여러 항목에 대한 추정치를 제공했다. (1) 막 대학을 졸업했고, 좋은 성과를 내고 까다로운 사람처럼 보이고 싶지 않아서 그랬고, 더 중요한 이유는 (2) 내가 내놓은 추정치가 곧 나를 향한 무기처럼 쓰이게 되리라는 사실을 그때는 아직 몰랐기 때문이다.
곧 나는 우리 팀이 내놓는 추정치가 _추정치_로 해석·사용되지 않는다는 걸 깨달았다. 그것들은 _마감일(deadline)_로 쓰였다. 우리가 하나의 기능을 합리적인 컴포넌트들로 쪼개고(이 쪼개기 자체도 불확실성이 가득한, 오류 가능성이 높은 작업이다) 각 부분을 적당히 추정하면, PO는 종종 그 부분들의 합을 동료들에게 이렇게 전달하곤 했다. “이때까지면 끝납니다.”
그러자 두 가지 일이 벌어졌다.
이제 추정치는 더 이상 추정치가 아니었다. 말이 안 되는 기대치에 대해 책임을 지지 않기 위한 안전 가드레일이 되어 버렸다.
문제가 보이는가?
해결책이 보이는가?
내가 보기엔, 추정치의 근본적인 문제는 "기대치"에서 비롯된다. 어딘가에서 누군가가, 제품 사용자/고객에게 _무언가_를 약속하는 순간, 조직의 나머지 사람들은 그 기대치를 맞추기 위해 살게 된다. 작은 회사에서는 그 소통을 PO가 직접 할 수도 있지만, 큰 조직에서는 PO도 개발자들만큼이나 제품 로드맵에 대한 발언권이 없다.
“해결책”은 간단해 보인다. 새로운 기능을 미리 대외적으로 알리지 말자. 어느 정도는 임의로 정한2 마감일을 세우는 행위를 멈추자. PO는 어떤 기능을, 어떤 순서로 원하는지만 개발자들에게 말해 주고, 개발자는 자신들이 가장 잘하는 일을 하게 두자. 코딩!
하지만 이런 마감일에도 이유는 있다. 연말정산을 도와주는 제품처럼, 특정 시기에만 쓸 수 있는 제품을 만든다면, 그 시점을 놓치는 건 그 해의 전체 매출 기회를 놓친다는 의미다. 리소스(대부분 직원 급여 형태)는 이미 프로젝트에 투입됐고, 추가 매출이라는 보상이 없다면, 그 리소스를 회수할 다른 방법을 찾아야 할 것이다. 그리고 그 방법은 보통 비용 절감, 즉 구조조정을 의미한다.
그래서 결국 이 게임에 참여하는 것이 모두의 이익이다. 우리는 서로의 일을 돕기 위한 – 좋다고 말하긴 어렵지만 현재로서는 우리가 아는 최선의 – 방법으로, 이 추정치 게임을 계속한다.
내가 이 기회에 DevOps 이야기를 안 할 거라고 생각했다면, 그건 오산이다.
DevOps에서 핵심 개념 중 하나는 _플로우(Flow)_다. 이는 조직이 병목을 줄이고, 제품의 새 버전을 더 빠른 속도로 전달할 수 있게 하는 능력을 설명한다. 플로우가 좋다는 것은 곧, 제품을 자주 배포·업데이트할 수 있다는 뜻이다.
DevOps의 개념이 추정치 문제를 직접적으로 해결해 주는 것은 아니지만, 소프트웨어 전달과 관련된 리스크를 줄여 줄 수 있는 여러 도구를 제공한다. 플로우는 우리가 기술 부채를 어떻게 다뤄야 할지, 의존성 관리를 어떻게 해서 뒤처지지 않을지에 대한 힌트를 준다. 또한 제품 라이프사이클에서 어떤 문제가 발생하는지 찾아내고, 그것들을 어떻게 제거할 수 있을지 이해하는 데도 도움을 준다.
플로우는 DevOps의 세 가지 길(The Three Ways) 중 하나다. 더 알고 싶다면 언제든 연락해도 좋다. 나는 DevOps 관련 여러 주제에 대해 발표를 하고 있고, 여러분 회사의 상황에 맞게 맞춤화한 DevOps 교육을 하러 직접 찾아갈 수도 있다.
영어에서 정의하는 본래 의미의 추정치(estimate) 자체가 문제인 건 아니다. 문제는 _추정치_가 예측, 마감일, 개발자에게 압박을 가하는 수단으로 취급될 때 생긴다. 오늘날 우리 업계에서 쓰이는 방식의 추정치는 사람들을 다치게 하고, 조직의 심리적 안전감을 떨어뜨린다. 나는 개발자들이 투명하게 일할 수 있고, 개발이 진행되는 동안 계속해서 추정치를 갱신해 공유할 수 있는 방식으로 일한다면 훨씬 나을 거라고 믿는다.
한편, 제품 책임자도 똑같이 사람이다! 개발자로서 우리는 PO도 압박을 받는 위치에 있다는 걸 이해해야 한다. 우리는 그들을 도와야 하고, 그들을 돕는 가장 좋은 방법은 개발 진행 상황을 지속적으로 공유하고, 처음에 제시했던 추정치를 크게 바꿔야 할 만한 문제가 생겼는지 수시로 알려 주는 것이다.