소프트웨어 공학 100 주제 시리즈의 70번째 글이다. (카테고리: 프로세스와 방법론)

한 줄 요약

DORA 지표는 “얼마나 빨리” 와 “얼마나 덜 깨지게” 를 한 쌍으로 재는 다섯 개의 숫자다. 지표 이름보다 중요한 것은 정의를 팀이 합의하는 일(무엇이 배포이고, 무엇이 실패인가)과, 그 숫자를 목표가 아니라 개선할 곳을 찾는 질문으로 쓰는 일이다.

왜 필요한가

다섯 지표의 이름과 뜻은 CI/CD 글에서 정리했다. 이 글은 그 다음 문제를 다룬다. 실제로 재려고 하면 바로 질문이 쏟아진다.

  • 스테이징 배포도 배포인가? 피처 플래그를 켜는 것은?
  • 리드 타임은 첫 커밋부터인가, PR 머지부터인가?
  • 배포 후 사흘 뒤 발견된 버그는 “변경 실패” 인가?
  • 열 개 팀의 숫자를 한 대시보드에 놓고 순위를 매겨도 되는가?

이 질문에 답하지 않고 대시보드부터 만들면, 숫자는 매주 나오지만 아무도 믿지 않거나, 더 나쁘게는 모두가 숫자를 맞추려고 행동을 바꾼다.

핵심 개념

지표는 진화해 왔다

DORA 의 Nathen Harvey 가 쓴 A history of DORA’s software delivery metrics(2026)가 변천을 정리한다.

시기 변화
2014 첫 연구가 “IT 성과” 를 정의하려고 배포 빈도, 변경 리드 타임, 평균 복구 시간(MTTR), 변경 실패율 네 변수로 출발. 그해 통계 분석에서는 변경 실패율이 다른 변수와 하나의 잠재 구성 개념으로 묶이지 않아, 2014년 정의는 나머지 세 지표에 의존
2015 처리량(배포 빈도, 리드 타임)과 안정성(MTTR, 변경 실패율)의 이원 구조로 정착. 고성과 팀이 둘 다 잘한다는 결과로 “속도는 안정성을 희생한다” 는 통념을 반박
2018 운영 건강도로 “가용성” 추가, 용어를 “소프트웨어 전달 및 운영(SDO) 성과” 로 변경
2021 “가용성” 을 지연·성능·확장성까지 포괄하는 “신뢰성” 으로 확장
2023 MTTR 을 실패한 배포 복구 시간으로 재정의. 소프트웨어 변경이 일으킨 장애와 외부 요인(데이터센터 장애 등)을 구분하기 위해
2024 다섯 번째 지표 배포 재작업률 도입. 처리량과 불안정성 두 묶음으로 재편

같은 글은 2021년 보고서가 신뢰성을 “다섯 번째 지표” 라고 부른 것이 부정확했다고 바로잡는다. 신뢰성은 전달 성과보다 운영 성과의 척도라는 것이다. 오래된 자료에서 “다섯 번째 지표 = 신뢰성” 을 보면 이 맥락을 기억해야 한다.

현재의 다섯 지표

DORA 지표 가이드의 정의다.

묶음 지표 정의
처리량 변경 리드 타임 변경이 버전 관리에 커밋된 때부터 운영에 배포될 때까지 걸리는 시간
처리량 배포 빈도 일정 기간의 배포 횟수, 또는 배포 사이의 시간
처리량 실패한 배포 복구 시간 즉각 조치가 필요한 실패 배포에서 복구하는 데 걸리는 시간
불안정성 변경 실패율 배포 직후 즉각 조치가 필요했던 배포의 비율
불안정성 배포 재작업률 운영 사고의 결과로 생긴, 계획에 없던 배포의 비율

복구 시간이 “안정성” 이 아니라 “처리량” 쪽에 있다는 점에 주목한다. 고치는 변경을 얼마나 빨리 내보낼 수 있는가도 흐름의 능력이기 때문이다.

왜 쌍으로 재는가

가이드는 DORA 연구가 “속도와 안정성이 트레이드오프가 아님” 을 거듭 보여 줬고, 대부분의 팀에서 지표들이 상관관계를 보이며, 상위 성과 팀은 다섯 지표 모두에서 잘하고 하위 팀은 모두에서 못한다고 쓴다. 한쪽만 재면 이런 일이 생긴다.

 배포 빈도만 목표  ─▶ 쪼개기·빈 배포로 숫자 상승, 실패율도 상승 (보이지 않음)
 실패율만 목표    ─▶ 배포를 미루고 묶음 ─▶ 큰 배치 ─▶ 실패 시 피해·복구 시간 증가
 쌍으로 측정      ─▶ 한쪽을 희생한 개선이 바로 드러남

측정 정의를 먼저 합의한다

DORA 정의는 개념 수준이다. 팀이 운영적 정의를 정해야 한다.

질문 권장 기준 이유
무엇이 “배포” 인가 사용자 트래픽을 받는 운영 환경에 새 버전이 반영된 것 스테이징 포함 시 빈도가 부풀려짐
리드 타임 시작점 해당 배포에 포함된 커밋의 시각 (가이드 정의) PR 머지 기준은 리뷰 대기를 숨김
리드 타임 대표값 중앙값과 상위 백분위 평균은 오래 묵은 커밋 하나에 휘둘림
무엇이 “실패” 인가 배포 직후 롤백·핫픽스·패치 등 즉각 조치가 필요했던 것 며칠 뒤 발견된 결함까지 넣으면 다른 지표가 됨
복구 완료 시점 서비스가 정상으로 돌아온 때(롤백 완료 포함) 근본 수정 배포까지 기다리면 의미가 바뀜
재작업 배포 판별 사고 티켓에 연결된 계획 외 배포 수동 라벨보다 연결 규칙이 일관적
측정 단위 애플리케이션·서비스 단위 가이드도 애플리케이션 수준 적용을 권함

예제

배포 기록에서 다섯 지표를 계산한다. 데이터는 예시다.

from datetime import datetime as dt
from statistics import median

# commit: 배포에 포함된 가장 오래된 커밋 시각
# failed: 배포 직후 즉각 조치가 필요했나 / unplanned: 사고 대응용 계획 외 배포인가
deploys = [
    dict(at="2026-09-01 10:00", commit="2026-08-29 15:00", failed=False, unplanned=False),
    dict(at="2026-09-02 16:00", commit="2026-09-01 11:00", failed=True,
         recovered="2026-09-02 17:10", unplanned=False),
    dict(at="2026-09-02 17:05", commit="2026-09-02 16:40", failed=False, unplanned=True),
    dict(at="2026-09-04 11:00", commit="2026-09-02 18:00", failed=False, unplanned=False),
    dict(at="2026-09-08 14:00", commit="2026-09-04 09:00", failed=False, unplanned=False),
    dict(at="2026-09-09 10:30", commit="2026-09-08 17:00", failed=True,
         recovered="2026-09-09 13:30", unplanned=False),
    dict(at="2026-09-09 13:20", commit="2026-09-09 12:50", failed=False, unplanned=True),
    dict(at="2026-09-11 15:00", commit="2026-09-10 10:00", failed=False, unplanned=False),
]
p = lambda s: dt.strptime(s, "%Y-%m-%d %H:%M")
hours = lambda a, b: (p(b) - p(a)).total_seconds() / 3600

days = (p(deploys[-1]["at"]) - p(deploys[0]["at"])).days + 1
lead = [hours(d["commit"], d["at"]) for d in deploys]
fails = [d for d in deploys if d["failed"]]
recov = [hours(d["at"], d["recovered"]) for d in fails]

print(f"배포 빈도            : {len(deploys)}회 / {days}일")
print(f"변경 리드 타임 중앙값  : {median(lead):.1f}시간")
print(f"실패 배포 복구 시간 중앙값: {median(recov):.1f}시간")
print(f"변경 실패율          : {len(fails)}/{len(deploys)} = {len(fails)/len(deploys):.0%}")
rw = sum(d["unplanned"] for d in deploys)
print(f"배포 재작업률         : {rw}/{len(deploys)} = {rw/len(deploys):.0%}")

실행 결과:

배포 빈도            : 8회 / 11일
변경 리드 타임 중앙값  : 29.0시간
실패 배포 복구 시간 중앙값: 2.1시간
변경 실패율          : 2/8 = 25%
배포 재작업률         : 2/8 = 25%

읽는 법:

  • 실패 두 건이 각각 재작업 배포(핫픽스)를 낳았다. 변경 실패율과 재작업률이 같은 것은 우연이 아니다. DORA 가 재작업률을 도입한 이유가, 변경 실패율이 팀이 해야 하는 재작업 양의 대리 지표로 작동한다는 관찰이었다.
  • 리드 타임 중앙값 29시간 중 대부분은 커밋 뒤 배포를 기다린 시간일 가능성이 크다. 다음 질문은 “어디서 기다렸나” 다. 가치 흐름 지도(SE100 #065)로 넘어간다.
  • 표본 8건은 너무 작다. 한 달 이상 모아 추세를 본다.

수집 파이프라인

# 이벤트 소스와 지표의 연결 (개념)
sources:
  vcs:        [commit_sha, committed_at]
  cd:         [deploy_id, service, env, deployed_at, commit_shas]
  incident:   [incident_id, caused_by_deploy_id, resolved_at]
derive:
  change_lead_time:        deployed_at - min(committed_at of commit_shas)
  deployment_frequency:    count(deploy where env == prod) per week
  change_fail_rate:        deploys with linked incident / prod deploys
  failed_deploy_recovery:  incident.resolved_at - deploy.deployed_at
  deployment_rework_rate:  prod deploys created to resolve an incident / prod deploys

Google 이 공개했던 참조 구현 Four Keys는 현재 보관(archived) 상태다. 구조는 참고하되 그대로 운영할 도구로 보지 않는 편이 좋다. 데이터가 없다면 DORA 의 Quick Check 설문으로 대략의 위치부터 볼 수 있다.

흔한 오해와 함정

DORA 지표 가이드가 직접 꼽는 함정이 대부분을 덮는다.

  • 지표를 목표로 삼는다. 가이드는 지표를 목표로 설정하면 팀이 지표를 조작할 가능성이 커진다고 경고한다(굿하트의 법칙).
  • 팀끼리 비교한다. 애플리케이션마다 맥락이 다르므로 팀·조직을 섞어 비교하는 것은 문제가 된다. 목표는 다른 팀과의 경쟁이 아니라 자기 팀의 시간에 따른 개선이다.
  • 소유가 갈라진다. 개발은 처리량, 운영은 안정성만 책임지면 쌍으로 재는 의미가 사라진다. 가이드는 지표를 전달에 관여하는 모든 팀이 공유하라고 한다.
  • 측정에 매달려 개선을 못 한다. 여러 시스템을 완벽하게 통합하는 데 몇 달을 쓰기보다, 거친 측정으로 시작해 개선에 집중하라고 권한다.
  • DORA = 개발자 생산성. 다섯 지표는 소프트웨어 전달 성과다. 개인 생산성이나 개발 경험은 재지 않는다. 더 넓은 측정 틀은 SE100 #095(SPACE)에서, 사용자 관점의 신뢰성 목표는 SE100 #084(SLO)에서 다룬다.
  • AI 도입 효과를 지표 하나로 판단한다. DORA 의 2025 보고서(State of AI-assisted Software Development)는 AI 의 주된 역할을 “조직의 기존 강점과 약점을 확대하는 증폭기” 로 본다. 처리량만 오르고 불안정성이 같이 오르면 증폭된 것은 약점이다.

확인 문제

  1. 2023년에 MTTR 이 “실패한 배포 복구 시간” 으로 바뀐 이유는?
  2. 현재 다섯 지표의 두 묶음과 각 묶음의 지표를 쓰라.
  3. 리드 타임 시작점을 “PR 머지 시각” 으로 잡으면 무엇이 가려지는가?
  4. 배포 빈도만 목표로 삼았을 때 생길 수 있는 왜곡 두 가지를 쓰라.
  5. 2021년 보고서가 신뢰성을 “다섯 번째 지표” 라고 부른 것이 부정확했다고 DORA 가 정정한 이유는?

풀이

  1. 이전 정의는 소프트웨어 변경이 일으킨 장애와 데이터센터 장애 같은 외부 요인을 구분하지 않았다. 변경으로 인한 손상에서의 복구에 초점을 맞춰 다른 전달 지표와 일관되게 했다.
  2. 처리량: 변경 리드 타임, 배포 빈도, 실패한 배포 복구 시간. 불안정성: 변경 실패율, 배포 재작업률.
  3. 커밋 뒤 리뷰를 기다리고 수정하는 시간. 흔히 리드 타임의 큰 부분인 리뷰 대기가 지표에서 사라진다.
  4. 의미 없는 작은 배포·빈 배포로 숫자를 부풀리는 것, 그리고 검증을 줄여 빈도를 올리면서 실패율·재작업률이 함께 나빠지는 것.
  5. 신뢰성은 소프트웨어 전달 성과라기보다 운영 성과의 척도이기 때문이다.

더 읽을거리 (References)