소프트웨어 공학 100 주제 시리즈의 12번째 글이다. (카테고리: 요구사항 공학)

한 줄 요약

“비기능 요구사항” 은 정의부터 합의가 없는 말이다. Glinz 의 관심사 기반 분류로 성능·특정 품질·제약을 나눠 부르고, ISO/IEC 25010:2023 의 아홉 가지 품질 특성을 빠짐없이 훑는 체크리스트로 쓰고, 각 항목을 측정 가능한 시나리오로 바꾸는 것이 실무의 정석이다.

왜 필요한가

기능 요구는 빠지면 티가 난다. 버튼이 없으니까. 비기능 요구는 빠져도 데모에서는 아무 문제가 없다. 문제는 트래픽이 열 배가 된 날, 감사를 받는 날, 개발자가 바뀌어 코드를 처음 읽는 날 드러난다. 그리고 그때 고치려면 아키텍처를 건드려야 한다.

두 번째 문제는 말이 통하지 않는 것이다. “보안이 중요합니다”, “확장성 있게 해 주세요” 는 요구가 아니라 희망이다. 기획자는 받아들였다고 생각하고, 개발자는 들어 본 적 없다고 생각한다. 요구사항 분석 글에서 25010:2011 의 여덟 특성을 소개했는데, 그사이 표준이 바뀌었고 분류 자체에 대한 논쟁도 있다. 이 글은 그 둘을 정리한다.

핵심 개념

“비기능” 이라는 말의 문제

Martin Glinz 는 RE’07 논문 On Non-Functional Requirements (DOI)에서 교과서·표준·웹에서 고른 열세 가지 정의를 나란히 놓고, 정의마다 “속성”, “제약”, “성능”, “품질” 같은 용어를 서로 다르게 쓴다는 것을 보였다. 어떤 정의는 제약을 비기능 요구의 하위 범주로, 어떤 정의는 모든 비기능 요구를 제약으로 본다.

그가 제안한 관심사(concern) 기반 분류는 이렇다.

요구사항
├── 프로젝트 요구사항 / 프로세스 요구사항   (시스템 요구와 뿌리부터 분리)
└── 시스템 요구사항
    ├── 기능 요구사항        — 동작·데이터·입력에 대한 반응
    ├── 속성(attribute)
    │   ├── 성능 요구사항    — 시간, 속도, 용량, 처리량
    │   └── 특정 품질 요구사항 — 신뢰성, 사용성, 보안, 이식성 …
    └── 제약(constraint)      — 물리·법·문화·환경·설계·구현·인터페이스

그리고 비기능 요구사항을 “시스템의 속성 또는 시스템에 대한 제약” 으로 정의한다. 성능을 따로 떼는 이유도 명시한다. 성능은 시간·용량·단위시간당 용량으로 재는 데 넓은 합의가 있지만, 다른 품질 특성은 일반적으로 합의된 척도가 없어서 이해관계자와 측정 방법부터 합의해야 하기 때문이다.

또 하나 중요한 관찰: 표현이 검증 방법을 정한다.

표현 방식 검증 방법 (Glinz)
동작으로 표현(operational) 리뷰, 테스트, 형식 검증
정량적 측정
정성적 직접 검증 불가 — 주관적 판단, 프로토타입, 목표 세분화로 간접 확인
선언적 리뷰

“사용하기 쉬워야 한다” 가 문제인 이유는 비기능이어서가 아니라 정성적으로 표현돼서다.

ISO/IEC 25010:2023 — 아홉 가지 제품 품질 특성

ISO/IEC 25010:2023은 2011년판을 대체한다. 서문에 적힌 주요 변경은 다음과 같다.

  • 2011년판의 사용 품질(quality in use) 모델은 ISO/IEC 25019 로, 품질 모델 개요와 사용법은 ISO/IEC 25002 로 옮겨졌다. 25010 은 제품 품질 모델만 남았다.
  • 안전성(safety)이 특성으로 추가됐다.
  • 사용성(usability)과 이식성(portability)이 각각 상호작용 능력(interaction capability)과 유연성(flexibility)으로 바뀌었다.
  • 하위 특성으로 포용성(inclusivity), 자기 서술성(self-descriptiveness), 저항성(resistance), 확장성(scalability)이 추가됐다.
특성 묻는 질문 요구로 바꾼 예
기능 적합성 명시·암묵적 필요를 충족하는 기능이 있나 정산 금액은 원 단위까지 원장과 일치한다
성능 효율성 자원 대비 성능 피크 300 RPS 에서 p95 응답 400ms 이하
호환성 다른 시스템과 공존·정보 교환 기존 ERP 의 CSV 포맷을 수정 없이 읽는다
상호작용 능력 지정된 사용자가 목표를 효과적으로 달성 첫 사용자 다섯 명 중 넷이 도움 없이 예약을 마친다
신뢰성 정해진 조건·기간 동안 기능 수행 월 가용성 99.9%, 장애 후 15분 안에 복구
보안성 권한에 맞는 접근, 공격 저항 관리자 기능은 MFA 없이 접근 불가
유지보수성 의도된 유지보수자가 효과적으로 수정 결제 수단 하나 추가가 한 모듈 변경으로 끝난다
유연성 다른·변하는 환경에 적응 노드를 추가하면 처리량이 늘어난다
안전성 사람·재산·환경에 대한 위해 회피 센서 이상 시 장비를 안전 상태로 전환한다

표의 숫자는 형식을 보여 주는 예시다. 실제 값은 이해관계자와 정한다.

품질 속성 시나리오

특성 이름만으로는 여전히 측정할 수 없다. 아키텍처 분야에서 널리 쓰는 형식이 품질 속성 시나리오다(Bass, Clements, Kazman, Software Architecture in Practice). 여섯 부분으로 쓴다.

자극원(source)        : 외부 결제 대행사
자극(stimulus)        : 응답이 30초 이상 오지 않음
환경(environment)     : 평일 피크 시간, 정상 운영
대상(artifact)        : 주문 서비스
반응(response)        : 주문을 '결제 대기' 로 두고 사용자에게 안내, 재시도 큐에 등록
반응 측정(measure)    : 사용자 화면은 2초 안에 응답, 주문 유실 0건

이렇게 쓰면 “신뢰성 있게” 가 테스트 가능한 문장이 된다. 장애 주입 테스트로 바로 확인할 수 있다.

운영 단계의 비기능 요구: SLI 와 SLO

운영 중인 서비스에서 성능·신뢰성 요구는 결국 SLI/SLO 로 바뀐다. Google SRE 책은 SLI 를 “제공되는 서비스 수준의 어떤 측면에 대한, 신중하게 정의된 정량적 척도” 로, SLO 를 “SLI 로 측정되는 서비스 수준의 목표값 또는 범위” 로 정의한다. 그리고 평균보다 백분위를 선호한다. 평균은 꼬리 지연을 가리기 때문이다. 요구 문장에 “평균 응답 시간” 이 있다면 의심하라.

실무 적용

25010 을 체크리스트로 쓰는 워크숍

  1. 특성 아홉 개를 카드로 깔아 둔다.
  2. 이해관계자에게 각 카드마다 “이게 깨지면 누가, 얼마나 아픈가” 를 묻는다.
  3. 아픈 카드만 남기고 나머지는 “이번 범위에서는 기본 수준” 으로 명시한다(빠뜨린 것과 의도적으로 뺀 것을 구분).
  4. 남은 카드마다 품질 속성 시나리오를 하나 이상 쓴다.
  5. 시나리오가 서로 부딪히는지 확인한다. 보안(매 요청 토큰 검증)과 성능(p95 100ms)은 자주 충돌한다. 충돌은 아키텍처 결정으로 넘긴다.

비기능 요구를 코드로 고정하기

측정 가능한 요구는 CI 에서 깨지게 만들 수 있다. 예를 들어 성능 회귀 검사:

# perf_gate.py — 부하 테스트 결과(JSON)를 읽어 요구 위반 시 실패
import json, sys

REQUIREMENTS = {               # 요구 ID: (지표, 한계)
    "NFR-PERF-01": ("p95_ms", 400),
    "NFR-PERF-02": ("error_rate", 0.001),
}

result = json.load(open(sys.argv[1]))   # {"p95_ms": 352, "error_rate": 0.0004}
failed = False
for rid, (metric, limit) in REQUIREMENTS.items():
    value = result[metric]
    ok = value <= limit
    failed |= not ok
    print(f"{rid} {metric}={value} limit={limit} {'PASS' if ok else 'FAIL'}")
sys.exit(1 if failed else 0)

요구 ID 를 출력에 남기면 실패한 빌드가 어떤 요구를 어겼는지 바로 보인다(추적성은 SE100 #019 에서 다룬다).

흔한 오해와 함정

  • “비기능 요구는 나중에 튜닝하면 된다.” 성능 일부는 그렇다. 하지만 보안·가용성·유연성 요구는 구조를 결정한다. 늦게 발견할수록 변경 범위가 커진다.
  • “25010 의 모든 특성에 요구를 써야 한다.” 체크리스트는 빠뜨리지 않기 위한 도구다. 모든 칸을 채우면 정작 중요한 두세 개가 묻힌다.
  • “사용성 = 상호작용 능력” 으로 그냥 바꿔 부르면 된다. 2023년판은 제품 모델의 상호작용 능력과, 25019 의 사용 품질 모델에서 말하는 사용성을 구분한다. 표준 노트는 상호작용 능력을 사용성의 전제 조건으로 설명한다. 제품을 써 본 사람의 결과로서의 사용성은 사용 맥락에서 재야 한다.
  • 2011년판 문서를 그대로 인용한다. 여덟 특성 체계로 쓴 사내 템플릿은 안전성 항목이 비어 있다. 물리적 장치나 의료·차량 도메인이라면 특히 확인해야 한다.
  • “빠르게”, “안전하게” 를 숫자 없이 둔다. Glinz 의 표처럼 정성적 표현은 직접 검증할 방법이 없다. 숫자를 정할 수 없다면 적어도 프로토타입으로 판단할 기준을 정한다.

확인 문제

  1. Glinz 가 성능을 다른 품질 특성과 분리한 이유는?
  2. ISO/IEC 25010:2023 에서 새로 추가된 특성과 이름이 바뀐 특성 두 가지는?
  3. 2011년판 25010 에 있던 사용 품질 모델은 어디로 갔는가?
  4. “결제 서비스는 장애에 강해야 한다” 를 품질 속성 시나리오 여섯 부분으로 다시 써 보라.
  5. SLO 를 평균이 아니라 백분위로 정하는 이유는?

풀이

  1. 성능은 시간·용량·처리량으로 재는 데 넓은 합의가 있지만, 다른 품질 특성은 합의된 척도가 없어 측정 방법부터 이해관계자와 정해야 하기 때문이다. 실무에서도 성능 요구는 따로 다뤄진다.
  2. 추가: 안전성. 변경: 사용성 → 상호작용 능력, 이식성 → 유연성.
  3. ISO/IEC 25019(사용 품질 모델)로 옮겨졌다. 품질 모델 개요·사용법은 ISO/IEC 25002 로 갔다.
  4. 예: 자극원 — 카드사 API, 자극 — 5분간 연결 실패, 환경 — 정상 운영 피크, 대상 — 결제 서비스, 반응 — 대체 PG 로 전환하고 실패 건은 재시도 큐에, 측정 — 전환까지 30초 이내, 이중 결제 0건.
  5. 평균은 소수의 매우 느린 요청(꼬리)을 가린다. 백분위는 분포의 모양, 특히 사용자가 체감하는 최악에 가까운 경험을 드러낸다.

더 읽을거리 (References)