[CS300 #183] 요구사항 분석 — 무엇을 만들지 검증 가능한 문장으로 적기
컴퓨터공학 300 주제 시리즈의 183번째 글이다. 전체 지도는 여기.
한 줄 요약
요구사항 분석은 이해관계자가 원하는 것을 찾아내고(도출), 정리하고(분석), 문서로 남기고(명세), 그것이 맞는지 확인하는(검증) 일이다. 좋은 요구사항은 테스트로 확인할 수 있는 문장이다.
왜 필요한가
“검색이 빨랐으면 좋겠어요.” 이 문장을 받은 개발자는 무엇을 만들어야 할까. 0.1초? 1초? 검색 결과 1만 건에서? 1억 건에서? 동시에 몇 명이 검색할 때?
요구사항이 모호하면 개발자는 자기 해석대로 만든다. 그 해석이 틀렸다는 사실은 사용자가 결과물을 볼 때 드러난다. 앞의 생명주기 글에서 봤듯이, 그 시점이 늦을수록 되돌리는 비용이 크다. 요구사항 분석은 “무엇을 만들지” 에 대한 오해를 코드를 짜기 전에 잡는 거의 유일한 기회다.
핵심 개념
요구사항 공학의 네 활동
| 활동 | 하는 일 | 도구·기법 |
|---|---|---|
| 도출(elicitation) | 이해관계자에게서 필요를 끌어낸다 | 인터뷰, 관찰, 워크숍, 기존 시스템 분석 |
| 분석(analysis) | 충돌·누락을 찾고 우선순위를 정한다 | 모델링, 우선순위 기법 |
| 명세(specification) | 합의된 내용을 기록한다 | 요구사항 명세서, 사용자 스토리 |
| 검증(validation) | 기록이 실제 필요와 맞는지 확인한다 | 리뷰, 프로토타입, 인수 기준 |
SWEBOK 은 이 흐름을 “소프트웨어 요구사항” 지식 영역으로 다루고, ISO/IEC/IEEE 29148 은 요구사항 공학 프로세스와 명세서 내용을 표준화한다.
기능 요구사항과 비기능 요구사항
- 기능 요구사항: 시스템이 무엇을 하는가. “사용자는 이메일과 비밀번호로 로그인할 수 있다.”
- 비기능 요구사항: 시스템이 얼마나 잘 하는가. 성능, 보안, 가용성, 사용성, 유지보수성 등. “로그인 API 의 95번째 백분위 응답 시간은 300ms 이하다.”
비기능 요구사항은 빠뜨리기 쉽고, 나중에 고치기 어렵다. 기능은 하나를 더 붙이면 되지만, “초당 1만 건을 처리해야 한다” 는 요구는 아키텍처 전체를 바꿀 수 있다. 품질 특성을 빠짐없이 훑을 때는 ISO/IEC 25010 품질 모델이 체크리스트로 쓸 만하다. 2011년판은 기능 적합성, 성능 효율성, 호환성, 사용성, 신뢰성, 보안성, 유지보수성, 이식성의 8가지 특성을 정의한다(2023년에 개정판이 나왔다).
좋은 요구사항의 성질
ISO/IEC/IEEE 29148 은 개별 요구사항이 갖춰야 할 특성으로 필요성, 명확성(모호하지 않음), 완전성, 단일성, 실현 가능성, 검증 가능성 등을 든다. 실무에서 가장 자주 깨지는 것은 세 가지다.
| 성질 | 나쁜 예 | 고친 예 |
|---|---|---|
| 명확성 | 화면이 적절히 빨리 떠야 한다 | 상품 목록 첫 화면은 4G 환경에서 2초 안에 표시된다 |
| 단일성 | 주문하고 결제하고 영수증을 메일로 보낸다 | 세 개의 요구사항으로 나눈다 |
| 검증 가능성 | 사용하기 쉬워야 한다 | 신규 사용자 5명 중 4명이 도움말 없이 3분 안에 첫 주문을 마친다 |
요구 수준을 나타내는 단어: RFC 2119
인터넷 표준 문서는 요구의 강도를 RFC 2119 의 키워드로 표시한다. MUST(반드시), SHOULD(특별한 이유가 없으면), MAY(선택) 등이다. RFC 8174 는 이 키워드가 대문자로 쓰였을 때만 이 특별한 뜻을 갖는다고 명확히 했다. 사내 명세서에도 이 구분을 빌려 쓰면 “해야 한다” 와 “하면 좋다” 가 섞여 생기는 다툼이 줄어든다.
사용자 스토리와 인수 기준
애자일 팀은 요구사항을 사용자 스토리로 많이 적는다.
[사용자 스토리]
장바구니를 쓰는 고객으로서,
담아 둔 상품의 가격이 바뀌면 알림을 받고 싶다.
그래야 결제 직전에 놀라지 않는다.
“누가, 무엇을, 왜” 가 한 묶음이다. “왜” 가 빠지면 개발자가 더 나은 해법을 제안할 여지가 사라진다. 스토리만으로는 검증할 수 없으므로 인수 기준(acceptance criteria)을 붙인다. 행위 주도 개발(BDD)에서 쓰는 Given-When-Then 형식이 흔하다.
시나리오: 담아 둔 상품 가격이 내려감
Given 고객의 장바구니에 10,000원짜리 상품 A 가 있다
When 상품 A 의 가격이 9,000원으로 바뀐다
Then 고객이 장바구니를 열면 "가격이 1,000원 내려갔습니다" 표시가 보인다
이 문장은 그대로 테스트 케이스가 된다. 요구사항과 테스트가 같은 문장을 공유하는 것이 핵심이다.
우선순위: MoSCoW
모든 요구를 다 만들 시간은 거의 없다. MoSCoW 는 요구를 Must have, Should have, Could have, Won’t have(이번에는 안 함) 로 나눈다. “이번에 안 하는 것” 을 명시하는 칸이 있다는 점이 중요하다. 범위에서 뺀 것을 적어 두지 않으면 나중에 “그것도 되는 줄 알았다” 가 나온다.
추적성
요구사항마다 ID 를 붙이고, 그 요구사항을 구현한 코드와 확인하는 테스트를 연결해 두는 것을 추적성이라 한다. 요구가 바뀌면 영향받는 코드와 테스트를 바로 찾을 수 있고, 테스트가 없는 요구사항도 드러난다.
직접 해 보기
요구사항 문장에서 모호한 표현과 측정 기준 누락을 잡아내는 작은 린터를 만들어 본다. 실제 도구들도 기본 원리는 비슷하다.
import re
VAGUE = ["빠르게", "빨리", "적절히", "충분히", "쉽게", "편리하게", "등", "가능한 한", "사용자 친화적"]
NUMBER_WITH_UNIT = re.compile(r"\d+(\.\d+)?\s*(ms|초|분|%|건|명|MB|GB|회)")
requirements = {
"REQ-001": "사용자는 이메일과 비밀번호로 로그인할 수 있다.",
"REQ-002": "검색 결과는 빠르게 표시되어야 한다.",
"REQ-003": "로그인 API 의 p95 응답 시간은 300 ms 이하여야 한다.",
"REQ-004": "주문하고 결제하고 영수증을 메일로 보낸다.",
"REQ-005": "관리 화면은 사용자 친화적이어야 하며 충분히 안전해야 한다.",
}
def lint(text):
problems = []
for w in VAGUE:
if w in text:
problems.append(f"모호한 표현 '{w}'")
if ("성능" in text or "응답" in text or "빠르" in text) and not NUMBER_WITH_UNIT.search(text):
problems.append("성능 요구인데 수치·단위가 없음")
if text.count("하고") >= 2:
problems.append("여러 요구가 한 문장에 섞임(단일성)")
return problems
for rid, text in requirements.items():
p = lint(text)
print(f"{rid} {'OK ' if not p else 'FIX'} {text}")
for item in p:
print(f" - {item}")
실행 결과:
REQ-001 OK 사용자는 이메일과 비밀번호로 로그인할 수 있다.
REQ-002 FIX 검색 결과는 빠르게 표시되어야 한다.
- 모호한 표현 '빠르게'
- 성능 요구인데 수치·단위가 없음
REQ-003 OK 로그인 API 의 p95 응답 시간은 300 ms 이하여야 한다.
REQ-004 FIX 주문하고 결제하고 영수증을 메일로 보낸다.
- 여러 요구가 한 문장에 섞임(단일성)
REQ-005 FIX 관리 화면은 사용자 친화적이어야 하며 충분히 안전해야 한다.
- 모호한 표현 '충분히'
- 모호한 표현 '사용자 친화적'
REQ-002 는 “빠르게” 라는 단어 하나 때문에 검증할 수 없는 문장이 됐다. REQ-003 처럼 지표(p95), 수치(300), 단위(ms)가 있어야 테스트로 통과·실패를 판정할 수 있다. 물론 이런 키워드 검사는 출발점일 뿐이다. 진짜 검증은 이해관계자와 함께 문장을 읽고 “이 조건이면 받아들이시겠어요?” 라고 묻는 리뷰에서 일어난다.
현업에서는
- 티켓 템플릿에 인수 기준 칸을 강제한다. 이슈 템플릿에 “완료 조건” 칸을 두면, 모호한 요구가 개발 단계로 넘어오기 전에 걸러진다.
- 비기능 요구사항은 SLO 로 바뀐다. “서비스는 안정적이어야 한다” 는 운영 단계에서 “월간 가용성 99.9%, p99 지연 500ms” 같은 서비스 수준 목표(SLO)로 구체화된다. 홈랩 클러스터에서도 모니터링 알림 임계값을 정하는 순간 이 작업을 하고 있는 것이다.
- “안 하는 것” 목록이 다툼을 줄인다. 릴리스 노트나 기획서에 “이번 범위 밖” 을 적는 팀은 막판 범위 논쟁이 적다.
- 도메인 전문가의 말을 그대로 쓴다. 사용자가 “출고” 라고 부르는 것을 개발 문서에서 “shipment” 와 “delivery” 로 섞어 쓰면 오해가 생긴다. 이 문제는 도메인 주도 설계의 “보편 언어” 로 이어진다.
확인 문제
- 기능 요구사항과 비기능 요구사항을 하나씩 예로 들라.
- “시스템은 사용하기 쉬워야 한다” 를 검증 가능한 요구사항으로 고쳐 써라.
- RFC 8174 가 RFC 2119 에 덧붙인 핵심 내용은 무엇인가?
- 사용자 스토리에서 “그래야 ~” 부분(이유)을 빼면 무엇을 잃는가?
- MoSCoW 에서 W 항목을 명시하는 이유는 무엇인가?
풀이
- 기능: “사용자는 비밀번호를 재설정할 수 있다.” 비기능: “비밀번호 재설정 메일은 요청 후 1분 안에 발송된다.”
- 예: “처음 쓰는 사용자 5명 중 4명 이상이 도움말 없이 3분 안에 회원가입을 마친다.” 대상, 조건, 측정 기준이 들어가면 된다.
- MUST·SHOULD 같은 키워드가 대문자로 쓰였을 때만 RFC 2119 의 특별한 의미를 갖는다는 점.
- 요구의 목적. 목적을 모르면 개발자가 더 단순하거나 나은 대안을 제안할 수 없고, 우선순위 판단도 어려워진다.
- 범위에서 뺀 것을 합의된 기록으로 남겨, 나중에 “그것도 포함인 줄 알았다” 는 오해를 막기 위해서다.
더 읽을거리 (References)
- S. Bradner, RFC 2119 — Key words for use in RFCs to Indicate Requirement Levels
- B. Leiba, RFC 8174 — Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words
- IEEE Computer Society, SWEBOK — Software Requirements 지식 영역
- ISO/IEC/IEEE 29148:2018, Systems and software engineering — Life cycle processes — Requirements engineering (서지 정보)
- ISO/IEC 25010:2011, Systems and software Quality Requirements and Evaluation (SQuaRE) — System and software quality models (서지 정보)