개념
먼저 결론부터
이 레슨의 결론은 한 문장이다. "이거 바뀌었는데 뭘 다시 테스트해야 하죠?"에 기억이 아니라 조회로 답할 수 있어야 한다.
요구사항이 바뀌는 것 자체는 실패가 아니다. 시장 상황이 바뀌고, 사용자 피드백이 들어오고, 처음엔 몰랐던 제약이 나중에 발견된다. 개발이 끝날 때까지 한 글자도 안 바뀌는 요구사항은 현실에 거의 없다. 문제는 변경 자체가 아니라, 변경이 어디까지 영향을 주는지 아무도 모르는 상태다.
그 "모르는 상태"를 없애는 장치가 추적성이다. 그리고 이건 거창한 도구 이야기가 아니라, 스프레드시트 한 장에서 시작할 수 있는 아주 실무적인 습관이다.
추적성이란
추적성(Traceability) 은 요구사항 하나가 어떤 설계, 어떤 코드, 어떤 테스트 케이스와 연결되어 있는지 계속 알 수 있는 상태를 말한다. 이 연결이 있으면, 요구사항이 바뀌었을 때 "이 변경 때문에 무엇을 다시 봐야 하는가"를 추측이 아니라 조회로 알 수 있다.
비유하자면 전기 배선도다. 두꺼비집에서 차단기 하나를 내렸을 때 어느 방의 불이 꺼지는지, 배선도가 있으면 즉시 안다. 없으면 하나씩 내려보면서 확인해야 하고, 하필 확인 안 한 방에 서버가 꽂혀 있었다는 걸 나중에 알게 된다. 요구사항 변경이 정확히 이 모양이다.
가장 단순한 형태 — 추적성 매트릭스
가장 단순한 형태는 추적성 매트릭스다. 요구사항 ID와 테스트 케이스 ID를 표로 연결해둔다.
| 요구사항 ID | 요구사항 요약 | 관련 테스트 케이스 |
|---|---|---|
| REQ-101 | 무료배송 기준 3만원 | TC-201, TC-202, TC-203 |
| REQ-102 | 쿠폰 중복 적용 불가 | TC-210, TC-211 |
| REQ-103 | 재고 0개면 주문 불가 | TC-220 |
이제 REQ-101이 3만원에서 5만원으로 바뀐다면, 이 표를 조회해서 TC-201, TC-202, TC-203을 다시 확인해야 한다는 걸 즉시 알 수 있다. 표가 없다면 "어떤 테스트가 이거랑 관련 있었더라?"를 기억에 의존해서 떠올려야 하고, 빠뜨릴 위험이 크다.
이건 모듈 1 레슨 4에서 배운 회귀 테스트 범위를 정하는 문제와 정확히 같은 문제다. 두 도구는 같은 질문에 서로 다른 방향에서 답한다.
| 영향 분석(모듈 1 레슨 4) | 추적성 매트릭스(이 레슨) | |
|---|---|---|
| 출발점 | 코드 변경(PR diff) | 요구사항 변경(기획서 수정) |
| 방법 | 바뀐 함수를 누가 부르는지 검색 | 요구사항 ID로 표를 조회 |
| 알아낼 수 있는 시점 | 개발이 끝난 뒤 | 기획 단계, 개발 시작 전 |
| 강점 | 실제 코드 의존성을 본다 | 구현 전에 미리 견적을 낼 수 있다 |
| 약점 | 문서에만 있고 코드에 없는 요구사항은 못 본다 | 표가 낡으면 그대로 틀린다 |
표의 PR diff 는 "이번에 바뀐 줄만 추려 보여 주는 화면" 이다. 고친 사람이 올린 변경 묶음에서 어디가 어떻게 달라졌는지 바로 볼 수 있다.
둘 중 하나만 쓰는 게 아니라 겹쳐 쓴다. 추적성 매트릭스로 후보를 뽑고, 영향 분석으로 코드 레벨에서 검증한다. 매트릭스가 놓친 걸 코드 검색이 잡고, 코드에 아직 반영되지 않은 변경을 매트릭스가 잡는다.
추적성이 없을 때와 있을 때
같은 상황을 두 팀이 어떻게 다르게 처리하는지 나란히 보자. 상황은 "무료배송 기준을 3만원에서 5만원으로 올린다"는 기획 변경이다.
| 추적성이 없는 팀 | 추적성이 있는 팀 | |
|---|---|---|
| 변경 통보 방식 | "무료배송 기준 바뀌었어요, 관련된 거 봐주세요" | "REQ-101이 변경됩니다" |
| 범위 파악 | 회의에서 각자 기억나는 걸 말한다 | 표를 조회한다(3분) |
| 견적 | "글쎄요, 해봐야 알 것 같은데요" | "테스트 3건 + 연관 2건, 반나절입니다" |
| 놓치는 것 | 오래된 기능, 다른 팀이 만든 화면 | 표에 없는 것(그래서 표를 보강한다) |
| 사고 나면 | "누가 그걸 알았겠어요" | "표에 이 연결이 빠져 있었다" — 고칠 대상이 명확 |
마지막 행이 핵심이다. 추적성의 진짜 가치는 틀렸을 때 어디를 고쳐야 하는지가 드러난다는 데 있다. 기억에 의존하면 사고는 "운이 나빴다"로 끝나지만, 기록에 의존하면 사고는 "기록의 어느 칸이 비어 있었다"로 끝난다. 후자만 다음번에 개선된다.
사례 연구 — 3만원이 5만원으로 바뀐 날
앞의 조각들을 하나의 흐름으로 이어보자. 추적성이 없는 팀에서 실제로 흔한 순서다.
월요일 — 변경 결정. 물류비 인상으로 무료배송 기준을 3만원에서 5만원으로 올리기로 한다. 기획자가 기획서의 숫자 하나를 고치고 슬랙에 공지한다. "무료배송 기준 5만원으로 변경됐습니다. 관련된 부분 확인 부탁드려요."
월요일 — 개발과 테스트. 개발자가 상수 하나를 30000에서 50000으로 바꾼다.
QA는 장바구니에서 49,000원과 50,000원을 넣어보고 배송비가 정상적으로 나오는 걸
확인한다. 30분 만에 끝난다. 여기까지는 아무 문제가 없어 보인다.
수요일 — 첫 신호. CS에 "무료배송 쿠폰을 썼는데 배송비가 붙는다"는 문의가 들어온다. 담당자는 쿠폰 시스템 문제로 보고 쿠폰팀에 넘긴다.
목요일 — 두 번째 신호. 마케팅팀이 "이번 주 무료배송 기획전 전환율이 반토막 났다"고 알린다. 기획전 랜딩 페이지에는 여전히 "3만원 이상 무료배송"이 적혀 있었다.
금요일 — 원인 확정. 실제로 "무료배송 3만원"에 의존하던 지점은 장바구니 하나가 아니었다.
| 지점 | 무슨 일이 있었나 | 왜 놓쳤나 |
|---|---|---|
| 장바구니 배송비 계산 | 정상 반영 | 유일하게 확인한 곳 |
| 무료배송 쿠폰 발급 조건 | 여전히 3만원 기준으로 발급 | 쿠폰은 다른 팀 담당 |
| 상품 상세 페이지 안내 문구 | "3만원 이상 무료배송" 그대로 | 문구는 하드코딩 |
| 기획전 랜딩 페이지 | 3만원으로 홍보 중 | 마케팅이 변경을 몰랐음 |
| 주문서 배송비 재계산 | 장바구니와 값이 달라짐 | 캐시된 값 사용 |
| 정산 리포트의 배송비 부담액 | 예상치와 어긋남 | 아무도 연결을 생각 못 함 |
총 비용. 30분짜리 변경이 나흘에 걸쳐 여섯 군데에서 터졌다. 잘못 발급된 쿠폰을 회수하고, 홍보 문구를 정정하고, 기획전 이탈 고객에게 안내하고, 정산을 다시 맞췄다. 원인 파악에만 사흘이 걸렸는데, 사흘 대부분은 "이게 그 변경 때문인지" 아무도 연결 짓지 못해서 흘러간 시간이다.
회고에서 나온 사실. 사고 후 팀이 확인해보니, 무료배송 기준을 검증하는 테스트 케이스는 실제로 11건이 존재했다. 장바구니 3건, 쿠폰 4건, 문구 2건, 주문서 2건. 없어서 못 돌린 게 아니라 있는데 못 찾아서 안 돌린 것이다. 이 사고의 정확한 원인은 "테스트가 부족했다"가 아니라 "요구사항 ID와 테스트 케이스의 연결이 어디에도 기록되어 있지 않았다"다.
처방. 팀이 실제로 한 조치는 세 가지다.
- 기획서의 각 요구사항 문장에 ID를 붙였다(REQ-101 형식).
- 기존 테스트 케이스에 어떤 REQ를 검증하는지 열을 하나 추가했다. 전부 한 번에 하지 않고, 최근 6개월 내 변경이 있었던 영역부터 채웠다.
- 기획 변경 공지 템플릿에 "변경되는 요구사항 ID" 칸을 넣었다. 이제 공지가 "무료배송 바뀌었어요"가 아니라 "REQ-101 변경"으로 온다.
세 번째가 의외로 효과가 컸다. 기획자가 ID를 적으려면 자기가 무엇을 바꾸는지 정확히 지목해야 하기 때문이다. "이것저것 좀 바꿨어요"가 불가능해진다.
양방향으로 본다
추적성은 화살표가 한 방향만 있는 게 아니다. 두 방향은 완전히 다른 질문에 답한다.
- 정방향 추적(요구사항 → 테스트): "이 요구사항, 테스트로 커버되고 있나?"를 확인한다. 연결된 테스트가 하나도 없는 요구사항이 있다면 그건 테스트 공백이다. 릴리즈 전에 이 표를 위에서 아래로 훑어 빈칸을 찾는 것만으로도 "아무도 확인하지 않은 기능"을 잡아낼 수 있다.
- 역방향 추적(테스트 → 요구사항): "이 테스트 케이스, 지금도 유효한 요구사항과 연결되어 있나?"를 확인한다. 연결이 끊긴 테스트 케이스는 이미 없어진 요구사항을 검증하고 있을 수 있다. 이걸 고아 테스트 케이스라고 부른다.
| 정방향 추적 | 역방향 추적 | |
|---|---|---|
| 질문 | 이 요구사항은 검증되는가 | 이 테스트는 무엇을 대표하는가 |
| 찾아내는 것 | 커버 안 된 요구사항(공백) | 고아 테스트 케이스(잉여) |
| 언제 하나 | 릴리즈 전, 변경 직후 | 분기 1회 정도의 정리 시점 |
| 안 하면 | 아무도 안 본 기능이 나간다 | 스위트가 부풀고 신뢰가 떨어진다 |
정방향은 대부분의 팀이 어느 정도 한다. 역방향은 거의 안 한다. 그런데 실무에서 조용히 더 위험한 쪽은 역방향이다.
고아 테스트 케이스가 위험한 진짜 이유
고아 테스트 케이스의 문제를 "쓸데없는 걸 돌리느라 시간을 낭비한다"로만 이해하면 절반만 본 것이다. 시간 낭비는 눈에 보이는 비용이고, 진짜 위험은 보이지 않는 쪽에 있다.
잘못된 확신을 만든다. 회귀 스위트 420건이 전부 초록불이면 팀은 안심한다. 그런데 그중 80건이 이미 사라졌거나 완전히 바뀐 요구사항을 검증하고 있다면, 그 80건의 초록불은 아무 정보도 담고 있지 않다. "테스트가 다 통과했으니 안전하다"고 믿지만, 그 통과가 대표하는 요구사항이 없다. 이건 모듈 1 레슨 5에서 다룬 살충제 패러독스가 요구사항 쪽에서 나타나는 모습이다. 스위트는 그대로인데 제품이 움직였다.
구체적인 모습은 이렇다.
| 고아가 되는 경위 | 남은 테스트가 하는 일 | 왜 위험한가 |
|---|---|---|
| 기능이 통째로 제거됨 | 사라진 화면을 열려다 실패 → "환경 문제"로 처리 | 실패에 무뎌진다 |
| 정책 숫자가 바뀜(3만원→5만원) | 옛 기준으로 통과하도록 기대값이 고정됨 | 틀린 값을 정답이라고 검증한다 |
| A/B 테스트 후 한쪽 폐기 | 폐기된 갈래를 계속 검증 | 실행 시간만 늘어난다 |
| 다른 기능으로 대체됨 | 옛 경로를 검증, 새 경로는 아무도 안 봄 | 공백과 잉여가 동시에 생긴다 |
두 번째 행이 가장 고약하다. 기대값이 옛 기준으로 남아 있으면 그 테스트는 실패하지 않는다. 오히려 개발자가 정책을 올바르게 고쳤을 때 테스트가 빨간불이 되고, 팀은 "테스트가 깨졌으니 코드를 되돌리자"는 잘못된 결론에 도달할 수 있다. 테스트가 품질을 지키는 게 아니라 낡은 정책을 지키는 파수꾼이 되어버리는 것이다.
네 번째 행도 짚어둘 만하다. 고아 테스트가 있다는 건 그 자리에 새 요구사항이 들어왔다는 뜻인 경우가 많다. 그래서 역방향 추적으로 고아를 찾는 작업은 삭제 작업이 아니라 공백 탐지 작업이다. "이 테스트는 왜 아직 여기 있지?"라는 질문은 거의 항상 "그럼 지금 그 자리는 누가 보고 있지?"로 이어진다.
추적성을 4단계로 늘리면
지금까지는 요구사항과 테스트, 두 칸만 연결했다. 실무에서는 중간 단계를 더 넣기도 한다.
요구사항 → 설계 → 코드 → 테스트
REQ-101 DES-12 PR #482 TC-201, TC-202, TC-203
| 연결 | 무엇을 답해주나 |
|---|---|
| 요구사항 → 설계 | 이 요구사항은 어떤 구조로 구현하기로 했나 |
| 설계 → 코드 | 그 설계가 실제로 어느 파일·어느 PR에 반영됐나 |
| 코드 → 테스트 | 그 코드는 어떤 테스트로 검증됐나 |
4단계까지 이어져 있으면 질문의 폭이 넓어진다. "REQ-101이 바뀐다"에서 시작해 어떤 PR을 다시 봐야 하는지까지 한 번에 나온다. 반대로 "이 PR이 왜 필요했지?"를 거슬러 올라가 요구사항을 찾는 것도 된다. 인수인계나 장애 회고에서 이 역방향 조회가 특히 값지다.
다만 처음부터 4단계를 목표로 삼지는 말자. 유지 비용이 단계 수에 비례해서 늘고, 설계 문서가 없는 팀도 많다. 대부분의 팀에서는 요구사항↔테스트 2단계로 충분하고, 여기에 실용적으로 하나만 더 얹는다면 보통 코드다. 방법도 무겁지 않다.
- 커밋 메시지나 PR 제목에 요구사항 ID를 적는다 —
[REQ-101] 무료배송 기준 상수화 - 이슈 트래커의 티켓 제목이나 라벨에 ID를 붙인다
- 테스트 케이스 이름 앞에 ID를 붙인다 —
TC-201 [REQ-101] 49,900원 배송비 부과
이것만 해도 저장소에서 REQ-101을 검색하는 순간 관련 PR과 테스트가 한꺼번에
나온다. 도구를 사는 게 아니라 검색 가능한 단어를 심는 것이다.
규제 산업에서는 선택이 아니다
의료기기, 항공, 자동차, 금융 같은 규제 산업에서는 추적성이 좋은 습관이 아니라 법적·계약적 요건이다. 왜 감사관이 이걸 요구하는지 이유가 분명하다.
사고가 났다고 하자. 인슐린 펌프의 투여량 계산에 오류가 있어 환자가 다쳤다. 감사관이 던지는 질문은 "테스트 많이 하셨나요?"가 아니다. "투여량 상한을 규정한 그 요구사항이, 출시된 그 버전에서, 실제로 테스트됐다는 증거를 보여주세요" 다. 이때 필요한 것이 정확히 추적성이다.
| 감사관의 질문 | 추적성 없이 | 추적성 있으면 |
|---|---|---|
| 이 요구사항은 테스트됐나 | "했을 겁니다" | REQ-114 → TC-330~TC-336 |
| 언제, 누가, 어떤 버전에서 | 기억에 의존 | 실행 기록에 날짜·담당자·빌드 번호 |
| 요구사항이 바뀐 뒤 다시 테스트했나 | 확인 불가 | 변경 이력과 재실행 기록 |
| 테스트 안 된 요구사항은 없나 | 답할 수 없음 | 정방향 추적으로 빈칸이 0임을 제시 |
핵심은 "했다"와 "했음을 증명할 수 있다"가 다르다는 것이다. 규제 감사는 후자만 인정한다. 그래서 이런 산업에서는 요구사항 하나하나에 ID가 붙고, 모든 테스트가 그 ID를 참조하며, 실행 결과가 서명과 함께 보관된다. 이 원리는 모듈 8(ISO/IEC/IEEE 29119)과 부록의 의료기기 표준(IEC 62304)에서 다시 다룬다.
규제 산업이 아니어도 이 감각은 쓸모가 있다. 큰 사고가 난 뒤의 회고, 보안 심사, 대기업 납품 검수에서 똑같은 질문을 받는다. "증명할 수 있는가" 는 규제만의 언어가 아니다.
반대로, 추적성이 짐이 되는 경우
균형을 위해 반대편도 봐야 한다. 추적성은 공짜가 아니다. 만드는 비용보다 갱신하는 비용이 훨씬 크고, 이 비용이 얻는 것보다 크면 안 하는 게 맞다.
| 상황 | 왜 무거운 추적성이 손해인가 |
|---|---|
| 요구사항이 20개 미만인 초기 제품 | 전체를 머리에 담을 수 있다. 표 유지 시간이 테스트 시간을 잡아먹는다 |
| 방향이 매주 바뀌는 프로토타입 | 표가 만들어지자마자 낡는다. 낡은 표는 없는 것보다 나쁘다 |
| 팀이 2~3명이고 한 사람이 전부 봄 | 연결이 사람 머릿속에 이미 있다 |
| 곧 폐기될 임시 기능 | 유지할 기간 자체가 없다 |
특히 두 번째가 중요하다. 틀린 매트릭스는 없는 매트릭스보다 위험하다. 없으면 사람들이 조심하지만, 있으면 사람들이 믿는다. 믿었는데 틀리면 그때 놓친다.
그래서 판단 기준은 "해야 하나 말아야 하나"가 아니라 "어디까지 할 것인가" 다. 리스크 기반으로 정한다.
- 반드시 연결한다 — 돈이 오가는 흐름, 개인정보·인증, 되돌릴 수 없는 동작, 규제 대상 기능, 여러 팀이 얽힌 기능
- 연결하면 좋다 — 최근 6개월 내 변경이 잦았던 영역, 결함 이력이 밀집된 영역
- 안 해도 된다 — 내부용 화면, 사용량이 극히 적은 기능, 곧 없어질 기능
이 우선순위 감각은 모듈 4(리스크 기반 테스트)에서 정식화된다. 여기서 기억할 것은 하나다. 완벽한 매트릭스를 만들려다 아무것도 못 만드는 것이 가장 흔한 실패 모드다.
어떻게 시작하는가 — 30분 최소 버전
지금 팀에 추적성이 전혀 없다면, 이 순서로 시작하면 된다. 도구도 승인도 필요 없다.
| 단계 | 할 일 | 시간 |
|---|---|---|
| 1 | 이번 릴리즈에서 리스크 상위 5개 기능만 고른다 | 5분 |
| 2 | 각 기능의 요구사항 문장에 임시 ID를 붙인다(REQ-001~) | 10분 |
| 3 | 기존 테스트 케이스 목록에 REQ 열을 하나 추가하고, 5개 기능에 해당하는 것만 채운다 | 10분 |
| 4 | 빈칸(연결된 테스트가 없는 REQ)이 있는지 훑는다 | 5분 |
4단계에서 빈칸이 나오면 그게 첫 성과다. 표를 만든 날 바로 테스트 공백이 발견되는 경우가 생각보다 많다. 그다음부터는 규칙 하나만 지킨다 — 테스트 케이스를 새로 만들 때 REQ 열을 비워두지 않는다. 이 습관이 있으면 매트릭스는 따로 관리하지 않아도 저절로 자란다.
도구는 이 개념의 자동화일 뿐이다
큰 프로젝트에서는 테스트 관리 도구(모듈 7에서 다룰 TestRail, Zephyr 등)가 이 연결을 자동으로 관리해준다. Jira 이슈에 테스트 케이스를 링크하면 커버리지 리포트가 자동으로 나오고, 요구사항이 바뀌면 연결된 케이스에 "재검토 필요" 표시가 붙는 식이다.
하지만 도구가 해주는 일은 표를 대신 관리해주는 것이지 연결을 대신 판단해주는 것이 아니다. "이 요구사항과 이 테스트가 관련 있다"를 결정하는 건 여전히 사람이다. 도구를 먼저 배우면 칸은 채우지만 왜 채우는지 모르는 상태가 된다.
실무에서 왜 필요한가
"이거 바뀌었는데 얼마나 걸려요?"에 숫자로 답할 수 있다. 추적성이 없으면 "해봐야 알 것 같아요"밖에 못 한다. 이 대답은 일정 협상에서 아무 힘이 없다. 표가 있으면 "직접 연결된 케이스 3건, 같은 데이터를 쓰는 화면 2건까지 포함해서 반나절"이라고 말할 수 있다. 모듈 1 레슨 5에서 본 것처럼, 범위와 시간을 함께 제시해야 협상이 된다.
"관련된 거 봐주세요"라는 모호한 요청을 구체화한다. 추적성이 없는 팀에서 요구사항이 바뀌면, "이거 바뀌었으니 관련된 거 다시 테스트해주세요"라는 말만 전달되고 실제로 "관련된 것"이 무엇인지는 각자의 기억에 맡겨진다. 사람마다 기억이 다르고, 빠뜨리는 부분이 생긴다. 특히 오래전에 만들어져 잘 안 건드리는 기능일수록 "설마 이것까지 영향 있겠어"라며 누락되기 쉽다. 추적성 매트릭스는 이 판단을 기억이 아니라 기록에 맡긴다.
릴리즈 전 커버리지 공백을 보고할 수 있다. 정방향 추적으로 표를 훑으면 "이번 릴리즈 요구사항 14개 중 12개는 테스트 케이스가 연결돼 있고, 2개는 비어 있습니다"라는 문장이 나온다. 이건 감이 아니라 셀 수 있는 사실이다. 남은 리스크를 팀이 함께 지게 만드는 가장 값싼 방법이다.
인수인계와 온보딩 시간이 줄어든다. 새로 합류한 QA가 "이 기능은 어디까지 테스트되고 있나요?"라고 물었을 때, 표를 보여주면 30초에 끝난다.
사고 회고가 개인 책임 추궁에서 시스템 개선으로 바뀐다. "왜 이걸 못 잡았냐"에 "죄송합니다"로 답하면 다음에 달라지는 게 없다. "REQ-101과 쿠폰 발급 테스트 사이의 연결이 표에 없었습니다. 그 연결을 추가하고, 쿠폰팀 케이스도 같은 표에 넣겠습니다"로 답하면 고칠 대상이 명확해진다. 이 차이가 팀이 같은 사고를 두 번 겪느냐를 가른다.
감사·심사에 대응할 수 있다. 규제 산업이 아니어도 대형 고객사 납품 검수, 보안 심사, ISMS 같은 인증 과정에서 "요구사항이 검증됐다는 증거"를 요구받는다. 그때 급하게 만들면 이미 늦다.