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

한 줄 요약

유스케이스는 타원과 막대 인간이 아니라 글이다. Cockburn 식 유스케이스는 주 행위자의 목표 하나를 두고, 성공하는 주 시나리오와 그 시나리오가 갈라지는 확장을 적어, 시스템과 이해관계자 사이의 행동 계약을 만든다.

왜 필요한가

UML 기초에서 유스케이스 다이어그램을 본 사람은 많다. 그런데 다이어그램만 그리고 끝내는 팀에서는 이런 일이 생긴다.

  • 타원 이름이 “회원 관리”, “주문 처리” 같은 기능 메뉴가 된다. 누가 무엇을 이루려는지 드러나지 않는다.
  • 성공 경로만 있다. 카드 한도 초과, 재고 소진, 세션 만료는 개발자가 코드를 짜다가 혼자 결정한다.
  • 화면 설계와 섞인다. “확인 버튼을 클릭한다” 가 요구사항에 들어가 UI 를 바꿀 때마다 요구 문서도 바뀐다.

사용자 스토리가 주류가 된 지금도 유스케이스가 쓸모 있는 이유는 예외 흐름을 체계적으로 찾게 만드는 구조 때문이다. 스토리는 계획 단위로 잘게 자르는 데 강하고, 유스케이스는 이야기 전체와 그 갈림길을 보여 주는 데 강하다.

핵심 개념

기원과 위치

유스케이스는 Ivar Jacobson 의 객체지향 방법론에서 나왔다. 1987년 OOPSLA 논문 Object-oriented development in an industrial environment 와 1992년 책 Object-Oriented Software Engineering: A Use Case Driven Approach 가 대표적이다. 이후 UML 이 유스케이스 다이어그램 표기를 표준화했지만, UML 은 유스케이스의 본문을 어떻게 쓸지는 정하지 않는다.

그 빈자리를 채운 것이 Alistair Cockburn 의 Writing Effective Use Cases (Addison-Wesley, 2001)다. 이 글의 템플릿과 용어는 이 책을 따른다.

행동 계약이라는 관점

Cockburn 은 유스케이스를 시스템과 이해관계자 사이의 행동 계약으로 본다. 여기서 중요한 구분이 둘 있다.

용어 뜻
주 행위자(primary actor) 시스템을 사용해 목표를 이루려는 쪽. 유스케이스를 시작한다
이해관계자(stakeholder) 시스템 동작에 이해(interest)가 걸린 모든 쪽. 그 자리에 없을 수도 있다

주문 유스케이스의 주 행위자는 고객이지만, 이해관계자에는 매장(돈을 받아야 함), 회계(세금 기록), 결제 대행사(중복 승인 방지)도 있다. 시스템은 그 자리에 없는 이해관계자의 이익까지 지켜야 한다. “이해관계자와 이해” 칸을 채우다 보면 로그, 검증, 감사 같은 요구가 저절로 튀어나온다.

목표 수준

같은 “주문” 이라도 크기가 다르다. Cockburn 은 목표의 높이를 세 층으로 나누고 그림 기호를 붙였다.

요약 수준(summary)     구름/연  ── "매장 운영하기", "한 달 장사 정산하기"
                                    여러 사용자 목표를 묶는다
사용자 목표(user goal)  해수면  ── "음료 주문하기", "환불 받기"
                                    한 사람이 한 자리에서 끝내고 만족하는 단위
하위 기능(subfunction)  물고기/조개 ── "회원 인증하기", "주소 검색하기"
                                    그 자체로는 목표가 아니다

대부분의 유스케이스는 해수면에 있어야 한다. 판별 질문은 단순하다. “주 행위자가 이걸 마치고 나면 만족해서 자리를 떠날 수 있는가?” 로그인을 마치고 만족해서 떠나는 사람은 없다. 그러니 로그인은 하위 기능이다.

범위(scope)

설계 대상이 무엇인지도 밝힌다. 회사 전체(조직)인지, 우리가 만드는 시스템인지, 그 안의 한 컴포넌트인지. 그리고 시스템을 블랙박스로 볼지(내부 구조 언급 없음, 요구사항 단계의 기본), 화이트박스로 볼지(내부 구성 요소 등장, 설계 단계)를 정한다.

완전한 형식(fully dressed) 템플릿

칸 내용
이름 주 행위자의 목표를 동사구로 (“음료를 주문한다”)
범위 / 수준 설계 대상, 목표 수준
주 행위자 목표를 가진 쪽
이해관계자와 이해 각자가 지키고 싶은 것
선행 조건 시작 시 시스템이 이미 확인해 둔 사실
최소 보장 실패하더라도 지키는 것
성공 보장 성공 시 참이 되는 것
트리거 유스케이스를 시작하는 사건
주 성공 시나리오 번호 붙인 3~9단계 정도의 성공 경로
확장 각 단계에서 갈라지는 조건과 처리 (3a, 3b …)
기술·데이터 변형 방식은 다르지만 흐름은 같은 경우 (카드/간편결제)

간단한 프로젝트에는 한 문단짜리 약식(casual) 형식도 허용된다. 형식의 무게는 프로젝트의 위험에 맞춘다.

좋은 단계 문장

나쁜 단계 좋은 단계 이유
고객이 메뉴 화면에서 ‘담기’ 버튼을 클릭한다 고객이 음료와 옵션을 고른다 UI 세부를 빼고 의도를 쓴다
시스템이 재고가 있는지 확인한다. 있으면 다음으로 간다 시스템이 재고를 확인한다 조건 분기는 확장으로 보낸다
데이터가 저장된다 시스템이 주문을 기록한다 누가 하는지(주어)를 분명히
고객과 시스템이 결제를 처리한다 고객이 결제 수단을 고른다 / 시스템이 승인을 요청한다 한 단계에 한 행위자

예제

유스케이스 UC-07: 음료를 주문한다
범위: 카페 주문 앱(블랙박스)       수준: 사용자 목표
주 행위자: 고객
이해관계자와 이해:
  - 고객: 원하는 음료를 정확한 가격에, 기다리는 시간을 알고 받고 싶다
  - 매장: 만들 수 없는 주문은 받지 않고 싶다. 결제된 주문만 제조하고 싶다
  - 회계: 모든 결제가 영수증 번호와 함께 기록되길 원한다
선행 조건: 고객이 매장을 선택했다
최소 보장: 결제가 승인됐는데 주문이 누락되는 일은 없다
성공 보장: 주문이 매장 대기열에 들어가고, 고객은 예상 대기 시간을 안다
트리거: 고객이 주문을 시작한다

주 성공 시나리오
1. 고객이 음료와 옵션을 고른다.
2. 시스템이 재고와 옵션 조합을 확인하고 금액을 보여 준다.
3. 고객이 결제 수단을 고른다.
4. 시스템이 결제 대행사에 승인을 요청하고 승인을 받는다.
5. 시스템이 주문을 기록하고 매장 대기열에 넣는다.
6. 시스템이 고객에게 주문 번호와 예상 대기 시간을 알려 준다.

확장
2a. 재료가 떨어졌다:
    2a1. 시스템이 해당 옵션을 품절로 알리고 대체 옵션을 보여 준다. 1단계로.
3a. 고객이 적립 포인트로 일부를 결제한다:
    3a1. 시스템이 차감 후 잔액을 보여 준다. 3단계로.
4a. 승인이 거절됐다:
    4a1. 시스템이 거절 사유를 보여 준다. 3단계로.
4b. 승인 응답이 시간 안에 오지 않는다:
    4b1. 시스템이 결제 상태를 조회한다.
    4b2. 승인된 것으로 확인되면 5단계로. 아니면 결제를 취소하고 실패를 알린다.
5a. 매장이 마감 중이다:
    5a1. 시스템이 결제를 취소하고 고객에게 알린다. 유스케이스 실패.
*a. 고객이 언제든 주문을 취소한다:
    *a1. 결제 전이면 종료. 결제 후면 '환불 받기'(UC-09)를 포함한다.

확장을 찾는 방법은 기계적이다. 주 성공 시나리오의 각 단계마다 “여기서 무엇이 잘못될 수 있나?” 를 묻는다. 4b 처럼 “응답이 오지 않는다” 는 개발자가 코드를 짜다 혼자 정하면 최소 보장(승인됐는데 주문 누락 없음)을 깨기 쉬운 지점이다. 이 확장이 문서에 있으면 테스트도 그대로 나온다.

유스케이스와 스토리를 함께 쓰기

Martin Fowler 는 Use Cases And Stories 에서 둘이 모두 요구를 조직하는 방법이지만 목적이 다르다고 정리한다. 유스케이스는 사용자가 시스템과 어떻게 관계 맺는지 이야기로 묶고, 스토리는 계획을 위해 요구를 쪼갠다. 그래서 하나의 스토리는 유스케이스의 시나리오 하나일 수도, 단계 하나일 수도 있다.

실무에서는 이렇게 섞는다.

UC-07 음료를 주문한다
 ├─ 스토리 A: 주 성공 시나리오(카드 결제) ── 첫 스프린트
 ├─ 스토리 B: 확장 2a 품절 대체 옵션
 ├─ 스토리 C: 확장 4b 승인 타임아웃 복구   ── 위험이 크므로 일찍
 └─ 스토리 D: 확장 3a 포인트 결제          ── 나중에

Jacobson 등이 제안한 Use-Case 2.0(CACM, 2016)은 이렇게 유스케이스를 잘라 낸 조각을 유스케이스 슬라이스라 부르며 같은 발상을 정식화했다. 스토리 크기 기준은 SE100 #014 에서 다룬다.

흔한 오해와 함정

  • 다이어그램이 유스케이스다. 다이어그램은 목차다. 요구의 대부분은 본문, 특히 확장에 있다.
  • “CRUD 유스케이스” — “회원 생성/조회/수정/삭제” 를 각각 유스케이스로 만들면 사용자 목표가 사라진다. 목표는 “주소를 바꾼다” 이지 “회원 정보 UPDATE” 가 아니다.
  • 화면 흐름을 쓴다. 버튼과 화면 이름이 들어가면 UI 를 바꿀 때마다 요구가 흔들린다. 의도를 쓰고, 화면은 별도 설계 산출물로 둔다.
  • 하위 기능 수준이 넘친다. “비밀번호를 검증한다” 같은 물고기 수준 유스케이스가 수십 개면 숲이 안 보인다. 해수면을 중심으로 두고 하위 기능은 필요할 때만 뽑아낸다.
  • 선행 조건에 ‘사용자가 원한다’ 를 쓴다. 선행 조건은 시스템이 이미 확인한 사실이다. 사용자의 의도는 트리거다.

확인 문제

  1. 주 행위자와 이해관계자를 구분해야 하는 이유는?
  2. “로그인한다” 가 보통 사용자 목표 수준이 아닌 이유를 Cockburn 의 판별 질문으로 설명하라.
  3. 최소 보장과 성공 보장의 차이를 예제 UC-07 로 설명하라.
  4. 확장을 빠짐없이 찾는 기계적인 방법은?
  5. 유스케이스 하나를 여러 사용자 스토리로 나눌 때 어떤 단위로 자를 수 있는가?

풀이

  1. 시스템은 그 자리에 없는 이해관계자(매장, 회계, 결제사)의 이익도 지켜야 한다. 주 행위자만 보면 기록·검증·감사 같은 요구가 빠진다.
  2. 로그인을 마쳤다고 만족해서 떠나는 사람은 없다. 다른 목표를 이루기 위한 단계일 뿐이므로 하위 기능이다.
  3. 최소 보장은 실패해도 지키는 것(승인됐는데 주문이 누락되지 않음), 성공 보장은 성공했을 때 참이 되는 것(주문이 대기열에 있고 고객이 대기 시간을 앎)이다.
  4. 주 성공 시나리오의 각 단계마다 “여기서 무엇이 잘못될 수 있나” 를 묻고, 각 조건을 단계번호+문자 확장으로 적는다. 어느 단계에서나 일어나는 것은 *a 로 둔다.
  5. 주 성공 시나리오 하나, 확장 하나, 기술·데이터 변형 하나(결제 수단별) 단위로 자를 수 있다. 위험이 큰 확장을 먼저 고른다.

더 읽을거리 (References)