공수 산정 (2) 기능점수는 왜 42% 낮게 나왔나 — 표준이 스스로 예고한 한계
단일 방법으로 낸 견적은 그 방법의 편향을 그대로 상속합니다. 그래서 서로 입력이 겹치지 않는 네 가지 방법으로 같은 프로젝트를 각각 독립 산정한 뒤 교차 대조해 봤습니다. 둘은 2.4% 차로 수렴했고, 하나는 42% 낮았고, 하나는 애초에 다른 것을 재고 있었습니다.
배경은 짧게만 적겠습니다. 어떤 외주 건의 개발 문서를 검토하게 됐는데, 발주처가 만든 문서 세트가 꽤 정교했습니다. 기능마다 검증 가능한 수용 기준이 붙어 있고, 선행 의존성이 표로 정리돼 있고, 문서가 임계경로를 스스로 지목했습니다. 덕분에 추정이 아니라 요구사항 ID와 수용 기준에 1:1로 대응하는 계산이 가능했습니다. (이런 문서 체계가 왜 필요한지는 기획 문서의 종류와 체계에서 따로 다룬 적이 있습니다.)
제품 성격만 추상화해 두면 이렇습니다. 여러 채널에서 데이터를 수집해 정제하고 점수화한 뒤 화면에 반영하는 4단 파이프라인이고, 멀티테넌트 SaaS이며, 모든 점수는 원시 데이터까지 역추적 가능해야 하고, 네 개 언어를 지원합니다.
네 가지 방법 — 입력이 겹치지 않도록
교차 검증의 핵심은 방법의 개수가 아니라 입력의 독립성이라는 생각이 들었습니다. 네 방법이 같은 자료를 보고 있으면 네 번 확인한 것이 아니라 한 번 확인한 것을 네 번 적은 것에 불과합니다. 그래서 결과가 아니라 입력이 서로 겹치지 않도록 축을 설계했습니다. (비슷한 문제의식으로 제 블로그 프로젝트 자체를 여러 방법론으로 견적해본 적이 있습니다 — 기능점수·COCOMO·시장 시세로 산정한 기록.)
| 축 | 방법 | 입력 |
|---|---|---|
| 1 | 법정 FP 산식 | 「SW사업 대가산정 가이드」 간이법 + [별표1] 생산성 상수. 공표된 상수만 사용 |
| 2 | 문서 내부 bottom-up | 발주처 문서의 역할 편성 × 요구사항 ID × 수용 기준. 외부 자료 일절 미사용 |
| 3 | 임계경로(CPM) | 각 기능의 선행 의존성 원문으로 의존 그래프를 그려 최장 경로 |
| 4 | 시장 벤치마크 역산 | 유사 제품의 공개된 실측(창업 회고·팀 규모·출시 기간) + COCOMO. 발주처 문서 전혀 미사용 |
수렴 — 입력이 하나도 겹치지 않는 두 방법이 2.4% 차
축2와 축4를 보시면 됩니다. 축2는 발주처 문서 안에서만 계산했고, 축4는 발주처 문서를 한 번도 열지 않고 외부 실측만으로 역산했습니다. 두 축이 참조한 자료는 단 하나도 겹치지 않습니다. 그런데 결과가 이랬습니다.
| 구간 | 축2 (문서 내부) | 축4 (외부 벤치마크) | 차이 |
|---|---|---|---|
| low | 6,400 인시 | 6,500 인시 | 1.5% |
| mid | 9,216 인시 | 9,000 인시 | 2.4% |
| high | 11,600 인시 | 11,000 인시 | 5.5% |
캘린더에서도 같은 일이 벌어졌습니다. 축1을 규정된 팀 편성 기준으로 환산하면 5.43개월, 축3의 임계경로를 한 사람이 순차로 밟으면 5.34개월이었습니다. 법정 산식과 의존 그래프는 서로를 전혀 모릅니다. 그런데 5.3~5.4개월에서 겹쳤습니다.
이 정도 일치는 맞추려고 해서 나오지 않습니다. 우연이거나 조작이려면 네 방법이 동시에 같은 방향으로 틀려야 합니다.
불일치 — 그리고 이걸 숨기면 안 되는 이유
축1(법정 FP 산식)은 5,343 인시였습니다. 축2·축4보다 약 42% 낮습니다. 더 곤란한 것은 축1의 상한이 축2·축4의 하한보다도 낮았다는 점입니다. 세 range가 겹치지도 않았습니다. 오차 범위로 설명할 수 있는 차이가 아니라는 뜻입니다.
여기서 유혹이 생깁니다. 축1을 빼고 9,000만 제시하면 문서가 깔끔해집니다. 하지만 그렇게 하면 어떻게 될까요. 상대가 다른 곳에 FP 검증을 의뢰하는 순간 5,000대 숫자가 나오고, 그 순간 제 문서 전체가 무너집니다. 숫자 하나가 틀린 것이 아니라, 제가 그 숫자를 알고도 숨겼다는 사실이 드러나기 때문입니다.
그래서 먼저 밝혔습니다. 타 개발사에 FP 검증을 의뢰하시면 5,000대 숫자가 나올 것이고 그것이 정상이라고요. 검증자가 발견할 것을 내가 먼저 말하면, 그 발견은 반박이 아니라 확인이 됩니다.
FP는 왜 낮게 나오나 — 네 가지 원인
여기서부터가 이 글에서 가장 실용적인 부분이라고 생각합니다. 「소프트웨어사업 대가산정 가이드」의 기능점수 방식은 국내 SW 사업 견적의 사실상 기준선입니다. 그 기준선이 어떤 사업에서 왜 낮게 나오는지를 알아야, 낮게 나왔을 때 그것이 내 계산 오류인지 방법의 적용 한계인지 구분할 수 있습니다.
① 표준 자신이 FP의 적용 한계를 규정하고 있습니다
가장 먼저 확인할 곳은 가이드 본문입니다. §2.1.5는 'R&D 성격의 소프트웨어개발 사업'과 '사용자에게 식별되는 기능규모에 비해 내부처리 복잡도가 현저히 높아 기능점수 방식의 대가체계 적용이 불합리하다고 인정되는 사업'을 FP 예외로 규정하고 투입공수방식을 허용합니다.
이 프로젝트의 다국어 자연어 처리와 다국가 커넥터가 정확히 후자입니다. 화면에서 사용자가 식별하는 기능은 점수 하나인데 내부 처리 복잡도는 언어 수만큼 곱해집니다. 즉 FP가 낮게 나오는 것은 제 계산이 틀려서가 아니라 표준 자신이 예고한 결과입니다. 이 조항을 모르면 42% 차이를 설명할 방법이 없고, 알면 42% 차이가 오히려 방법의 정합성을 입증합니다.
② 정량 증거 — 13배 괴리
조항 인용만으로는 부족하다는 생각이 들었습니다. "복잡도가 높다"는 주관적 주장으로 읽힐 수 있으니까요. 그래서 숫자로 확인해 봤습니다.
다국어 감성분석 모듈을 FP 간이법으로 세면 전체의 1.3%, 약 68시간으로 계상됩니다. 그런데 발주처 자신의 문서는 이 모듈에 전담 인력 한 명을 배정했고(여섯 개 역할 중 하나이므로 편성의 17%), 임계경로로 지목했으며, 정확도 목표까지 요구했습니다.
| 다국어 감성분석 모듈 | 비중 |
|---|---|
| 발주처 문서의 인력 편성 | 17% |
| FP 간이법 계상 | 1.3% (약 68시간) |
13배 차이입니다. 그리고 이 괴리는 제가 만든 것이 아닙니다. 발주처 문서와 법정 산식이 같은 모듈을 놓고 서로 13배 다르게 평가한 것입니다. 68시간에 네 개 언어의 감성분석을 목표 정확도까지 끌어올릴 수는 없습니다.
이 대목이 실무적으로 가장 강했던 이유는 따로 있습니다. 반박할 대상이 제가 아니라 발주처 자신의 편성이 되기 때문입니다. "그 견적은 부풀려졌다"고 말하려면 먼저 "우리가 이 모듈에 전담 인력을 붙인 것이 과했다"고 말해야 합니다.
③ 비기능 요구사항이 FP에 0으로 잡힙니다
이것도 가이드 원문에 그대로 쓰여 있습니다. §2.1.3은 이렇게 규정합니다.
비 기능 요구사항은 기능점수 산정 대상은 아니지만 개발생산성에 영향을 미치는 품질 요구사항 및 기술 요구사항으로 보정계수 평가 시 사용된다.
애석하게도 이 프로젝트에서 어려운 것은 대부분 비기능 요구사항 쪽에 몰려 있었습니다. 다국어 지원, 모든 점수의 원시 데이터 역추적, 재현성, 테넌트 격리, 감사 로그. 이것들이 FP 본체에는 한 점도 안 잡히고 보정계수로만 간접 반영됩니다.
그런데 여기서 한 번 더 막힙니다. 현행 표준의 보정계수에는 다국어 항목이 아예 없습니다. 규모·연계복잡성·성능요구·운영환경·보안성 다섯 가지뿐입니다. 네 개 언어를 지원하는 자연어 처리의 부담을 반영할 계수가 표준에 존재하지 않는 것입니다.
없는 계수를 만들어 넣을 수도 있었습니다. 그렇게 하지 않았습니다. 표준에 없는 계수를 임의로 추가하는 순간 그 숫자는 법정 산식이 아니라 제 주장이 됩니다. 축1의 값어치는 "공표된 상수만 사용했다"는 데 있고, 거기에 손을 대면 축1은 축2의 복사본이 되어 교차 검증 자체가 무의미해집니다. 그래서 낮게 나온 채로 뒀습니다.
④ FP 계수 자체가 해석에 따라 갈립니다
마지막은 조금 다른 성격입니다. 앞의 셋이 "FP가 구조적으로 못 잡는 것"이라면, 이건 "FP를 세는 사람에 따라 달라지는 것"입니다.
같은 범위를 619 FP로 셀 수도 있었고 970 FP로 셀 수도 있었습니다. 57% 차이입니다. 무엇이 갈랐냐면, 데이터 수집 커넥터를 '채널 유형당 하나'로 세느냐 '플랫폼당 하나'로 세느냐의 차이였습니다. 기능이 늘어난 것이 아니라 경계를 어디에 긋느냐가 달라졌을 뿐입니다.
돌이켜 생각해보면 이것이 FP의 가장 조용한 함정입니다. 산식도 공표돼 있고 상수도 공표돼 있어서 객관적으로 보이는데, 입력을 만드는 단계에 해석이 들어갑니다. 경계 정의가 ±20% 변동의 주된 원인이었습니다. 그래서 FP 결과를 받으면 숫자보다 먼저 물어야 하는 것이 있다는 생각이 들었습니다. "무엇을 하나로 셌습니까?"
축3은 합산하면 안 됩니다
네 개 축이 있으니 평균을 내고 싶어집니다. 그런데 축3은 그 계산에 들어갈 수 없습니다. 임계경로 인시는 총 개발 인시가 아니기 때문입니다.
축2·축4가 재는 것은 총량입니다. 총량은 인원으로 나눌 수 있습니다. 축3이 재는 것은 사슬입니다. 사슬은 나눌 수 없습니다. 성격이 다른 두 값을 더하면 이중 계상이 됩니다.
그래서 축3은 총량 계산에 기여하지 않습니다. 대신 "인원을 늘리면 되지 않느냐"에 대한 반증 형식으로만 기능합니다. 이 이야기는 따로 다룰 만큼 길어서 5편으로 미뤄 두겠습니다.
중앙값을 산술평균으로 잡지 않은 이유
네 축의 전체 range를 놓고 산술 중앙을 내면 약 7,900이 나옵니다. 깔끔한 숫자입니다. 그런데 쓰지 않았습니다.
이유는 단순합니다. 7,900은 어느 방법도 산출하지 않은 값이기 때문입니다. 네 방법 중 무엇도 그 숫자를 낸 적이 없습니다. 산술 중앙은 제가 계산기로 만든 조작값이고, 조작값은 출처를 물었을 때 답할 곳이 없습니다.
반면 9,000은 독립된 두 방법이 실제로 낸 수렴점입니다. 출처를 물으면 축2와 축4를 각각 펼쳐 보일 수 있습니다. 그래서 중앙값은 9,000으로 잡고, 낮게 나온 축1의 5,343은 지우는 대신 range의 low에 그대로 반영하고 문서 전면에 노출했습니다.
결과적으로 range는 넓어졌고 문서는 덜 단정해졌습니다. 다만 그 넓이가 진짜 불확실성의 넓이입니다. 좁은 range는 정확한 것이 아니라 정보를 버린 것일 때가 많습니다.
정리하며
교차 검증의 가치는 일치가 아니라 일치와 불일치를 둘 다 드러내는 데 있었습니다. 처음에는 네 방법이 다 비슷하게 나오길 바랐습니다. 그런데 실제로 문서를 강하게 만든 것은 2.4% 수렴이 아니라 42% 불일치였습니다. 수렴은 "그럴듯하다"까지만 말해주고, 불일치는 "이 방법이 무엇을 못 재는가"를 말해주기 때문입니다.
그리고 불일치를 먼저 공개하는 것이 문서를 강하게 만듭니다. 숨긴 약점은 상대가 찾으면 반박이 되고, 밝힌 약점은 상대가 찾아도 확인이 됩니다. 같은 사실인데 놓인 위치가 다릅니다.
결정적으로 — 어느 축을 택하든 결론이 바뀌지 않았습니다. 방법 간 불일치는 "되냐 안 되냐"가 아니라 "얼마나 안 되냐"에서만 발생했습니다. 가장 낮은 축1의 5,343 인시조차 규정된 기간과 팀 편성 안에 들어가지 않았습니다. 이것이 교차 검증의 마지막 쓸모라는 생각이 들었습니다. 네 방법이 다르게 나왔는데도 결론이 같다면, 그 결론은 방법에 의존하지 않는다는 뜻입니다.
관련 글
소프트웨어 개발 비용, 어떻게 산정할까? - 4가지 방법론과 실제 적용 사례
개인 블로그 프로젝트(42,000줄)를 4가지 비용 산정 방법론으로 분석해봤습니다. 기능점수(FP), COCOMO, 시장 시세, 유사 프로젝트 비교까지 - 각 방법의 원리와 실제 적용 결과를 공유합니다.
공수 산정 (1) 예산에 맞춰 범위를 줄였는데, 그 범위도 예산에 안 맞았습니다
예산이 고정된 외주에서 "이 예산이면 여기까지 됩니다"를 계산해 제시하는 건 옳은 접근입니다. 그런데 예산을 시급 하한으로 나눈 107시간에 맞춰 범위를 줄인 뒤, 같은 범위를 예산과 무관하게 다시 재니 137시간이었습니다. 28% 차이가 어디서 왔는지의 기록입니다.
서브에이전트 모델 티어링: 위임까지 최상위 모델일 필요는 없습니다
메인 에이전트를 가장 비싼 모델로 켜둔 어느 날, 로그 몇 줄 요약하는 서브에이전트까지 같은 모델을 상속하고 있다는 걸 뒤늦게 알아차렸습니다. 무지성 상속도 다운그레이드도 답이 아니었습니다. 작업마다 최저 충분한 모델 티어를 고르는 판정 기준을 정리했습니다.