본문으로 건너뛰기
입문약 22분

수용 기준(Acceptance Criteria)과 요구사항의 관계

요구사항이 무엇을 만들지를 말한다면, 수용 기준은 언제 완료로 인정할지를 말한다. Given-When-Then을 잘못 쓴 예와 고친 예로 배우고, 세 역할이 함께 AC를 만드는 과정을 따라간다.

  • #수용기준
  • #AcceptanceCriteria
  • #GivenWhenThen
  • #QA기초

개념

도착했다는 것을 누가 판정하는가

여행 계획을 세운다고 해보자. "부산에 간다"는 목적지다. 그런데 어디까지 가야 도착인가? 부산 시계를 넘으면 도착인가, 부산역 개찰구를 나와야 도착인가, 숙소에 체크인해야 도착인가. 셋 다 "부산에 갔다"는 말은 성립하지만, 판정 결과는 완전히 달라진다.

소프트웨어에서 이 차이가 그대로 재현되는 순간이 있다. 개발자는 "다 됐어요"라고 하고, 기획자는 "이건 아닌데요"라고 하고, QA는 "그럼 저는 뭘 확인해야 하나요"라고 묻는 그 회의다. 세 사람 모두 거짓말을 하고 있지 않다. 도착 판정 기준을 아무도 미리 정해두지 않았을 뿐이다.

수용 기준(Acceptance Criteria, AC) 은 바로 그 도착 판정 기준이다. 요구사항이 "어디로 갈지"를 말한다면, AC는 "도착했는지 어떻게 알지"를 말한다.

요구사항과 수용 기준의 관계

요구사항은 "무엇이 필요한가"를 넓게 말한다. AC는 그 요구사항이 "언제 완료로 인정되는가"를 구체적인 통과/실패 조건으로 쪼갠 것이다. 레슨 2에서 배운 테스트 가능성을 실제로 문서 형태로 만든 결과물이 AC라고 볼 수 있다.

요구사항: 사용자는 이메일과 비밀번호로 회원가입할 수 있다.

수용 기준:

  • 유효한 이메일 형식과 8자 이상 비밀번호를 입력하면 가입이 완료된다
  • 이미 가입된 이메일이면 "이미 가입된 이메일입니다" 메시지를 보여준다
  • 비밀번호가 8자 미만이면 가입 버튼이 비활성화된다
  • 가입 완료 시 인증 메일이 발송된다

하나의 요구사항에서 여러 개의 AC가 나온다. AC 하나하나가 "이 조건이 충족됐는가?"를 명확히 판단할 수 있는 문장이어야 한다 — 그래서 레슨 2의 테스트 가능성 기준을 그대로 만족해야 한다.

둘의 관계를 표로 정리하면 이렇다.

요구사항수용 기준(AC)
답하는 질문무엇을 만드는가무엇이 되면 끝인가
관점목적·가치관찰 가능한 결과
개수하나보통 3~10개
주 독자팀 전체, 이해관계자개발자, QA, 리뷰어
바뀌는 빈도드물게논의하면서 자주 다듬어짐
없으면 생기는 일방향을 잃는다완료 여부로 싸운다

마지막 줄이 이 레슨의 핵심이다. 요구사항이 없으면 무엇을 만들지 모르지만, AC가 없으면 다 만들고 나서 싸운다.

좋은 AC가 갖춰야 할 다섯 가지

AC를 쓸 때 매번 떠올릴 기준이다. 앞 레슨들에서 배운 것들이 여기 모인다.

  1. 관찰 가능한가 — 겉으로 확인할 수 있는 결과인가. "잘 처리된다"는 관찰할 수 없고 "주문 상태가 결제완료로 바뀐다"는 관찰할 수 있다.
  2. 통과/실패가 둘로 갈리는가 — "빠르게 응답한다"가 아니라 "2초 이내에 응답한다". 판정하는 사람이 달라도 같은 답이 나와야 한다.
  3. 구현 방식이 아니라 동작을 말하는가 — "Redis에 세션을 저장한다"는 구현 지시이지 수용 기준이 아니다. AC는 밖에서 보이는 것을 쓴다.
  4. 하나의 시나리오만 다루는가 — 한 AC에 조건 두 개가 섞이면 절반만 맞았을 때 통과인지 실패인지 아무도 모른다.
  5. 비즈니스 언어로 쓰여 있는가 — 기획자가 읽고 "그래, 그 뜻이야"라고 할 수 있어야 한다. 그래야 합의의 근거가 된다.

Given-When-Then 형식

AC를 쓸 때 자주 쓰는 형식이 Given-When-Then이다. "어떤 상황에서(Given), 무엇을 하면(When), 어떻게 되어야 한다(Then)"를 구조화한다.

Given 사용자가 회원가입 페이지에 있고
When  유효한 이메일과 8자 이상 비밀번호를 입력하고 가입 버튼을 누르면
Then  계정이 생성되고 인증 메일이 발송된다
Given 사용자가 회원가입 페이지에 있고
When  이미 가입된 이메일을 입력하면
Then  "이미 가입된 이메일입니다" 메시지가 표시되고 가입은 진행되지 않는다

세 부분이 각각 맡은 일이 다르다. 헷갈릴 때 이 표로 돌아오면 된다.

부분무엇을 쓰는가자주 틀리는 지점
Given행동 이전에 이미 참인 상태사용자의 행동을 여기 쓴다
When판정을 촉발하는 행동 하나검증 조건이나 결과를 섞어 쓴다
Then관찰 가능한 결과모호하게 쓰거나, 성공만 쓴다

이 형식이 좋은 이유는 하나의 AC가 정확히 하나의 시나리오만 다루도록 강제하기 때문이다. "그리고(and)"로 여러 조건을 욱여넣고 싶어지는 유혹을 구조 자체가 막아준다. 이 형식은 모듈 7에서 다룰 BDD(Behavior-Driven Development)와 Cucumber 같은 도구에서 실행 가능한 테스트로 그대로 이어진다 — 지금 잘 써두면 나중에 자동화까지 재사용할 수 있다.

잘못 쓴 AC를 고쳐보기

좋은 예만 보면 "이 정도야 나도 쓰겠는데"라고 생각하게 된다. 그런데 막상 쓰면 거의 항상 아래 셋 중 하나에 걸린다. 실제로 현장에서 올라오는 모습 그대로 보고, 고치는 과정을 따라가 보자.

실수 1 — 여러 시나리오를 하나에 욱여넣기

Given 사용자가 로그인 페이지에 있고
When  이메일과 비밀번호를 입력하면
Then  맞으면 메인 화면으로 이동하고, 틀리면 에러 메시지를 보여주고,
      5회 틀리면 계정이 잠긴다

Then에 결과가 세 개 들어 있다. 이러면 무슨 일이 벌어지는가.

  • 개발자가 두 개만 구현하고 "완료"라고 올려도 형식상 틀린 말이 아니다.
  • QA가 "AC 1번 실패"라고 리포트하면 어느 부분이 실패인지 다시 물어야 한다.
  • 나중에 계정 잠금 정책만 바뀌어도 이 AC 전체를 다시 써야 한다.

고친 것 — 시나리오 수만큼 AC를 나눈다.

[AC-1]
Given 가입된 계정이 있고
When  올바른 이메일과 비밀번호로 로그인하면
Then  메인 화면으로 이동한다
 
[AC-2]
Given 가입된 계정이 있고
When  비밀번호를 틀리게 입력하면
Then  "이메일 또는 비밀번호가 올바르지 않습니다" 메시지가 표시된다
 
[AC-3]
Given 같은 계정으로 비밀번호를 연속 4회 틀린 상태이고
When  5회째 틀리면
Then  계정이 잠기고 "계정이 잠겼습니다" 안내가 표시된다

AC 개수가 늘어난 것이 손해처럼 보이지만, 판정이 셋으로 나뉜 것이 이득이다. 이제 "AC-3만 미완"이라고 말할 수 있다.

AC-3의 Given도 눈여겨보자. "연속 4회 틀린 상태"라는 사전 상태를 명시해서, 5회째라는 경계를 정확히 짚었다. 이 경계값 감각은 모듈 3에서 기법으로 배운다.

실수 2 — When에 검증 조건이 섞이기

Given 사용자가 장바구니에 있고
When  수량을 재고보다 많이 입력하면
Then  수량이 변경되지 않는다

언뜻 멀쩡해 보이지만 문제가 있다. "재고보다 많이"는 시스템이 판정하는 조건이지 사용자의 행동이 아니다. When은 행동을 쓰는 자리다. 판정 조건이 When에 들어가면 두 가지가 흐려진다.

  • 재고가 몇 개인지 안 적혀 있어서 재현이 불가능하다.
  • "많이 입력하면"의 경계가 안 보인다. 재고와 같은 수는 되는가, 안 되는가.

고친 것 — 상태는 Given으로, 행동은 When으로, 구체적인 수치로.

Given 상품 A의 재고가 5개이고 장바구니에 1개 담겨 있을 때
When  수량을 6으로 변경하면
Then  수량은 5로 유지되고 "재고가 5개 남았습니다" 안내가 표시된다

숫자가 들어가자 재현 절차가 저절로 생겼다. Given에 상태를, When에 행동 하나를 — 이 배치만 지켜도 AC의 절반은 좋아진다.

실수 3 — Then이 모호하기

Given 사용자가 결제 페이지에 있고
When  결제에 실패하면
Then  적절히 처리된다

"적절히", "정상적으로", "문제없이", "잘" — 이 단어들이 Then에 보이면 그 AC는 아직 아무것도 정하지 않은 것이다. 레슨 2에서 다룬 테스트 불가능한 표현이 AC로 옮겨온 모습이다.

Then을 다듬을 때는 세 곳을 각각 묻는 게 요령이다.

물을 것예시 답
화면에는 무엇이 보이나결제 실패 안내와 다시 시도 버튼
데이터는 어떻게 되나주문 상태가 결제대기로 유지되고 재고는 차감되지 않는다
다음에 무엇을 할 수 있나같은 주문으로 결제를 다시 시도할 수 있다

고친 것

Given 사용자가 결제 페이지에서 카드 정보를 입력했고
When  결제사에서 승인 거절 응답이 오면
Then  "결제가 거절되었습니다" 안내와 다시 시도 버튼이 표시되고,
      주문 상태는 결제대기로 유지되며 재고는 차감되지 않는다

Then이 길어졌다고 실수 1과 헷갈리면 안 된다. 여기서는 시나리오가 하나다 — 결제 거절이라는 한 사건의 결과를 화면·데이터·다음 행동으로 나눠 적었을 뿐이다. 시나리오가 늘어나면 AC를 쪼개고, 한 시나리오의 결과가 여럿이면 Then 안에 적는다.

세 실수를 한눈에

증상신호가 되는 표현고치는 법
시나리오 뭉침Then에 "맞으면 ~, 틀리면 ~"시나리오 수만큼 AC를 나눈다
When에 조건 혼입"~보다 많이", "잘못된", "유효하지 않은"조건은 Given에 수치로, When은 행동 하나
Then 모호"적절히", "정상적으로", "잘"화면·데이터·다음 행동 셋으로 나눠 쓴다
Given 누락Given이 아예 없거나 "사용자가 있고"이 시나리오가 성립하려면 무엇이 참이어야 하는지
구현 지시"API를 호출해서", "DB에 저장해서"밖에서 보이는 결과로 바꿔 쓴다

성공만 쓰고 실패를 빠뜨리는 문제

AC를 처음 쓰면 거의 예외 없이 성공 경로만 나온다. "제대로 입력하면 제대로 된다"는 문장들이다. 그런데 실무에서 결함이 나오는 곳은 대부분 그 반대편이다.

이유는 단순하다. AC는 보통 기획 의도에서 출발하는데, 기획 의도는 "사용자가 이걸 해서 이런 가치를 얻는다"이지 "사용자가 실수하면 어떻게 된다"가 아니기 때문이다. 부정 케이스는 아무도 원해서 쓰지 않는다. 습관으로만 쓰인다.

습관을 만드는 방법은 AC 목록을 다 쓴 뒤 다음 네 줄을 기계적으로 훑는 것이다.

질문나오는 AC의 예
입력이 비어 있거나 형식이 틀리면?이메일 형식이 아니면 가입 버튼이 비활성화된다
권한이 없는 사람이 시도하면?로그아웃 상태에서 주문 상세 URL로 접근하면 로그인 화면으로 보낸다
외부 시스템이 실패하거나 느리면?인증 메일 발송이 실패해도 계정 생성은 유지되고 재발송 버튼이 보인다
같은 동작을 두 번 하면?가입 버튼을 연속 두 번 눌러도 계정은 하나만 생성된다

마지막 줄은 특히 자주 빠진다. 더블 클릭, 새로고침, 뒤로 가기 후 재제출 — 전부 "같은 동작을 두 번"이다. 결제·주문·포인트처럼 돈이 걸린 기능에서는 이 AC가 없으면 중복 처리 사고로 이어진다.

한 가지 균형은 잡아야 한다. 부정 케이스를 무한히 늘리라는 뜻이 아니다. 레슨 3에서 배운 누락 체크리스트로 후보를 뽑고, 그중 비즈니스에 영향이 큰 것만 AC로 승격시킨다. 나머지는 테스트 케이스 수준에서 다루면 된다.

AC와 테스트 케이스는 다르다

AC는 "무엇을 확인해야 완료인가"의 경계를 정의한다. 테스트 케이스는 그 AC를 검증하기 위한 구체적인 실행 절차다. AC 하나에서 여러 테스트 케이스가 나올 수 있다.

수용 기준(AC)테스트 케이스
목적완료 판정 합의결함 발견
쓰는 시점개발 전개발 전후
주 저자기획·개발·QA 함께QA
상세도조건과 기대 결과사전조건·데이터·단계·기대 결과
개수 관계AC 1개 →테스트 케이스 여러 개

예를 들어 "비밀번호는 8자 이상" AC 하나에서도 경계값 분석(모듈 3에서 배운다)을 적용하면 7자, 8자, 9자를 각각 확인하는 케이스가 나오고, 여기에 공백만 8자·이모지 포함·붙여넣기 같은 케이스가 더 붙는다. AC는 그중 어느 것도 명시하지 않았지만 전부 그 AC를 검증한다.

그래서 이런 판단이 가능해진다 — AC를 다 통과했다고 테스트가 끝난 것은 아니다. AC는 최소 기준이지 충분 조건이 아니다. 이 감각이 없으면 "AC 전부 OK"라는 말을 곧 "품질 OK"로 읽는 실수를 하게 된다.

AC와 Definition of Done은 다르다

실무에서 가장 자주 섞이는 두 개념이다. 구분은 간단하다. AC는 기능마다 다르고, DoD는 모든 기능에 똑같이 적용된다.

수용 기준(AC)Definition of Done(DoD)
적용 범위이 기능 하나팀의 모든 작업
내용무엇이 동작해야 하는가어떤 절차를 거쳤는가
예재고를 초과하면 수량이 변경되지 않는다코드 리뷰 승인, 단위 테스트 통과, 문서 갱신, 스테이징 배포
바뀌는 주기티켓마다팀 합의로 드물게
누가 정하나기획·개발·QA팀 전체

둘 다 만족해야 진짜 완료다. AC는 전부 통과했는데 코드 리뷰를 안 받았다면 DoD 미충족이고, 리뷰도 배포도 다 했는데 AC-3이 동작하지 않으면 AC 미충족이다. 스프린트 리뷰에서 "완료"를 선언하기 전에 이 두 줄을 각각 확인하는 팀이 나중에 되돌아오는 일이 적다.

AC가 열 개, 스무 개로 늘어나면

작은 기능은 AC 3~5개로 끝나지만, 실무 티켓은 금방 열 개를 넘긴다. 그때 목록을 그냥 늘어놓으면 아무도 안 읽는다. 두 가지로 정리한다.

첫째, 카테고리로 묶는다. 순서를 고정해두면 빠진 칸이 눈에 띈다는 부수 효과가 있다.

묶음들어가는 것비어 있으면 의심할 것
정상 흐름의도한 대로 됐을 때(여기가 비면 요구사항 자체를 다시 본다)
입력 검증형식·범위·필수값빈 값과 경계값을 정말 정했는가
권한·상태비로그인, 등급, 이전 상태로그아웃 상태 접근을 안 정했을 확률이 높다
예외·실패외부 연동 실패, 타임아웃, 중복 요청대부분 여기가 비어 있다
비기능응답 시간, 동시 사용자, 접근성성능 기준이 숫자로 있는가
데이터·이력저장·집계·로그·알림로그가 남아야 CS 대응이 된다

둘째, 우선순위를 붙인다. 전부 같은 무게일 수 없다.

  • Must — 하나라도 실패하면 릴리즈하지 않는다.
  • Should — 실패하면 알려진 이슈로 등록하고 다음 스프린트에 처리한다.
  • Could — 여유가 있으면 이번에, 아니면 백로그로.

이 표시는 릴리즈 직전에 진가를 발휘한다. 마감 전날 AC 두 개가 미완일 때, 그것이 Must인지 Could인지가 릴리즈 여부를 가르는 유일한 근거가 된다. 표시가 없으면 그 자리에서 목소리 큰 사람이 결정하게 된다.

마지막으로 신호 하나. AC가 스무 개를 넘어가면 대개 AC 문제가 아니라 요구사항 문제다. 티켓 하나가 너무 큰 것이다. "사용자는 주문을 관리할 수 있다" 같은 요구사항은 조회·취소·교환·환불로 쪼개야 각각의 AC가 다시 읽을 만한 크기가 된다.

누가 쓰는가 — three amigos

이상적으로는 기획자·개발자·QA 세 역할이 함께 AC를 만든다. 이걸 three amigos 라고 부른다. QA만 혼자 쓰면 구현 제약을 놓치고, 기획자만 쓰면 테스트 가능성이 떨어지고, 개발자만 쓰면 이미 짜기로 마음먹은 구조에 기준이 끌려간다.

세 사람이 서로 다른 것을 본다는 게 핵심이다.

역할주로 던지는 질문발견하는 것
기획이게 사용자에게 무슨 가치인가비즈니스 규칙, 예외 정책, 우선순위
개발이걸 만들려면 무엇이 필요한가구현 제약, 데이터 한계, 성능 위험
QA이게 틀어지는 경우는 언제인가예외 케이스, 경계값, 상태 조합

three amigos 세션 엿보기

말로만 들으면 감이 안 오니 30분짜리 세션을 짧게 따라가 보자. 요구사항은 한 줄이다.

"회원은 주문한 상품을 배송 전까지 취소할 수 있다."

기획: 마이페이지 주문 상세에 취소 버튼을 넣고, 누르면 취소되고 환불이 시작되는 흐름이에요.

QA: 배송 전까지라고 하셨는데, 주문 상태가 몇 개인가요? 어느 상태까지가 취소 가능인지 정해야 할 것 같아요.

개발: 상태는 결제대기, 결제완료, 상품준비중, 배송중, 배송완료 다섯 개예요. 상품준비중은 이미 창고에 넘어간 뒤라 시스템만으로는 못 막습니다.

기획: 그럼 결제완료까지는 즉시 취소, 상품준비중은 취소 요청으로 받고 CS가 승인하는 걸로 할게요.

QA: 상태가 바뀌는 순간에 걸치면요? 취소 버튼을 누르는 사이에 상품준비중으로 넘어가면 어느 쪽으로 처리되나요?

개발: 그건 서버에서 다시 확인해야 해요. 버튼이 보인다고 취소가 되는 게 아니라, 요청 시점 상태로 판정하는 게 맞습니다.

기획: 그 경우엔 "이미 상품 준비가 시작되어 취소 요청으로 접수되었습니다"로 안내할게요.

QA: 하나 더요. 부분 취소는 되나요? 세 개 시킨 것 중 하나만요.

기획: 이번 범위는 전체 취소만요. 부분 취소는 다음 스프린트로 빼겠습니다.

개발: 그럼 취소 시 재고는 바로 복구할까요? 환불 완료 후일까요?

기획: 재고는 바로 복구해주세요. 환불은 카드사 쪽이라 3~5일 걸리는 걸 안내하고요.

30분 만에 나온 결과를 정리하면 이렇다.

누가무엇을 끌어냈나없었다면
QA상태별 취소 가능 범위개발자가 임의로 정하고 나중에 재작업
개발상품준비중은 시스템만으로 못 막음릴리즈 후 창고와 충돌
QA상태가 바뀌는 순간의 경합운 나쁜 타이밍에만 나는 재현 어려운 버그
개발재고 복구 시점재고가 새거나 이중으로 잡히는 사고
기획부분 취소는 범위 밖개발 막바지에 범위가 부풀어 일정 붕괴

이 대화에서 QA가 한 일을 다시 보면 답을 준 게 아니라 질문을 던졌다. "상태가 몇 개인가요", "그 사이에 걸치면요", "부분 취소는요" 세 마디다. 레슨 3의 "만약 ~라면?" 질문법이 그대로 쓰였고, 레슨 6에서 배울 리뷰 회의 질문 설계와도 이어진다.

세션이 끝나면 나온 합의를 곧바로 AC로 옮긴다. 기억에 남겨두면 반드시 사라진다.

[AC-1 / Must]
Given 주문 상태가 결제완료이고
When  주문 상세에서 취소 버튼을 누르면
Then  주문 상태가 취소로 바뀌고 재고가 즉시 복구되며
      환불 예상 소요(3~5영업일) 안내가 표시된다
 
[AC-2 / Must]
Given 주문 상태가 상품준비중이고
When  주문 상세에서 취소 버튼을 누르면
Then  취소 요청 상태로 접수되고 "상품 준비가 시작되어 취소 요청으로
      접수되었습니다" 안내가 표시된다
 
[AC-3 / Must]
Given 취소 버튼을 누르기 직전에 주문 상태가 상품준비중으로 바뀌었고
When  취소 요청이 서버에 도달하면
Then  요청 시점 상태로 판정되어 AC-2와 동일하게 처리된다
 
[AC-4 / Must]
Given 주문 상태가 배송중 또는 배송완료이고
When  주문 상세를 열면
Then  취소 버튼이 노출되지 않고 반품 안내가 대신 표시된다

AC-3이 이 세션의 수확이다. 회의 없이 혼자 썼다면 거의 확실히 빠졌을 AC이고, 실제로 재현이 가장 어려운 종류의 버그를 미리 막는다.

언제 쓰는가

AC는 개발 착수 전에 쓰는 것이 원칙이다. 개발이 끝난 뒤에 쓰면 이미 구현된 방식에 기준을 끼워 맞추게 되어 목적이 무색해진다.

현실적인 타이밍은 보통 이렇다.

시점하는 일
백로그 정리요구사항 한 줄 + AC 초안 2~3개 (대략적 크기 가늠용)
스프린트 계획 전three amigos로 AC 확정, 우선순위 표시
개발 중새로 발견된 예외를 AC에 추가 (변경 이력을 남긴다)
개발 완료 후AC를 기준으로 확인, 통과 여부 기록

세 번째 줄이 중요하다. AC는 한 번 쓰고 얼려두는 문서가 아니다. 개발 도중에 새로 드러난 조건은 AC에 반영하되, 무엇이 언제 추가됐는지는 남긴다. 그래야 다음 레슨에서 다룰 추적성이 성립하고, 일정이 밀린 이유도 설명할 수 있다.

실무에서 왜 필요한가

완료 논쟁이 사실 확인으로 바뀐다. "이 기능, 완료된 거 맞나요?"에 대한 논쟁은 실무에서 자주 일어난다. AC가 명확히 있으면 이 논쟁은 사실 확인만으로 끝난다 — "AC-3이 아직 안 됐으니 완료가 아니다"처럼. AC가 없으면 "제 생각엔 이 정도면 된 것 같은데요"식의 주관적 공방이 된다. AC는 QA·개발·기획 사이의 객관적인 합의 기준을 만든다는 점에서 실무 갈등을 줄이는 가장 실용적인 도구 중 하나다.

질문의 비용이 싸질 때 질문할 수 있다. 레슨 1에서 배운 대로 결함은 늦게 발견될수록 비싸다. AC를 쓰는 과정은 결국 개발 착수 전에 질문을 몰아서 하는 일이다. 앞의 three amigos 세션에서 나온 다섯 가지 발견을 릴리즈 후에 알았다면 각각이 장애 대응이나 재작업이 됐을 것이다.

테스트 설계를 개발과 동시에 시작할 수 있다. AC가 개발 착수 전에 있으면 QA는 코드가 나오기 전에 테스트 케이스를 설계할 수 있다. 빌드가 넘어온 뒤에야 "뭘 테스트하지"를 고민하는 것과 비교하면, 같은 마감에서 확보되는 실제 테스트 시간이 완전히 달라진다.

회귀 테스트의 씨앗이 된다. AC는 그 기능이 지켜야 할 최소 약속이다. 이번 스프린트가 끝나도 그 약속은 유효하므로, AC 목록은 그대로 회귀 스위트의 후보 목록이 된다. 특히 부정 케이스 AC는 나중에 다른 기능이 바뀌었을 때 조용히 깨지기 쉬운 부분이라 회귀 가치가 높다.

변경이 왔을 때 영향 범위가 보인다. 요구사항이 바뀌면 AC 중 어느 것이 바뀌는지 짚을 수 있고, 그 AC에 연결된 테스트 케이스가 곧 재실행 대상이 된다. 이게 다음 레슨의 추적성으로 이어지는 지점이다. AC 없이 요구사항과 테스트 케이스를 직접 연결하려 하면 연결이 너무 굵어서 "이 요구사항이 바뀌면 테스트 200건 전부 다시"밖에 못 말하게 된다.

채용시장에서의 위치

AC 작성 경험은 신입·주니어 QA 공고에서 "요구사항 리뷰 참여", "스토리 기반 테스트 설계", "애자일 환경 경험" 같은 문구로 나타난다. 실제 면접에서는 이렇게 물어본다.

질문좋은 답변의 방향
수용 기준을 써보신 적 있나요형식 설명에서 끝내지 말고 어떤 요구사항에서 몇 개를 뽑았고 그중 무엇이 회의에서 새로 나온 것인지까지
AC와 테스트 케이스의 차이는요경계 대 절차, 그리고 AC 1개에서 케이스 여러 개가 나온다는 관계까지
AC와 DoD는 어떻게 다른가요기능별 대 전사 공통. 둘 다 만족해야 완료라는 결론까지
기획서가 부실하면 어떻게 하세요불평이 아니라 AC 초안을 먼저 써서 확인받는다는 절차로 답한다
개발이 완료라는데 QA는 아니라고 볼 때는요주관 대결로 가지 않고 사전에 합의된 AC를 근거로 통과/미통과를 표시해 공유

네 번째 질문이 실전에서 가장 자주 나온다. "기획서를 제대로 써달라고 요청합니다"는 약한 답이다. "제가 이해한 대로 AC 초안을 5개 정도 써서 기획자에게 확인을 요청합니다. 틀린 곳을 지적받는 과정에서 명세가 빨라집니다"가 강한 답이다 — 남에게 일을 미루지 않고 스스로 착수하는 방법을 말했기 때문이다.

실습 과제

과제 1 — 잘못 쓴 AC 고치기 (12분)

아래 AC의 문제를 찾아내고 Given-When-Then으로 다시 쓴다.

Given 사용자가 쿠폰함에 있고
When  유효하지 않은 쿠폰을 적용하려고 하면
Then  적절한 처리가 된다
해설 보기

문제가 세 군데다.

  • When에 판정 조건이 섞였다. "유효하지 않은"은 시스템이 판정하는 것이지 사용자의 행동이 아니다. 그리고 유효하지 않은 이유가 만료·사용됨· 최소 주문금액 미달·대상 상품 아님 등 여러 가지라 시나리오가 하나가 아니다.
  • Then이 모호하다. "적절한 처리"는 아무것도 정하지 않은 것이다.
  • Given이 비어 있다. 어떤 쿠폰이 어떤 상태인지가 없어서 재현할 수 없다.

이유별로 나누고 수치를 넣어 다시 쓴다.

[AC-1]
Given 유효기간이 어제 끝난 쿠폰을 보유하고 있고
When  장바구니에서 그 쿠폰을 적용하면
Then  "사용 기간이 만료된 쿠폰입니다" 메시지가 표시되고
      주문 금액은 변하지 않는다
 
[AC-2]
Given 최소 주문금액이 30,000원인 쿠폰을 보유하고
      장바구니 금액이 29,900원일 때
When  그 쿠폰을 적용하면
Then  "30,000원 이상 주문 시 사용할 수 있습니다" 메시지가 표시되고
      주문 금액은 변하지 않는다

AC-2의 29,900원이 우연이 아니다. 경계 바로 아래를 골라 적었다 — 이렇게 쓰면 개발자도 경계를 의식하게 된다.

과제 2 — 부정 케이스 채우기 (12분)

아래는 어떤 팀이 실제로 쓴 AC 목록이다. 전부 성공 경로만 있다. 앞에서 배운 네 가지 질문(빈 값·권한·외부 실패·중복 요청)을 적용해 AC를 최소 4개 더 추가한다.

요구사항: 회원은 배송지를 등록하고 기본 배송지로 지정할 수 있다.

  • AC-1: 주소를 입력하고 저장하면 배송지 목록에 추가된다
  • AC-2: 목록에서 기본 배송지로 지정하면 주문 시 자동 선택된다
해설 보기

예시 답이다. 표현이 달라도 네 방향을 각각 짚었으면 맞다.

  • 빈 값·형식: 우편번호를 검색하지 않고 상세주소만 입력한 상태에서 저장하면 "주소를 검색해 주세요" 안내가 표시되고 저장되지 않는다
  • 권한·상태: 로그아웃 상태에서 배송지 등록 URL로 접근하면 로그인 화면으로 이동하고, 로그인 후 원래 화면으로 돌아온다
  • 외부 실패: 우편번호 검색 서비스가 응답하지 않으면 "주소 검색을 잠시 후 다시 시도해 주세요" 안내가 표시되고 입력한 내용은 유지된다
  • 중복 요청: 저장 버튼을 연속 두 번 눌러도 배송지는 하나만 등록된다
  • 상태 조합(추가 점수): 기본 배송지로 지정된 주소를 삭제하면 남은 배송지 중 하나가 기본으로 지정되거나, 기본 배송지가 없는 상태가 명시적으로 처리된다

마지막 항목은 네 질문에 없던 것이다. "이미 지정된 것을 지우면?" 같은 질문은 상태를 다루는 기능이면 거의 항상 나온다. 여기까지 떠올렸다면 아주 좋다.

과제 3 — AC 작성하기 (15분)

다음 요구사항에 대해 Given-When-Then 형식으로 AC를 5개 이상 작성한다. 성공 경로 하나, 나머지는 검증·예외·경계로 채운다. 각 AC에 Must/Should를 표시한다.

"사용자는 장바구니에서 상품 수량을 변경할 수 있다. 단, 재고 수량을 초과할 수 없다."

해설 보기

방향을 보여주는 예시다. 수치를 넣었는지, 부정 케이스가 들어갔는지를 스스로 점검해본다.

[AC-1 / Must] 정상 흐름
Given 상품 A의 재고가 5개이고 장바구니에 2개 담겨 있을 때
When  수량을 3으로 변경하면
Then  수량이 3으로 반영되고 주문 예상 금액이 즉시 갱신된다
 
[AC-2 / Must] 경계 - 재고와 같은 수량
Given 상품 A의 재고가 5개일 때
When  수량을 5로 변경하면
Then  수량이 5로 반영된다
 
[AC-3 / Must] 경계 - 재고 초과
Given 상품 A의 재고가 5개일 때
When  수량을 6으로 변경하면
Then  수량은 5로 유지되고 "재고가 5개 남았습니다" 안내가 표시된다
 
[AC-4 / Must] 하한 경계
Given 장바구니에 상품 A가 1개 담겨 있을 때
When  수량을 0으로 변경하면
Then  "1개 이상 선택해 주세요" 안내가 표시되거나
      상품 삭제 여부를 확인받는다
 
[AC-5 / Should] 외부 상태 변화
Given 장바구니를 열어둔 사이에 상품 A의 재고가 5개에서 2개로 줄었을 때
When  수량을 4로 변경하면
Then  서버 기준 재고로 판정되어 "재고가 2개 남았습니다" 안내가 표시된다

AC-2와 AC-3이 짝을 이루는 것이 핵심이다. "초과할 수 없다"는 요구사항 한 줄에서 5와 6이라는 두 케이스가 나온다. 재고와 같은 수량이 되는지 안 되는지를 정하지 않으면 개발자마다 다르게 구현한다.

AC-4는 요구사항에 아예 없던 것이다 — 요구사항은 상한만 말했지 하한을 말하지 않았다. 레슨 3의 누락 찾기가 여기서 쓰였다.

AC-5는 화면의 값과 서버의 값이 다를 수 있다는 문제다. Should로 둔 것은 발생 빈도가 낮기 때문이지만, 품절 임박 상품에서는 실제로 자주 일어난다.

과제 4 — AC에서 테스트 케이스 도출하기 (10분)

과제 3에서 쓴 AC 중 하나를 골라, 그 AC를 검증할 구체적인 테스트 케이스를 3개 이상 적는다. 각 케이스에 사전조건·입력값·기대 결과를 포함한다.

해설 보기

AC-3(재고 초과)을 골랐다면 이런 케이스들이 나온다.

사전조건입력기대 결과
재고 5, 장바구니 2수량을 5로5로 반영 (경계 안쪽, AC-2 확인)
재고 5, 장바구니 2수량을 6으로5 유지 + 안내 노출
재고 5, 장바구니 2수량 입력란에 99 직접 타이핑5 유지 + 안내 노출
재고 5, 장바구니 2수량 증가 버튼을 빠르게 10회 클릭5에서 멈춤, 중복 요청이 나가지 않음
재고 0(품절), 장바구니 1수량 변경 시도품절 안내, 변경 불가

AC 하나에서 다섯 개가 나왔다. 그리고 3~5번째 케이스는 AC에 명시되어 있지 않다 — 입력 방식(버튼 대 직접 입력), 연속 조작, 재고 0이라는 특수 상태는 AC의 문장에는 없지만 같은 AC를 검증한다.

이게 앞에서 말한 "AC는 최소 기준이지 충분 조건이 아니다"의 실제 모습이다.

과제 5 — 역할 바꿔 앉기 (선택, 15분)

지금 회사(또는 학습 프로젝트)에서 진행 중인 기능 하나를 골라, 혼자서 three amigos를 흉내 내본다. 종이를 세 칸으로 나누고 각 칸에 기획·개발·QA 관점의 질문을 최소 세 개씩 적는다.

  • 기획 칸: 이 기능이 없으면 사용자가 무엇을 못 하나, 예외 정책은 누가 정하나
  • 개발 칸: 이 데이터는 어디서 오나, 실패할 수 있는 외부 호출은 무엇인가
  • QA 칸: 상태가 바뀌는 순간은 언제인가, 두 번 하면 어떻게 되나

다 적은 뒤, 그중 아무도 답을 모르는 질문에 표시한다. 그게 다음 리뷰 회의에 들고 갈 목록이다. 질문을 우선순위대로 정리하는 법은 레슨 6에서 이어서 다룬다.

자가 체크리스트

  • 요구사항과 수용 기준의 관계를 "넓은 것 대 구체적인 통과 조건"으로 설명할 수 있다
  • Given에 상태를, When에 행동 하나를, Then에 관찰 가능한 결과를 배치할 수 있다
  • 여러 시나리오가 한 AC에 뭉쳐 있는 것을 알아보고 나눌 수 있다
  • When에 판정 조건이 섞인 AC를 Given으로 옮겨 고칠 수 있다
  • "적절히", "정상적으로" 같은 모호한 Then을 화면·데이터·다음 행동으로 나눠 다시 쓸 수 있다
  • 성공 경로만 쓴 AC 목록에 부정 케이스 네 방향(빈 값·권한·외부 실패·중복)을 적용할 수 있다
  • AC가 많아졌을 때 카테고리와 Must/Should로 정리할 수 있다
  • AC와 테스트 케이스의 차이를 설명하고, AC 1개에서 케이스 여러 개를 뽑을 수 있다
  • AC와 Definition of Done의 차이를 예를 들어 설명할 수 있다
  • three amigos에서 세 역할이 각각 무엇을 발견하는지 말할 수 있다

흔한 실수

  • AC 하나에 여러 시나리오를 욱여넣는다. "맞으면 A, 틀리면 B" 식으로 결과를 여러 개 섞으면 통과/실패 판단이 애매해진다. 시나리오마다 AC를 나눈다.
  • When에 검증 조건을 쓴다. "유효하지 않은 값을 입력하면"은 행동이 아니라 판정이다. 상태는 Given에 수치로 넣고 When에는 행동 하나만 남긴다.
  • Then을 "정상적으로 처리된다"로 끝낸다. 레슨 2의 테스트 불가능한 표현이 AC로 옮겨온 것이다. 화면·데이터·다음 행동 셋으로 나눠 쓴다.
  • 성공 경로만 쓴다. 결함은 대부분 반대편에서 나온다. 목록을 다 쓴 뒤 빈 값·권한·외부 실패·중복 요청 네 줄을 기계적으로 훑는 습관을 만든다.
  • AC에 구현 방식을 지시한다. "이 API를 호출해서"는 설계이지 수용 기준이 아니다. AC는 밖에서 보이는 동작만 말하고, 어떻게 만들지는 개발자에게 남긴다.
  • AC를 테스트 케이스와 똑같이 취급한다. AC는 경계, 테스트 케이스는 절차다. "AC 전부 OK"를 "테스트 끝"으로 읽으면 안 된다.
  • AC와 DoD를 섞는다. "코드 리뷰 완료"는 모든 티켓에 공통이므로 DoD이지 이 기능의 AC가 아니다. 기능별 AC 목록에 팀 공통 절차가 섞이면 티켓마다 같은 줄을 복사하게 되고, 정작 기능 고유의 조건이 묻힌다.
  • AC를 QA 혼자 사후에 작성한다. 개발이 끝난 뒤에 쓰면 이미 구현된 방식에 AC를 끼워 맞추게 되어 원래 목적(사전에 기준을 합의하는 것)이 무색해진다.
  • AC 개수가 폭발하는데 그냥 늘어놓는다. 스무 개를 넘으면 대개 티켓이 너무 크다는 신호다. 카테고리로 묶고, 그래도 많으면 요구사항 자체를 쪼갠다.
  • 한 번 쓴 AC를 다시 안 본다. 개발 중에 새 예외가 드러나면 AC에 반영하고 변경 이력을 남긴다. 그래야 다음 레슨의 추적성이 성립한다.

참고 자료

낯선 말 풀이

이 레슨에 나온 약어입니다. 본문에서도 처음 나올 때 점선으로 표시해 두었습니다 (제목과 링크 글자는 그대로 둡니다).

QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
AC — 수용 기준
"이 조건들을 만족하면 다 된 것으로 친다" 를 미리 글로 못 박아 둔 목록.
BDD — 행위 주도 개발
"어떤 상황에서 무엇을 하면 무엇이 된다"는 문장으로 요구사항을 적고, 그 문장을 그대로 시험으로 돌리는 방식.
API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
URL — 인터넷 주소
웹에서 무언가의 위치를 가리키는 주소 한 줄.
DoD — 완료의 정의
모든 작업에 똑같이 적용되는 "여기까지 해야 끝" 목록. 코드 검토·문서 갱신 같은 것들이다.
CS — 고객 지원 · 칩 선택 신호
이 커리큘럼에서 두 가지로 쓰인다. ① 고객 문의와 불만을 직접 받는 조직 ② 여러 부품이 한 선을 나눠 쓸 때 "지금은 네 차례" 라고 하나를 고르는 신호. 앞뒤에 문의·고객이 있으면 ①, 통신·배선 이야기면 ②다.

용어집 전체 보기