개념
같은 "완료"라는 단어, 세 사람이 다른 뜻으로 쓴다
개발자 "완료했습니다" = 코드를 짰고 내 PC에서 돈다
QA "완료했습니다" = 테스트했고 결함이 없다
PO "완료했습니다" = 사용자가 쓸 수 있는 상태다이 세 정의가 문서화되지 않으면, 스프린트 리뷰에서 충돌이 일어나는 대신 스프린트 리뷰가 끝난 뒤 운영에서 충돌이 일어난다 . 완료의 정의(Definition of Done, DoD)는 이 세 문장을 하나로 합치는 작업이다.
스크럼 가이드에서 DoD의 정확한 위치
2020년판 스크럼 가이드는 DoD를 증분(Increment)에 붙은 확약(commitment) 으로 정의한다. 세 개의 산출물에 각각 확약이 하나씩 붙는 구조다.
| 산출물 | 확약 | 답하는 질문 |
|---|---|---|
| 제품 백로그 | 제품 목표(Product Goal) | 이 제품은 어디로 가는가 |
| 스프린트 백로그 | 스프린트 목표(Sprint Goal) | 이번 스프린트는 무엇을 이루는가 |
| 증분(Increment) | 완료의 정의(DoD) | 무엇을 "만들어졌다"고 부를 것인가 |
여기서 두 가지가 따라 나온다.
- DoD는 증분 전체에 적용된다. 스토리 하나가 아니라 이번 스프린트에서 나온 결과물 전체가 이 기준을 만족해야 한다.
- DoD를 만족하지 못한 작업은 증분에 포함되지 않는다. "80% 완료" 같은 것은 없다. 스크럼 가이드는 이 경우 그 작업이 다음 스프린트 백로그로 돌아간다고 본다.
조직 차원의 DoD가 이미 있으면 팀은 그것을 최소선으로 삼아 더 엄격하게만 만들 수 있다. 완화할 수는 없다.
AC · DoD · 릴리스 기준 — 세 층을 구분한다
모듈 2(레슨 4)에서 인수 기준(AC)과 DoD가 다르다는 것을 이미 봤다. 여기서는 한 층을 더 붙여 세 층으로 본다.
| 층 | 범위 | 누가 쓰는가 | 바뀌는 빈도 | 예 |
|---|---|---|---|---|
| 인수 기준(AC) | 스토리 하나 | PO + 팀 (스토리마다 새로) | 스토리마다 | 5만 원 미만 주문은 배송비 3,000원이 붙는다 |
| 완료의 정의(DoD) | 모든 스토리에 공통 | 팀 전체 (합의) | 분기~반기 | 코드 리뷰 승인, 단위 테스트 통과, 스테이징 배포, 회귀 스위트 그린 |
| 릴리스 기준 | 릴리스 단위 | 팀 + 이해관계자 | 릴리스마다 | 미해결 Critical 0건, 성능 p95 800ms 이하, 롤백 절차 검증 완료 |
핵심 구분 — AC는 "무엇을 만들었는가", DoD는 "어떻게 만들었는가", 릴리스 기준은 "내보내도 되는가"에 답한다. DoD에 "배송비 규칙이 맞다"를 넣으면 안 되고(그건 AC), AC에 "코드 리뷰를 받았다"를 넣으면 안 된다(그건 DoD).
릴리스 기준은 모듈 4(레슨 5)의 Go/No-Go 판정에서 다룬다. 스프린트마다 릴리스하는 팀에서는 DoD와 릴리스 기준이 합쳐지기도 하지만, 합칠 때도 두 층이 있었다는 것은 기억해 둬야 한다 — 합쳐 두면 "이번 릴리스만 예외" 협상이 DoD 전체를 무너뜨린다.
검증 가능한 DoD 문장 쓰기
DoD 항목의 유일한 품질 기준은 두 사람이 따로 판정해도 같은 답이 나오는가 다.
| 나쁜 문장 | 왜 나쁜가 | 고친 문장 |
|---|---|---|
| 코드 품질이 좋다 | 판정 불가 | 정적 분석에서 Blocker·Critical 0건 |
| 충분히 테스트했다 | 판정 불가 | AC의 모든 항목에 대응하는 테스트가 실행되고 통과했다 |
| 문서를 갱신했다 | 범위 불명 | 변경된 API가 있으면 API 문서와 변경 이력이 갱신됐다 |
| 성능에 문제가 없다 | 기준 없음 | 해당 화면의 기존 응답 시간 대비 20% 이상 저하가 없다 |
| 리뷰를 받았다 | 누가·무엇을 | 작성자 외 1인 이상이 PR을 승인했다 |
DoD 초안 — 여기서 빼면서 시작한다
처음부터 완벽한 DoD를 쓰려 하면 합의가 안 된다. 넉넉한 초안을 놓고 "지금 못 지키는 것"을 덜어내는 방식 이 빠르다. 덜어낸 항목은 버리지 않고 "언젠가 넣을 목록"으로 남긴다.
[코드]
- 작성자 외 1인 이상 PR 승인
- 정적 분석 Blocker/Critical 0건
- 새 로직에 단위 테스트가 있고 전체 단위 테스트가 통과한다
[테스트]
- AC의 모든 항목에 대응하는 테스트가 실행·통과했다
- 회귀 자동화 스위트가 그린이다
- 실패한 자동화 케이스가 있으면 원인이 분류됐다(제품 결함 / 케이스 결함 / 환경)
- 탐색 차터 1건 이상 수행, 세션 노트 남김
[통합·배포]
- 스테이징에 배포되어 실제로 동작하는 것을 팀원 1인 이상이 확인했다
- 기능 플래그가 있으면 끈 상태와 켠 상태 모두 확인했다
- 롤백 방법이 PR 또는 티켓에 적혀 있다
[문서·데이터]
- API가 바뀌었으면 문서와 변경 이력이 갱신됐다
- DB 마이그레이션이 있으면 롤백 스크립트가 함께 있다
- 운영 지표·로그에서 이 기능을 확인할 방법이 있다
[예외]
- 위 항목 중 지키지 못한 것이 있으면 티켓으로 등록되고 PO가 인지했다마지막 [예외] 블록이 실제로 가장 중요하다. 예외 경로가 없는 DoD는 압박이 오면 그냥 무시되고, 한 번 무시된 DoD는 다시 서지 않는다. 예외를 금지하는 대신 예외를 기록하게 만든다.
스토리별 추가 조건 — DoD를 부풀리지 않는 법
"개인정보를 다루는 스토리는 보안 리뷰가 필요하다"를 DoD에 넣으면, 개인정보와 무관한 스토리 95%가 불필요한 체크를 달고 다닌다. 이럴 때는 DoD 대신 조건부 체크리스트 를 쓴다.
DoD (모든 스토리 공통) ← 짧게 유지
+ 조건부 항목
개인정보 필드를 추가/변경했다면 → 보안 리뷰
결제 흐름을 건드렸다면 → 결제 회귀 스위트 전체 실행
외부 연동을 추가했다면 → 장애 시 폴백 동작 확인
DB 스키마를 바꿨다면 → 데이터 마이그레이션 리허설조건부 항목은 스토리 템플릿의 체크박스로 넣어 두면 리파인먼트에서 자동으로 걸린다. DoD는 짧을수록 지켜진다.
DoD를 진화시키는 회고 질문
DoD는 한 번 만들고 두는 문서가 아니다. 회고에서 두 가지 질문으로 갱신한다.
- "지난 스프린트에 운영으로 나간 결함 중, DoD에 무엇이 있었다면 막혔을까?" → 항목 추가 후보
- "DoD 항목 중 최근 3스프린트 동안 한 번도 문제를 잡지 못한 항목은?" → 항목 삭제 후보
두 번째 질문을 안 하면 DoD가 계속 길어지기만 하고, 결국 형식적으로 체크만 하게 된다. 추가만 있고 삭제가 없는 체크리스트는 죽은 체크리스트다.
DoD와 미완료 스토리 — 스프린트 경계에서의 처리
DoD를 만족하지 못한 스토리는 스프린트 리뷰에서 "완료"로 시연하지 않는다. 처리 규칙을 미리 정해 둔다.
| 상황 | 처리 |
|---|---|
| 기능은 되고 DoD 일부 미충족 | 완료 아님. 남은 항목을 다음 스프린트 최우선으로 |
| 포인트를 쪼개서 일부만 완료 | 스토리 자체를 쪼갠다. 부분 점수는 없다 |
| DoD 항목 자체가 현재 불가능(도구 장애 등) | 예외 등록 + 해제 조건과 담당자 명시 |
| 릴리스 압박으로 DoD를 건너뛰자는 요청 | PO가 기술 부채 티켓을 수용하는 조건으로만. 결정과 근거를 기록 |
마지막 행이 실전에서 가장 자주 일어난다. 이때 QA의 역할은 막는 것이 아니라 선택지와 대가를 명확히 만들고 결정을 기록하는 것 이다(모듈 43 레슨 7의 한 장짜리 상태 보고와 같은 논리다).
실무에서 왜 필요한가
DoD가 없는 팀에서는 품질 기준이 QA 개인의 권위 에 실린다. "이건 나가면 안 됩니다"라고 QA가 말할 때 그 근거가 문서가 아니라 경험이면, 그 말은 개인 의견으로 들리고 일정 압박 앞에서 무너진다. DoD는 그 말을 "팀이 합의한 기준의 3번 항목을 아직 못 지켰습니다"로 바꾼다. 같은 내용이지만 협상 구조가 완전히 다르다.
또 DoD는 신규 입사자의 온보딩 문서 로 가장 효율이 높다. "우리 팀은 이렇게 일합니다"를 열 페이지 문서로 쓰는 대신, DoD 한 장을 보여 주면 절반은 전달된다. 남은 절반은 첫 스토리를 함께 끝내면서 채워진다.