요구사항이 바뀔 때 테스트 누락을 줄이려면, 요구사항과 테스트를 한 번 연결한 표를 만드는 데서 멈춰서는 안 된다. Requirement, Change, Implementation Artifact, Test, Defect, Baseline에 각각 식별자와 버전을 부여하고 객체 사이를 의미가 분명한 링크로 연결해야 한다.
변경 한 건이 접수되면 Change Package를 열어 연결을 양방향으로 탐색한다. 영향받을 가능성이 있는 구현·테스트·결함을 모으고 각 항목을 수정·유지·폐기·영향 없음 중 하나로 검토한다. 마지막에는 링크가 끊겼는지, 근거가 없는 객체가 생겼는지, 예전 버전을 계속 가리키는 링크가 남았는지 확인한다.
이 구조가 답하는 질문은 “무엇이 영향을 받았는가?”다. 찾아낸 테스트 후보 중 실제로 무엇을 회귀 테스트에 포함할지는 별도의 선택 문제이며 추적성이 완성됐다고 해서 소프트웨어의 출시 여부가 결정되는 것도 아니다.
NASA의 요구사항 관리 Guidance도 양방향 추적성을 전 생애주기 동안 유지하고 요구사항 변경이 생기면 테스트 계획·절차와 관련 산출물을 현재 요구사항에 맞게 갱신하도록 요구한다. 다만 이는 NASA 프로젝트를 위한 체계다. 여기서는 일반 소프트웨어 팀이 적용할 수 있는 운영 원리로 재구성한다. (NASA)
문제는 RTM이 아니라 ‘한 번 만들고 끝내는 RTM’이다
요구사항 추적성 매트릭스, 즉 RTM은 충분히 유용하다. 요구사항마다 연결된 설계·구현·테스트를 찾을 수 있고 누락된 항목도 표로 확인할 수 있다.
문제는 표를 최초 작성한 시점의 연결을 현재 연결이라고 믿을 때 생긴다.
예를 들어 REQ-AUTH-014의 비밀번호 정책이 버전 2에서 버전 3으로 바뀌었다고 하자. 테스트 TC-AUTH-007이 여전히 REQ-AUTH-014와 연결돼 있다는 이유만으로 커버리지가 유지됐다고 볼 수는 없다. 테스트가 새 길이 제한, 예외 조건, 오류 메시지를 반영했는지 확인하지 않았다면 그 링크는 존재하지만 오래된 링크다.
NASA SWE-071도 추적성 매트릭스를 시점 고정 문서로 보지 않는다. 프로젝트가 변하는 동안 계속 갱신하고 요구사항 변경 시 어떤 테스트 절차·케이스·스크립트·데이터가 영향을 받는지 찾는 도구로 사용한다. (SWEHB)
따라서 추적성 설계에는 세 가지가 함께 있어야 한다.
- 무엇을 연결할지 정하는 객체 모델
- 연결의 의미를 구분하는 링크 유형
- 변경이 일어날 때 연결을 다시 검토하는 운영 절차
Object Schema Table: 최소 추적 객체 모델
추적성은 모든 업무 데이터를 한곳에 복제하는 작업이 아니다. 각 시스템에 있는 객체를 안정적인 ID와 버전으로 참조할 수 있으면 된다.
| 객체 | 역할 | 최소 필드 | 이 객체가 답해야 하는 질문 |
|---|---|---|---|
| Requirement | 구현·검증해야 할 현재 요구 | id, version, statement, source, acceptance_criteria, status, owner, updated_at |
지금 유효한 요구는 무엇이며 어느 버전인가 |
| Change | 요구가 왜, 무엇에서 무엇으로 바뀌었는지 기록 | id, reason, before_ref, after_ref, status, owner, captured_at |
어떤 변경이 발생했고 변경 전후는 무엇인가 |
| Implementation Artifact | 요구를 구현하는 코드·API·DB Schema·설정·문서 | id, kind, location, revision, status, owner |
어떤 산출물이 이 요구를 구현하는가 |
| Test | 요구를 어떤 조건과 결과로 검증하는지 기록 | id, revision, objective, preconditions, test_data_ref, expected_result, status, owner |
어떤 테스트가 어느 요구 버전을 검증하는가 |
| Defect | 검증 또는 운영 중 발견된 불일치 | id, summary, state, severity, source_ref, fix_ref, owner |
무엇이 어떤 근거로 발견됐고 어디와 연결되는가 |
| Release / Baseline Reference | 특정 시점의 요구·구현·테스트 집합을 재현하는 참조 | id, requirement_set_revision, implementation_revision, test_catalog_revision, created_at |
이 추적 상태가 어느 버전 집합을 기준으로 하는가 |
| Change Package | 변경 한 건의 영향 검토와 링크 갱신을 묶는 운영 단위 | id, change_ref, target_baseline, impacted_objects, dispositions, orphan_result, freshness_result, reviewer, state |
이 변경에서 무엇을 확인했고 무엇이 남아 있는가 |
Release / Baseline Reference는 출시 승인 표시가 아니다. “이 표가 어느 요구사항·코드·테스트 버전을 기준으로 만들어졌는지”를 재현하기 위한 좌표에 가깝다.
Traceability Graph: 표가 아니라 연결 구조로 보기
다음은 인증 요구사항이 바뀐 상황을 단순화한 예다.
구조 다이어그램
REQ-AUTH-014@v3
└─ supersedes ──> REQ-AUTH-014@v2
IMPL-auth-api@8f2a
└─ implements ──> REQ-AUTH-014@v3
TC-AUTH-007@v4
└─ verifies ────> REQ-AUTH-014@v3
REQ-AUTH-014@v3
└─ affected_by ─> CHG-042
IMPL-auth-api@8f2a
└─ affected_by ─> CHG-042
TC-AUTH-007@v4
└─ affected_by ─> CHG-042
DEF-088
├─ found_by ────> TC-AUTH-007@v4
└─ blocks ──────> CP-042
CP-042
change: CHG-042
target_baseline: BASE-2026.08.3
BASE-2026.08.3
requirement_set: requirements@v3
implementation_revision: 8f2a
test_catalog_revision: tests@v4
이 그래프에서 중요한 것은 도구의 화면이 아니다. 각 연결이 어떤 관계인지, 어느 버전끼리의 연결인지, 어떤 변경에서 마지막으로 검토됐는지를 알 수 있어야 한다.
Link Type Table: 링크 이름이 있어야 영향 범위를 설명할 수 있다
| Link Type | 방향 | 의미 | 검토할 내용 |
|---|---|---|---|
implements |
Implementation Artifact → Requirement | 해당 산출물이 요구를 구현한다 | 구현 Revision이 현재 요구 버전과 일치하는가 |
verifies |
Test → Requirement | 해당 테스트가 요구를 검증한다 | 조건·데이터·기대 결과가 현재 요구를 실제로 확인하는가 |
affected_by |
Requirement·Implementation·Test·Defect → Change | 해당 객체가 변경의 영향 검토 대상이다 | Change Package에 처리 결과와 근거가 있는가 |
found_by |
Defect → Test | 결함이 해당 테스트에서 발견됐다 | 재현 가능한 테스트와 결함이 연결돼 있는가 |
supersedes |
새 Requirement 또는 Test 버전 → 이전 버전 | 새 객체가 이전 객체를 대체한다 | 이전 객체가 폐기·대체 상태로 정리됐는가 |
blocks |
Defect → Change Package | 결함 처리가 기록되기 전에는 변경 패키지를 닫을 수 없다 | 수정·재현 불가·별도 이관 등의 상태와 근거가 기록됐는가 |
모든 결함이 테스트에서 발견되는 것은 아니다. 고객 문의, 모니터링, 코드 검토에서 발견된 결함에 가짜 found_by 링크를 만들면 안 된다. 이런 경우에는 source_ref에 실제 발견 근거를 남기고 Change Package의 영향 객체에 연결한다.
blocks도 출시 차단 판정이 아니다. 이 글에서 blocks는 해당 결함의 처리 상태가 정리되기 전까지 변경 영향 검토 패키지를 완료 처리하지 못한다는 뜻으로만 사용한다.
양방향 추적성은 역방향 링크를 하나 더 만드는 일이 아니다
양방향 추적성은 같은 관계를 앞뒤 어느 쪽에서도 조회할 수 있다는 뜻이다.
TC-AUTH-007@v4 --verifies--> REQ-AUTH-014@v3라는 링크가 있다면 다음 질문에 모두 답할 수 있어야 한다.
- 이 요구사항을 검증하는 테스트는 무엇인가
- 이 테스트는 어떤 요구사항과 버전을 근거로 만들어졌는가
정방향용 행과 역방향용 행을 따로 저장할 필요는 없다. 두 행을 별도로 관리하면 한쪽만 갱신되는 순간 연결이 모순된다. 하나의 링크를 저장하고 조회 방향만 바꾸는 편이 안전하다.
관계는 일대일일 필요도 없다. 하나의 요구사항을 여러 테스트가 검증할 수 있고 하나의 통합 테스트가 여러 요구사항을 함께 검증할 수도 있다. NASA의 양방향 추적성 Guidance도 이러한 다대다 관계와 고아 객체의 검토를 명시한다. (SWEHB)
Change Package: 변경 한 건을 어디까지 확인했는지 묶는다
Change Package는 파일 압축 묶음이나 배포 패키지가 아니다. 하나의 변경이 요구사항·구현·테스트·결함과 링크에 남긴 영향을 끝까지 추적하기 위한 검토 단위다.
변경이 들어오면 먼저 변경 전후 요구사항 버전을 기록한다. 그다음 기존 링크를 따라 영향 후보를 모은다. 후보마다 다음 중 하나를 지정한다.
update— 내용을 수정해야 함retain— 다시 검토했지만 그대로 유지retire— 더 이상 유효하지 않아 폐기not_impacted— 후보로 발견됐지만 영향 없음
retain과 not_impacted에도 근거가 있어야 한다. 아무 기록 없이 상태를 유지하면 “검토해서 유지한 것”과 “검토하지 않은 것”을 구분할 수 없다.
NASA의 요구사항 관리 체계도 변경 영향 분석 결과와 관련 문서 갱신 조치를 Change Package에 포함하고 갱신이 완료될 때까지 추적하도록 한다. SWE-053은 변경된 요구사항뿐 아니라 관련 설계·코드·테스트·문서와 추적 정보도 최신 상태로 유지해야 한다고 설명한다. (NASA)
Change Package Checklist
| 확인 항목 | 완료 조건 |
|---|---|
| 변경 식별 | change_id, 변경 이유, 요청자·Owner가 기록됨 |
| 변경 전후 요구 | before_ref와 after_ref가 버전까지 식별됨 |
| 영향 후보 탐색 | Requirement에서 구현·테스트·결함 방향으로, 구현·테스트에서 Requirement 방향으로 탐색함 |
| 구현 산출물 검토 | 모든 후보에 update, retain, retire, not_impacted 중 하나와 근거가 있음 |
| 테스트 검토 | 변경된 요구를 검증하는 테스트의 Revision·조건·기대 결과를 검토함 |
| 결함 검토 | 연결된 미해결 결함의 상태와 Change Package에 미치는 영향이 기록됨 |
| 링크 갱신 | 추가·수정·삭제·대체된 링크와 검토자가 기록됨 |
| 고아 탐지 | 정의된 Orphan Rule을 실행하고 결과를 처리함 |
| 최신성 검토 | 관련 링크가 present, reviewed, stale 중 하나로 분류됨 |
| Baseline 고정 | 요구·구현·테스트 집합의 기준 Revision이 기록됨 |
| 검토 기록 | Owner, Reviewer, 검토 시점, 미해결 후속 작업이 남음 |
Change Package가 닫혔다는 것은 “변경 영향과 링크를 정해진 절차로 검토했다”는 뜻이다. 그 자체로 소프트웨어의 출시 가능 여부를 의미하지 않는다.
Orphan Rule Table: 연결되지 않은 항목을 자동으로 질문하게 만들기
고아 항목은 무조건 잘못된 데이터가 아니다. 다만 사람이 설명해야 할 연결 공백이다. 자동 검사는 고아를 삭제하거나 임의의 링크를 만들기보다 검토 대기열에 올려야 한다.
| Orphan Rule | 탐지 조건 | 왜 문제인가 | 필요한 조치 |
|---|---|---|---|
| 테스트 없는 변경된 요구사항 | 현재 Change Package에서 변경된 active·검증 가능 Requirement에 reviewed 상태의 verifies 링크가 없음 |
새 요구가 검증 체계에서 빠질 수 있음 | 테스트 추가·수정 또는 검증 불필요 근거 기록 |
| 근거 없는 테스트 | active Test가 현재 유효한 Requirement나 승인된 별도 근거와 연결되지 않음 |
무엇을 확인하는 테스트인지 알 수 없고 유지보수 비용만 남을 수 있음 | 요구와 연결하거나 근거를 보완하고 불필요하면 폐기 |
| 연결되지 않은 결함 | Defect에 실제 발견 근거가 없고 관련 Change·Test·영향 객체도 식별되지 않음 | 재현·수정·재검증 경로를 찾기 어려움 | 실제 source_ref, found_by, 영향 객체를 보완 |
| Impact Review 없는 변경 | 승인 또는 구현된 Change에 Change Package가 없거나 영향 후보의 Disposition이 미완료 | 일부 코드·테스트·문서가 변경에서 빠질 수 있음 | Change Package 생성 및 양방향 영향 검토 |
| 폐기된 요구를 계속 검증하는 테스트 | active Test가 retired 또는 superseded Requirement에만 연결됨 |
테스트는 실행되지만 현재 요구 충족을 설명하지 못함 | 새 요구 버전에 재연결·갱신하거나 테스트 폐기 |
NASA SWE-052도 출처가 없는 설계·구현 등의 고아 요소를 자동으로 불필요하다고 단정하지 않고 팀이 필요성을 검토한 뒤 빠진 상위 근거를 추가하거나 객체를 정리하도록 한다. (SWEHB)
Link Freshness: 링크가 있다는 것과 믿을 수 있다는 것은 다르다
링크 상태를 Boolean 하나로 관리하면 true인 오래된 링크가 정상 연결처럼 보인다. 최소한 다음 세 상태를 구분하는 편이 낫다.
| 상태 | 의미 | 필요한 Evidence |
|---|---|---|
present |
양쪽 객체와 Link Type이 존재한다 | from, type, to, 생성 시점 |
reviewed |
현재 Change 또는 Baseline에서 양쪽 버전과 관계의 의미를 검토했다 | Endpoint 버전, reviewed_at, reviewed_by, review_context |
stale |
링크가 가리키는 객체나 검토 Context가 변경돼 현재 상태를 설명하지 못한다 | stale_reason, 변경된 Endpoint, 마지막 검토 Context |
다음 중 하나가 발생하면 링크를 오래된 상태로 전환할 수 있다.
- Requirement가 새 버전으로 대체됨
- Test의 조건·데이터·기대 결과가 수정됨
- Implementation Artifact의 Revision이 바뀜
- 연결 대상이 폐기 또는 삭제됨
- 현재 Change Package가 Link Endpoint를 영향 대상으로 식별했지만 링크 재검토가 끝나지 않음
- 새 Baseline이 만들어졌지만 해당 링크가 그 Baseline에서 검토되지 않음
오래됨을 날짜만으로 판단할 필요는 없다. 6개월 전에 만들어졌어도 양쪽 객체가 바뀌지 않았고 현재 Baseline에서 다시 검토됐다면 유효할 수 있다. 반대로 어제 만든 링크도 오늘 Requirement가 대체됐다면 오래된 링크다.
최소 Link Record는 다음 정도면 충분하다.
yaml 예시
link_id: LINK-1042
from: TC-AUTH-007@v4
type: verifies
to: REQ-AUTH-014@v3
created_at: 2026-08-19
created_by: qa-owner
freshness: reviewed
reviewed_at: 2026-08-21
reviewed_by: change-reviewer
review_context: CP-042
source_version: 4
target_version: 3
stale_reason: null
Trace Coverage와 Test Pass Rate는 서로 다른 숫자다
추적 커버리지는 구조의 완전성을 본다. 테스트 통과율은 특정 실행 결과를 본다.
| 지표 | 이 글에서의 정의 | 답하는 질문 |
|---|---|---|
| Reviewed Trace Coverage | 검증 가능한 변경 Requirement 중 하나 이상의 reviewed verifies 링크를 가진 Requirement 비율 |
변경된 요구가 테스트 구조에 빠짐없이 연결됐는가 |
| Test Pass Rate | 특정 실행에서 수행된 테스트 중 통과한 실행 비율 | 이번에 실행한 테스트는 얼마나 통과했는가 |
예를 들어 검증 가능한 변경 요구사항이 10개이고 검토 완료된 테스트 링크가 있는 요구사항이 8개라면 추적 커버리지는 80%다.
계산식
Reviewed Trace Coverage
= reviewed verifies 링크가 있는 변경 Requirement 수
/ 검증 가능한 전체 변경 Requirement 수
= 8 / 10
= 80%
한편 테스트 20개를 실행해 18개가 통과했다면 이 글에서 정의한 통과율은 90%다.
계산식
Test Pass Rate
= 통과한 테스트 실행 수 / 전체 실행한 테스트 수
= 18 / 20
= 90%
90%라는 통과율은 연결되지 않은 두 요구사항을 설명하지 못한다. 반대로 추적 커버리지가 100%여도 테스트가 실행됐거나 통과했다는 뜻은 아니다. 하나의 링크가 해당 요구를 충분히 검증하는지도 별도의 검토 대상이다.
작은 팀은 스프레드시트나 YAML로도 시작할 수 있다
처음부터 전용 요구사항 관리 플랫폼을 도입할 필요는 없다. NASA Software Engineering Handbook도 소규모 프로젝트에서는 스프레드시트나 경량 매트릭스로 요구사항·테스트·변경을 관리할 수 있다고 설명한다. 중요한 것은 도구보다 고유 ID, 버전, 관계, 유지 책임이다. (SWEHB)
작은 팀의 최소 구현은 다음과 같다.
- 객체 ID를 먼저 고정한다.
요구사항은 REQ-*, 변경은 CHG-*, 테스트는 TC-*, 결함은 DEF-*처럼 도구가 바뀌어도 유지되는 ID를 사용한다.
- 객체와 링크를 분리한다.
요구사항 행 안에 테스트 ID를 문자열로 계속 붙이는 대신, from–type–to 형태의 Link Table을 따로 둔다.
- 모든 승인된 변경에 Change Package를 하나 만든다.
규모가 작다면 이슈 템플릿이나 YAML 파일 한 개여도 된다.
- PR·테스트·결함에 관련 ID를 남긴다.
링크 테이블만 보지 않고 실제 작업 위치에서도 Requirement와 Change를 찾을 수 있게 한다.
- 간단한 자동 검사를 붙인다.
존재하지 않는 ID, 허용되지 않은 객체 유형 조합, 변경된 요구의 테스트 링크 누락, 폐기된 요구를 가리키는 테스트를 검사한다.
- 날짜가 아니라 사건에 맞춰 재검토한다.
Requirement 변경, Test Revision 변경, Change Package 종료, Baseline 생성이 링크 검토의 Trigger가 된다.
여러 역할을 한 사람이 맡을 수는 있다. 다만 owner, reviewer, reviewed_at 필드는 없애지 않는 편이 좋다. 역할이 같은 사람에게 있더라도 어떤 책임으로 무엇을 확인했는지는 남아야 한다.
Vendor-neutral 최소 YAML 예시
yaml 예시
baseline:
id: BASE-2026.08.3
requirement_set_revision: requirements@v3
implementation_revision: 8f2a
test_catalog_revision: tests@v4
created_at: 2026-08-21
objects:
- id: REQ-AUTH-014@v2
type: requirement
status: superseded
- id: REQ-AUTH-014@v3
type: requirement
status: active
owner: product-owner
- id: CHG-042
type: change
before_ref: REQ-AUTH-014@v2
after_ref: REQ-AUTH-014@v3
status: under_review
- id: IMPL-auth-api@8f2a
type: implementation_artifact
kind: api_module
status: active
- id: TC-AUTH-007@v4
type: test
status: active
owner: qa-owner
- id: DEF-088
type: defect
state: open
source_ref: TC-AUTH-007@v4
links:
- from: REQ-AUTH-014@v3
type: supersedes
to: REQ-AUTH-014@v2
freshness: reviewed
review_context: CP-042
- from: IMPL-auth-api@8f2a
type: implements
to: REQ-AUTH-014@v3
freshness: reviewed
review_context: CP-042
- from: TC-AUTH-007@v4
type: verifies
to: REQ-AUTH-014@v3
freshness: reviewed
review_context: CP-042
- from: REQ-AUTH-014@v3
type: affected_by
to: CHG-042
freshness: reviewed
review_context: CP-042
- from: DEF-088
type: found_by
to: TC-AUTH-007@v4
freshness: reviewed
review_context: CP-042
- from: DEF-088
type: blocks
to: CP-042
freshness: present
change_package:
id: CP-042
change_ref: CHG-042
target_baseline: BASE-2026.08.3
state: impact_reviewed
impacted_objects:
- ref: IMPL-auth-api@8f2a
disposition: update
rationale: requirement constraint changed
- ref: TC-AUTH-007@v4
disposition: update
rationale: expected result changed
orphan_checks:
changed_requirement_without_test: pass
test_without_basis: pass
disconnected_defect: pass
change_without_impact_review: pass
active_test_for_retired_requirement: pass
freshness_result:
present: 1
reviewed: 5
stale: 0
reviewer: change-reviewer
reviewed_at: 2026-08-21
실제 저장소에서는 객체 정보가 각 업무 도구에 남아 있어도 된다. YAML은 모든 원문을 복제하는 데이터베이스가 아니라 객체 ID와 Link Record를 연결하는 최소 Registry로 사용할 수 있다.
추적성의 최종 산출물은 ‘검토 가능한 영향 범위’다
잘 설계된 추적성은 요구사항마다 테스트 ID가 하나씩 들어 있는 표보다 더 많은 것을 보여준다.
- 어떤 변경이 발생했는가
- 어떤 구현·테스트·결함이 영향 후보로 발견됐는가
- 각 후보를 수정·유지·폐기·영향 없음으로 판단한 근거는 무엇인가
- 연결되지 않은 객체는 무엇인가
- 존재하지만 현재 변경에서는 다시 검토되지 않은 링크는 무엇인가
- 어느 요구·구현·테스트 버전을 기준으로 이 결과를 재현할 수 있는가
여기까지 확인하면 팀은 변경으로 인해 살펴봐야 할 범위를 설명할 수 있다. 그 후보 중 어떤 회귀 테스트를 실제로 실행할지는 별도의 선택 규칙이 필요하다.
그리고 추적성만으로 출시 여부가 결정되지는 않는다. 추적성은 전체 출시 판단에 필요한 증거 중 변경 영향과 검증 연결의 구조를 담당한다.