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

모호함과 누락 찾아내기

하나의 문장이 여러 방식으로 해석될 수 있는 이유를 유형별로 정리하고, 요구사항에서 흔히 빠지는 조건을 체크리스트로 찾아낸다.

  • #모호함
  • #요구사항누락
  • #QA기초

개념

도장을 찍기 전에 계약서를 읽는 사람

부동산 계약서에 이렇게 쓰여 있다고 하자.

"잔금은 이사 전에 지급한다."

문제없어 보인다. 그런데 여기서 '이사'는 파는 사람이 짐을 빼는 날인가, 사는 사람이 짐을 들이는 날인가? 두 날짜가 사흘 차이라면 잔금 날짜도 사흘 달라진다. 계약서에 도장을 찍기 전이라면 이건 한 줄 고치면 끝나는 일이다. 이사 당일에 두 사람이 서로 다른 날짜를 기대하고 있었다는 걸 알게 되면, 그때는 돈과 감정이 함께 든다.

요구사항 문서는 팀이 함께 도장을 찍는 계약서다. 기획자·개발자·QA가 같은 문장을 읽고 각자 다른 그림을 그린 채 헤어지면, 그 차이는 몇 주 뒤 통합 단계나 릴리스 직전에 청구서로 돌아온다. 이 레슨에서 배우는 것은 그 계약서를 읽는 법, 정확히는 한 문장이 두 가지로 읽히는 지점을 찾아내는 법이다.

능동적 읽기(레슨 1)로 문서에 질문을 던지는 법을, 테스트 가능성(레슨 2)으로 "이 문장을 검증할 수 있는가"를 판단하는 법을 배웠다. 이번에는 그 두 가지를 실제로 작동시키는 렌즈 — 모호함과 누락을 유형별로 알아보는 눈을 만든다.

모호한 문장은 이상하게 읽히지 않는다

가장 먼저 받아들여야 할 사실이 있다. 모호한 문장은 읽을 때 어색하지 않다. 비문도 아니고 오타도 아니다. 오히려 매끄럽게 읽힌다.

매끄럽게 읽히는 이유는, 사람이 모호한 자리를 만나면 자기 경험으로 자동으로 메꿔버리기 때문이다. 커머스를 오래 한 개발자는 '삭제'를 자연스럽게 소프트 삭제로 읽고, 데이터 담당자는 완전 삭제로 읽는다. 둘 다 "이해했다"고 느끼기 때문에 회의에서 아무도 손을 들지 않는다.

그래서 모호함 찾기는 감각이 아니라 유형 목록을 대고 훑는 작업이어야 한다. 아래 네 가지가 실무에서 마주치는 거의 전부다.

유형 1 — 어휘적 모호함: 한 단어가 두 뜻

같은 단어를 서로 다른 뜻으로 쓰고 있는데, 단어가 같아서 아무도 눈치채지 못하는 경우다.

문제의 단어해석 A해석 B물어야 할 질문
"게시글을 삭제한다"데이터에서 완전히 지움목록에서만 숨김(복구 가능)삭제 후 복구 요청이 오면? 통계 집계에는 남는가?
"회원에게만 제공"가입 절차를 마친 사람이메일 인증까지 끝낸 사람인증 전 계정은 회원인가? 휴면 계정은?
"3영업일 이내 환불"주말만 제외주말과 공휴일 모두 제외시간대 기준은? 금요일 오후 접수 건은 언제까지?
"주문을 취소한다"결제 취소 + 주문 무효화주문만 무효, 환불은 별도 절차부분 취소는? 이미 출고된 건은?

'삭제'가 특히 자주 사고를 낸다. 개발자가 소프트 삭제로 구현했는데 QA는 완전 삭제를 기대하고 DB를 확인하면 "버그"로 보고하게 되고, 반대로 완전 삭제로 구현됐는데 CS팀은 복구가 될 거라 믿고 고객에게 안내한다. 셋 다 같은 한 단어를 읽었다.

요령이 하나 있다. 업무 용어(도메인 용어)일수록 위험하다. '주문', '취소', '회원', '정산', '노출' 같은 단어는 회사마다, 심지어 같은 회사의 팀마다 다르게 쓰인다. 팀에 들어온 지 얼마 안 됐다면 이런 단어야말로 물어볼 자격이 가장 큰 단어다.

유형 2 — 범위의 모호함: 기준이 없는 수량 표현

"많이", "빠르게", "최근", "일정 시간" 같은 표현은 사람마다 기준이 다르다. 레슨 2의 테스트 가능성과 맞닿는 유형이다 — 기준이 없으면 통과/실패를 판정할 수 없다.

표현무엇이 빠졌나확정해야 할 것
"최근 주문 내역"기간인지 개수인지최근 30일인가, 최근 10건인가
"대용량 파일은 경고"임계값정확히 몇 MB부터인가
"일정 시간 활동이 없으면 로그아웃"시간과 '활동'의 정의30분인가. 마우스 움직임도 활동인가, API 호출만 활동인가
"목록을 빠르게 불러온다"측정 기준몇 초 이내, 몇 건 기준, 어느 회선에서

여기서 한 단계 더 들어가야 한다. 숫자가 적혀 있어도 여전히 모호할 수 있다. 신입이 가장 자주 놓치는 지점이다.

  • "하루 3회 제한" — 하루의 기준이 자정인가, 첫 사용 시점부터 24시간 롤링인가? 서버 시간대인가 사용자 시간대인가? 해외 사용자는?
  • "30분 이내 결제" — 30분의 시작점이 장바구니 담은 시점인가, 결제창을 연 시점인가? 결제창에서 뒤로 갔다 다시 오면 초기화되는가?
  • "월 1회 지급" — 매월 1일 기준인가, 지급일로부터 30일인가? 2월은?

숫자를 봤다고 안심하지 말고 "이 숫자를 재기 시작하는 지점은 어디인가" 를 붙여보는 습관을 들이면 이 유형은 거의 다 잡힌다.

유형 3 — 암묵적 가정: 머릿속엔 있었지만 문장엔 없는 것

작성자에게는 너무 당연해서 굳이 쓰지 않은 전제다. 당연함은 사람마다 다르기 때문에, 이 유형이 만들어내는 구멍이 가장 크다.

요구사항숨어 있는 가정가정이 깨지면
"결제 후 배송을 시작한다"결제는 성공한다결제 승인은 났는데 주문 저장이 실패하면? 부분 취소된 주문은?
"가입하면 환영 이메일을 보낸다"이메일 발송은 성공한다발송 실패 시 가입은 성공인가? 재시도하는가?
"관리자는 주문을 취소할 수 있다"취소 가능한 상태의 주문만 온다이미 배송 완료된 주문을 취소하면? 환불은 자동인가?
"쿠폰을 적용하면 할인된다"쿠폰 금액이 주문 금액보다 작다5,000원 쿠폰을 3,000원 주문에 쓰면? 차액은 사라지는가 남는가?

이 유형을 잡아내는 가장 빠른 방법은 문장의 동사에서 '성공'만 적혀 있는지 보는 것이다. "보낸다", "저장한다", "결제한다", "발급한다" — 전부 실패할 수 있는 동작인데 요구사항에는 성공한 경우만 쓰여 있다. 성공만 적힌 동사를 발견하면 그 자리에 곧바로 질문 하나가 생긴다: "이게 실패하면 어떻게 되나요?"

유형 4 — 문장 구조 모호함: 누가 무엇을 수식하는가

한국어는 수식어가 어디까지 걸리는지 표시하는 장치가 약하다. 그래서 같은 문장이 문법적으로 둘 다 맞는 두 가지 구조로 읽힌다.

문장해석 A해석 B
"관리자와 일반 사용자 중 활성 상태인 사람에게 알림"관리자·일반 사용자 모두에게 활성 조건 적용일반 사용자에게만 활성 조건 적용
"삭제된 게시글의 댓글은 노출하지 않는다"게시글이 삭제된 경우댓글이 삭제된 경우
"신규 가입한 사용자의 추천인에게 포인트를 지급한다"신규 가입자가 기준추천인이 신규 가입자여야 함
"관리자 또는 작성자가 아니면 수정할 수 없다"둘 중 아무도 아니면 불가관리자이거나, 또는 '작성자가 아닌' 사람

마지막 줄이 특히 지독하다. 부정이 어디까지 걸리는지가 불명확해서 정반대 권한 규칙이 나올 수 있다. 권한 관련 문장에 '아니면', '없으면', '제외하고'가 들어 있으면 반드시 다시 읽는다.

한국어에서 이 유형을 만드는 장치는 대체로 네 가지다.

  • 관형절의 걸림 범위 — "~한 A의 B"에서 '~한'이 A를 꾸미는지 B를 꾸미는지
  • 접속의 범위 — "A와 B 중 C인 것"에서 C가 A에도 걸리는지
  • 부정의 범위 — "A 또는 B가 아니면"에서 부정이 어디까지인지
  • 조사 생략 — "회원 등급 변경 시 알림 발송"에서 누가 변경하고 누구에게 발송하는지가 통째로 빠져 있다

찾아내는 방법은 의외로 기계적이다. 의심되는 문장을 괄호를 넣어 두 가지로 다시 써본다. 둘 다 말이 되면 그 문장은 모호한 것이다.

원문: "삭제된 게시글의 댓글은 노출하지 않는다"

  • (A) "(삭제된 게시글)의 댓글은 노출하지 않는다"
  • (B) "삭제된 (게시글의 댓글)은 노출하지 않는다"

→ 둘 다 자연스럽다. 그러므로 모호하다. 게다가 두 해석은 테스트 케이스가 완전히 다르다 — (A)는 게시글을 지우고 댓글을 확인하는 시나리오, (B)는 댓글만 지우고 확인하는 시나리오다.

이 "두 가지로 다시 쓰기"는 질문할 때도 그대로 쓰인다. "이 문장이 모호해요" 보다 "(A)로 이해할 수도 있고 (B)로 이해할 수도 있는데 어느 쪽인가요?"가 훨씬 빠르게 답을 얻는다. 리뷰 회의에서 질문을 전달하는 방법은 레슨 6에서 따로 다룬다.

네 유형 한눈에 보기

유형신호가 되는 표현대표 질문
어휘적삭제·취소·회원·노출 같은 도메인 용어"여기서 X는 정확히 무엇을 말하나요?"
범위최근·일정·대용량·빠르게, 그리고 기준점 없는 숫자"정확히 얼마부터인가요? 어디서부터 재나요?"
암묵적 가정성공만 적힌 동사(보낸다·저장한다·결제한다)"이게 실패하면 어떻게 되나요?"
문장 구조~한 A의 B, A와 B 중, ~가 아니면, 조사 생략"(A)인가요 (B)인가요?"

같은 문장을 팀원 세 명에게 보여주면 세 가지 다른 해석이 나올 수 있다 — 이게 모호함이 실무에서 문제가 되는 방식이다. 각자 다르게 이해한 채로 개발과 테스트가 따로 진행되면, 통합 단계(모듈 1에서 배운 "통합 테스트")에서야 불일치가 드러난다.

누락 — 없는 문장을 어떻게 보는가

모호함은 있는 문장을 두 가지로 읽는 문제다. 누락은 문장 자체가 없는 문제다. 후자가 훨씬 어렵다. 없는 것은 눈에 띄지 않기 때문이다. 그래서 누락은 감으로 찾는 게 아니라 체크리스트를 대고 찾는다.

  1. 예외·실패 경로 — 정상 흐름만 적혀 있고, 실패했을 때가 없다. 네트워크 끊김, 외부 결제사 응답 지연, 저장 실패, 중간에 창을 닫음.
  2. 권한·역할 — "사용자"라고만 적혀 있다. 비회원·일반회원·관리자만이 아니라 휴면·정지·탈퇴 계정도 상태의 일종이다. 남의 것에 접근하면?
  3. 상태 전이 — 어떤 상태에서 어떤 상태로 갈 수 있고, 갈 수 없는 조합은 무엇인지가 없다. 배송 완료된 주문을 취소하면? 취소된 주문을 다시 결제하면? 탈퇴한 계정으로 재가입하면?
  4. 동시성 — 같은 자원을 여러 사용자가 동시에 건드리면 어떻게 되는지가 없다. (아래에서 따로 깊게 본다.)
  5. 비기능 조건 — "얼마나 잘"에 대한 기준이 아예 없다.

상태 전이는 표 하나로 눈에 띄게 만들 수 있다. 세로에 현재 상태, 가로에 가능한 동작을 놓고 빈칸을 채워보면, 채울 수 없는 칸이 곧 요구사항의 구멍이다.

현재 상태취소환불재주문
결제 대기가능해당 없음—
결제 완료가능전액—
배송 중??—
배송 완료??가능
취소됨불가—?

물음표가 네 개 나왔다. 이 네 개가 그대로 질문 목록이자, 나중에는 그대로 테스트 케이스가 된다. 상태 전이를 다루는 정식 기법(상태 전이 테스트)은 모듈 3에서 배운다.

비기능 조건도 다섯 갈래로 나눠 훑으면 빠뜨리기 어렵다.

갈래물어볼 것
성능몇 건일 때 몇 초 이내인가. 목록이 10,000건이면?
보안·권한URL을 직접 입력해 남의 자원에 접근하면? 로그는 남는가
접근성키보드만으로 조작 가능한가. 스크린 리더에서 읽히는가
국제화·시간대날짜 기준 시간대는? 이름·주소에 외국 문자가 들어오면?
운영·감사누가 언제 했는지 기록이 남는가. 문제 생기면 어떻게 되돌리나

동시성 — 신입이 가장 많이 놓치는 자리

다섯 가지 중 동시성만 따로 보는 이유가 있다. 혼자 테스트할 때는 절대 재현되지 않기 때문이다.

QA는 보통 한 사람이 한 브라우저에서 순서대로 클릭한다. 개발자도 로컬에서 혼자 실행한다. 스테이징 환경에서도 접속자는 몇 명뿐이다. 그래서 동시성 결함은 테스트를 아무리 성실하게 해도 통과한다. 그리고 프로덕션에서 사용자가 몰리는 첫날 — 보통 이벤트 시작 시각이나 티켓 오픈 시각 — 정확히 그 순간에 터진다. 가장 아플 때 터지도록 설계된 결함인 셈이다.

실제로 나타나는 모양은 대체로 정해져 있다.

경합하는 자원시나리오잘못된 결과
마지막 재고 1개두 사람이 같은 순간에 주문둘 다 결제 성공, 재고가 -1이 됨
1회용 쿠폰결제 버튼을 빠르게 두 번 클릭쿠폰이 두 번 차감되거나, 할인이 두 번 적용됨
포인트 잔액두 탭에서 동시에 사용잔액보다 많이 사용됨
하나의 티켓·문서두 상담원이 같이 열어 각자 저장나중에 저장한 쪽이 앞사람 수정을 통째로 덮어씀
결제 요청응답이 느려 사용자가 새로고침 후 재시도같은 주문이 두 번 결제됨
이벤트 응모선착순 100명에 동시 요청 300건당첨자가 104명이 됨

마지막 줄이 동시성 결함의 성격을 잘 보여준다. 틀린 값이 조금씩만 틀린다. 100명이어야 하는데 104명이니, 화면상으로는 아무 문제도 없어 보이고 정산할 때에야 드러난다. 조용하고 늦게 드러나는 결함이 가장 비싸다.

요구사항을 읽으면서 던질 질문은 세 개면 충분하다.

  1. "이 자원을 동시에 두 사람이 건드릴 수 있나요?" — 재고, 잔액, 쿠폰, 좌석, 순번처럼 개수가 정해진 것이 있으면 거의 항상 그렇다.
  2. "같은 요청이 두 번 들어오면 어떻게 되나요?" — 더블클릭, 새로고침, 네트워크 재시도로 생각보다 자주 일어난다. 이걸 다루는 성질을 멱등성 (idempotency)이라고 부르는데, 용어보다 "두 번 눌러도 한 번만 처리되나요?"라는 질문 자체가 중요하다.
  3. "먼저 들어온 요청이 먼저 처리된다고 가정하고 있나요?" — 취소 요청이 주문 생성보다 먼저 도착하는 순서 역전은 실제로 일어난다.

테스트할 때는 창 두 개를 나란히 띄우고 동시에 누르거나, 개발자 도구에서 같은 요청을 다시 보내는 것만으로도 상당수가 재현된다. 본격적인 방법은 스테이지 4(자동화)와 성능 테스트에서 다루지만, 요구사항 단계에서 질문으로 남겨두는 것이 훨씬 싸다. 이 시점에는 문장 한 줄 추가로 끝나는 일이, 릴리스 후에는 데이터 복구 작업이 된다.

찾는 방법: "만약 ~라면?" 질문

빈 곳을 찾는 가장 실용적인 방법은 요구사항을 읽으며 계속 "만약 ~라면?"을 붙여보는 것이다.

요구사항: "사용자는 장바구니에 상품을 담을 수 있다."

  • 만약 품절 상품이면?
  • 만약 이미 장바구니에 있는 상품을 또 담으면?
  • 만약 로그인하지 않은 상태라면?
  • 만약 같은 상품을 두 창(탭)에서 동시에 담으면?

질문이 잘 안 떠오를 때는 여섯 개의 축을 순서대로 대보면 된다. 축을 정해두면 "생각나는 대로"가 아니라 빠짐없이 훑을 수 있다.

축질문 템플릿장바구니 예시
빈 값·없음만약 아무것도 없으면?장바구니가 비어 있을 때 결제 버튼은?
경계만약 딱 한계값이면?담을 수 있는 최대 수량이 정확히 99개일 때
중복만약 같은 걸 또 하면?같은 상품을 다시 담으면 수량 증가인가 별도 줄인가
순서만약 순서가 뒤바뀌면?결제 도중에 상품이 품절되면
실패만약 중간에 실패하면?담기 API가 타임아웃되면 화면은 무엇을 보여주나
권한·상태만약 다른 역할·상태라면?휴면 계정, 정지 계정, 비회원

이 질문들이 곧 놓친 요구사항 후보다. 전부 다 실제로 명세에 넣어야 하는 건 아니지만, 최소한 "이건 어떻게 할지 정했나요?"라고 물어볼 재료가 된다.

화면 뒤까지 밀고 가기

"만약 ~라면?"은 화면에서만 쓰는 도구가 아니다. 같은 질문을 한 겹 아래로 내리면 훨씬 깊은 누락이 나온다. 스테이지 3에서 코드와 API 응답을 읽는 법을 배우면 이 층이 훨씬 선명해지는데, 지금 단계에서도 질문은 던질 수 있다.

층질문이런 결함으로 이어진다
화면만약 품절 상품을 담으면?담기 버튼이 눌리고 결제 단계에서야 막힘
API만약 같은 요청이 두 번 오면?중복 주문 생성
API만약 응답이 타임아웃됐는데 서버에선 성공했으면?화면은 실패, 실제로는 결제됨
데이터만약 이 필드가 비어 있으면(null)?목록에서 이름 자리에 빈칸 또는 오류
데이터만약 참조 대상이 이미 삭제됐으면?삭제된 상품이 담긴 장바구니를 열면 화면이 깨짐
데이터만약 값이 길이 제한을 넘으면?저장은 되는데 잘려서 보임, 또는 저장 실패

"타임아웃됐는데 사실은 성공한 경우"는 특히 자주 실제 사고로 이어진다. 사용자는 실패 화면을 보고 다시 결제하고, 두 건이 청구된다. 요구사항에 이 경우가 적혀 있는 서비스는 드물다.

발견하는 것과 해소하는 것은 다르다

여기가 이 레슨에서 가장 중요한 구분이다. 모호함을 발견하는 것과 해소하는 것은 완전히 다른 행동이고, QA에게는 발견 권한만 있지 해소 권한은 없다.

신입이 가장 흔하게 하는 실수가 이것이다. "삭제"가 모호하다는 걸 분명히 알아챘는데, "커머스니까 당연히 숨김 처리겠지"라고 혼자 결론 내고 그 전제로 테스트 케이스를 짠다. 발견은 했는데 해소를 자기가 해버린 것이다.

왜 안 되는지 세 가지 이유가 있다.

첫째, 리스크가 비대칭이다. 내 해석이 맞으면 아무 일도 일어나지 않는다. 얻는 게 없다. 틀리면 그 전제로 만든 테스트 케이스 전부가 틀린다. 걸 게 없는 쪽에 판돈이 크게 걸린 내기다.

둘째, 조용한 통과가 만들어진다. 혼자 해석한 전제로 테스트를 돌려 전부 통과시키면, 팀에는 "검증 완료"로 보고된다. 검증되지 않은 것이 검증된 것처럼 보이는 상태 — 아예 테스트하지 않은 것보다 위험하다. 아무도 그 자리를 다시 보지 않게 되기 때문이다.

셋째, 문서가 그대로 모호하게 남는다. 내 해석이 우연히 맞았더라도 문장은 고쳐지지 않았다. 6개월 뒤 이 기능을 수정하는 사람이 같은 문장을 다시 읽고 다시 헷갈린다. 모호함은 한 번 해소하면 영구히 사라지는 게 아니라, 문서에 반영해야만 사라진다.

혼자 해소물어서 해소
걸리는 시간0분5분~하루
내 해석이 맞을 때아무 일 없음아무 일 없음 (문서는 개선됨)
내 해석이 틀릴 때테스트 전체가 무효, 릴리스 후 발견사전에 바로잡힘
다음 사람에게같은 함정이 그대로 남음문서가 명확해짐

그래서 실무의 흐름은 다섯 단계다.

  1. 발견 — 유형 목록으로 훑어 모호한 지점을 표시한다
  2. 기록 — 문장·해석 A·해석 B를 그대로 적는다 (기억에 의존하지 않는다)
  3. 질문 — 요구사항의 주인(기획자·PO)에게 묻는다
  4. 확정 — 답을 받는다
  5. 문서 반영 — 여기까지 해야 끝난다

5번이 자주 빠진다. 회의에서 구두로 답을 듣고 문서를 고치지 않으면, 반년 뒤 그 결정은 사라진다. "그때 이렇게 정했잖아요"는 근거가 되지 못한다. 답을 받았으면 문서에 반영되었는지 확인하거나, 최소한 티켓 코멘트로 남긴다.

단, 모든 것을 다 물어야 한다는 뜻은 아니다. 사소한 것까지 하나하나 질문으로 올리면 오히려 신뢰를 잃는다. 리스크가 낮은 항목은 가정을 드러내놓고 진행하는 방법이 있다.

"취소 목록의 '최근'은 30일로 가정하고 테스트 케이스를 만들었습니다. 다르면 알려주세요."

이건 혼자 판단하는 것과 결정적으로 다르다. 가정이 문서에 남아 있어서, 틀렸을 때 누군가가 바로잡을 수 있다. 침묵한 가정은 아무도 고칠 수 없지만, 적어둔 가정은 고쳐진다. 질문의 우선순위를 정하는 기준은 모듈 4의 리스크 기반 접근에서, 회의에서 전달하는 방법은 레슨 6에서 이어진다.

사례 연구 — 한 줄의 모호함이 결함이 되기까지

앞의 조각들이 실제로 어떻게 엮이는지, 한 문장을 끝까지 따라가 보자.

1단계 — 요구사항은 한 줄이었다.

"이벤트 기간 중 신규 가입자에게 웰컴 쿠폰을 1회 지급한다."

읽으면 아무 문제 없어 보인다. 리뷰 회의에서 아무도 질문하지 않았다.

2단계 — 세 사람이 세 가지로 이해했다.

'신규 가입자' 시점'1회'의 기준
기획자이메일 인증까지 마친 시점사람당 1회 (휴대폰 인증 기준)
개발자가입 API가 성공한 시점계정당 1회
QA첫 로그인 시점계정당 1회

'신규 가입자'는 어휘적 모호함, '1회'는 범위의 모호함이다. 게다가 아무도 탈퇴 후 재가입(상태 전이 누락)과 동시 요청(동시성 누락)을 묻지 않았다.

3단계 — 각자 자기 해석대로 진행했다. 개발자는 가입 API 성공 시점에 계정 기준으로 쿠폰을 발급하도록 구현했다. QA는 "가입 → 로그인 → 쿠폰함 확인" 시나리오로 테스트했고, 통과했다. 각자의 세계 안에서는 전부 정상이다.

4단계 — 이벤트 당일에 드러났다.

  • 이메일 인증을 하지 않은 계정도 쿠폰을 받았다 (기획 의도와 불일치)
  • 탈퇴 후 재가입을 반복해 한 사람이 쿠폰을 여러 장 받았다
  • 가입 요청이 몰리는 순간 같은 계정에 쿠폰이 두 장 발급된 기록이 있었다
  • 결과적으로 쿠폰 예산이 계획의 1.4배로 집행됐다

5단계 — 원인을 되짚었다. 코드에 버그가 있었던 게 아니다. 개발자는 자신이 이해한 요구사항대로 정확히 구현했다. 결함은 코드가 아니라 요구사항 문장에서 시작됐다. 그리고 그 문장에는 이 레슨에서 배운 네 유형 중 두 개와, 누락 체크리스트 다섯 개 중 두 개가 동시에 들어 있었다.

6단계 — 리뷰 때 붙였어야 할 질문은 이것이었다.

  • '신규 가입자'는 어느 시점 기준인가요? (가입 완료 / 이메일 인증 / 첫 로그인)
  • '1회'는 계정 기준인가요, 사람 기준인가요?
  • 탈퇴 후 재가입한 계정은 신규 가입자인가요?
  • 같은 사람의 가입 요청이 동시에 두 번 처리되면 쿠폰은 몇 장 나가나요?

네 개를 만드는 데 걸리는 시간은 30초다. 이 사례에서 실제로 든 비용은 쿠폰 예산 초과분, 데이터 정리 작업, 재발급 CS 응대, 긴급 배포였다. 이것이 QA가 요구사항 단계에서 만드는 가치의 크기다 — 코드 한 줄 쓰지 않고, 테스트 한 번 돌리지 않고, 질문 네 개로.

실무에서 왜 필요한가

결함을 만들기 전에 없앤다. 모듈 1에서 결함 발견 시점이 늦어질수록 비용이 기하급수적으로 는다는 것을 봤다. 요구사항 단계의 모호함은 그 곡선의 가장 왼쪽 끝, 즉 가장 싼 지점에 있다. 여기서 문장 하나를 고치면 코드도, 테스트 케이스도, 디자인도 아직 만들어지기 전이다.

"각자 다르게 이해한 채로"가 진짜 위험이다. 기획자는 A로 이해하고, 개발자는 B로 구현하고, QA는 C를 기준으로 테스트 케이스를 짜면, 통합 단계에서야 셋 다 다른 걸 만들었다는 게 드러난다. 이 시점이면 이미 코드도, 테스트 케이스도, 어쩌면 디자인까지 다시 손봐야 한다. 더 나쁜 경우는 셋이 어긋난 채로 릴리스까지 통과해버리는 것이다 — 위 사례 연구가 그랬다.

테스트 케이스의 품질은 요구사항의 명확도를 넘지 못한다. 모호한 문장 위에 아무리 정교한 테스트 설계를 얹어도, 전제가 틀리면 전부 무효다. 모듈 3에서 배울 동등분할·경계값·상태 전이 기법도 "무엇이 맞는 동작인가"가 정해져 있어야 쓸 수 있다.

다음 레슨들의 입력이 된다. 여기서 만든 질문 목록이 레슨 4의 수용 기준 (AC)으로 확정되고, 레슨 6의 리뷰 회의에서 실제로 전달된다. 즉 이 레슨은 "질문을 만드는" 단계이고, 뒤 레슨들은 그 질문을 "합의로 바꾸는" 단계다.

QA의 평판을 만든다. 릴리스 후에 버그를 잘 찾는 QA보다, 릴리스 전에 터질 곳을 미리 짚는 QA가 팀에서 훨씬 귀하게 여겨진다. 후자는 눈에 잘 띄지 않는 기여지만, 몇 번 반복되면 "이 사람이 리뷰한 기능은 나중에 덜 터진다"는 신뢰로 쌓인다.

채용시장에서의 위치

QA 면접에서 거의 빠지지 않는 질문이 있다. "요구사항이 애매할 때 어떻게 하시나요?"

흔한 답은 "개발자에게 물어봅니다"다. 나쁘지는 않지만 누구나 하는 답이라 변별력이 없다. 이 레슨을 익혔다면 절차로 답할 수 있다.

"먼저 모호함을 유형별로 분류합니다 — 단어 뜻인지, 기준값인지, 빠진 가정인지, 문장 구조인지에 따라 물어볼 대상과 방식이 달라지기 때문입니다. 그다음 두 가지 해석을 나란히 적어서 '(A)인가요 (B)인가요' 형태로 묻습니다. 리스크가 낮은 항목은 가정으로 명시해 기록하고 진행하되, 혼자 판단하고 넘어가지는 않습니다. 답을 받으면 문서나 티켓에 반영되었는지 확인합니다."

지식이 아니라 방법을 가진 사람으로 보이는 답이다. 여기에 실제 사례 하나(위 웰컴 쿠폰 같은)를 덧붙일 수 있으면 더 강하다.

과제 전형에서 일부러 모호하게 쓴 요구사항을 주고 테스트 케이스를 짜오라는 경우도 흔하다. 이때 평가자가 보는 것은 케이스 개수가 아니라, 제출물에 "이런 부분이 모호해서 이렇게 가정했습니다"라는 항목이 있는지다. 그 항목이 있으면 실무에서 상류 작업을 할 수 있는 사람으로 읽힌다.

실습 과제

과제 1 — 모호함 유형 분류하기 (10분)

다음 문장에서 모호한 부분을 모두 찾아, 네 가지 유형(어휘적/범위/암묵적 가정/문장구조) 중 무엇에 해당하는지 적는다.

"최근 주문 내역에서 관리자는 취소된 주문을 확인할 수 있다."

해설 보기
  • "최근" → 범위. 며칠인가, 몇 건인가. 기준 시점은 주문일인가 결제일인가.
  • "취소된" → 문장 구조. '취소된'이 주문을 꾸미는 건 맞지만, 취소 주체가 빠져 있다. 사용자가 취소한 것, 관리자가 취소한 것, 시스템이 자동 취소한 것이 모두 '취소된 주문'이다.
  • "관리자" → 어휘적. 어떤 관리자인가. 전체 관리자와 지점 관리자가 나뉘어 있다면 남의 지점 주문도 보이는가.
  • "확인할 수 있다" → 어휘적 + 암묵적 가정. 목록에서 보이는 것인지, 상세 내용까지 보는 것인지, 개인정보도 포함인지.
  • 빠진 것 → 취소된 주문이 하나도 없을 때 화면은 무엇을 보여주는가. 삭제된 계정의 주문은 어떻게 되는가.

네 개 이상 찾았다면 충분하다. 중요한 건 개수가 아니라 한 문장에 이렇게 많은 구멍이 있을 수 있다는 감각이다.

과제 2 — 두 가지로 다시 쓰기 (10분)

아래 문장들을 각각 괄호를 넣어 두 가지 해석으로 다시 쓰고, 두 해석의 테스트 케이스가 어떻게 달라지는지 한 줄씩 적는다.

  1. "탈퇴한 회원의 리뷰는 노출하지 않는다."
  2. "관리자 또는 작성자가 아니면 게시글을 수정할 수 없다."
해설 보기

1번

  • (A) "(탈퇴한 회원)의 리뷰는 노출하지 않는다" → 회원이 탈퇴하면 그 사람이 쓴 리뷰가 전부 사라진다. 테스트: 리뷰 3개를 쓴 계정을 탈퇴시키고 상품 페이지 확인.
  • (B) "탈퇴한 (회원의 리뷰)는…" → 사실상 같게 읽히지만, 여기서 진짜 쟁점은 시점이다. 탈퇴 이전에 이미 노출되던 리뷰를 소급해서 내리는가, 앞으로만 안 보이게 하는가. 테스트: 탈퇴 전후로 같은 리뷰의 노출 여부 비교.

두 해석에서 평점 평균이 달라진다는 점도 짚을 만하다 — 리뷰가 사라지면 상품 평점이 바뀌는가?

2번

  • (A) "(관리자 또는 작성자)가 아니면 수정 불가" → 관리자이거나 작성자이면 수정 가능. 대부분 이 의도다.
  • (B) "관리자, 또는 (작성자가 아닌 사람)이면 수정 불가" → 문법적으로 가능한 해석이고, 이 경우 관리자도 수정할 수 없게 된다.

권한 문장에서 '아니면'을 만나면 이렇게 정반대 규칙이 나올 수 있다. 그래서 권한은 문장이 아니라 표로 확정받는 게 안전하다 — 역할을 세로로, 동작을 가로로 놓고 O/X를 채운다.

과제 3 — 누락 체크리스트 적용하기 (15분)

다음 요구사항에 누락 체크리스트 다섯 가지(예외·권한·상태전이·동시성·비기능)를 차례로 대고, 각 항목마다 최소 한 개씩 빠진 것을 찾아 적는다.

"사용자는 마이페이지에서 등록한 배송지를 수정할 수 있다."

해설 보기
  • 예외·실패: 저장 중 네트워크가 끊기면 이전 값은 유지되는가. 우편번호 조회 서비스가 응답하지 않으면?
  • 권한·역할: 비회원도 배송지가 있는가. 휴면 계정은 수정 가능한가. 관리자가 대신 수정할 수 있는가. 남의 배송지 ID로 요청하면 막히는가.
  • 상태 전이: 이미 진행 중인 주문에 사용된 배송지를 수정하면 그 주문의 배송지도 바뀌는가? 이게 이 요구사항에서 가장 큰 구멍이다. 출고 후에 바뀌면 사고가 된다.
  • 동시성: PC와 앱에서 동시에 수정하면 어느 쪽이 남는가. 수정하는 동안 다른 탭에서 그 배송지를 삭제하면?
  • 비기능: 배송지가 100개면 목록이 느려지지 않는가. 수정 이력이 남는가 (분쟁 시 필요). 주소에 외국 문자나 이모지가 들어오면?

상태 전이 항목을 찾아냈다면 특히 잘한 것이다. "수정"이라는 단어 하나가 다른 도메인(주문)에 영향을 준다는 걸 알아채는 게 이 과제의 핵심이다.

과제 4 — "만약 ~라면?" 만들고 추리기 (15분)

다음 요구사항에 "만약 ~라면?" 질문을 최소 10개 만든다. 앞의 여섯 축(빈 값·경계·중복·순서·실패·권한)을 순서대로 대며 만든다. 그다음, 그중 리뷰 회의에 꼭 가져갈 3개를 골라 왜 그 셋인지 한 줄로 적는다.

"사용자는 게시글에 좋아요를 누를 수 있다."

해설 보기

질문 예시: 이미 누른 글을 또 누르면 취소인가 무시인가 / 자기 글에도 누를 수 있나 / 비회원이 누르면 / 삭제된 글에 누르면 / 좋아요를 누른 뒤 글이 삭제되면 카운트는 / 빠르게 연타하면 / 두 기기에서 동시에 누르면 / 차단한 사용자의 글이면 / 좋아요 수가 100만이면 표시는 / API가 실패했는데 화면 숫자는 이미 올라갔으면 / 작성자에게 알림이 가는가, 취소해도 가는가.

우선순위 3개 고르는 기준은 "틀렸을 때 피해가 큰 것"이다.

  1. 연타·동시 클릭 시 중복 반영 — 숫자가 조용히 틀어지고 나중에 복구가 어렵다
  2. API 실패 시 화면 숫자만 올라가는 경우 — 사용자가 잘못된 상태를 사실로 믿는다
  3. 삭제된 글의 좋아요 카운트 처리 — 집계·랭킹 등 다른 기능으로 번진다

나머지("자기 글에 누를 수 있나" 등)는 정책 결정일 뿐 피해가 작으므로, 가정으로 적어두고 넘어가도 된다. 모든 질문이 같은 무게가 아니라는 것이 이 과제의 요점이다. 우선순위를 정하는 정식 방법은 모듈 4에서 다룬다.

과제 5 — 실제 문서에 적용하기 (선택, 20분)

지금 팀에서 진행 중인 기획서나 티켓을 하나 열고, 이 레슨의 유형 목록과 체크리스트를 실제로 대본다. 목표는 모호함 5개, 누락 3개를 찾는 것이다.

찾은 것을 다음 형식으로 정리해보면 그대로 리뷰 회의에 가져갈 수 있다.

문장유형해석 A해석 B리스크
(원문 그대로)어휘적높음/중간/낮음

리스크가 '낮음'인 항목은 가정으로 적어두고, '높음'인 것부터 질문한다.

자가 체크리스트

  • 모호한 문장이 왜 읽을 때는 어색하게 느껴지지 않는지 설명할 수 있다
  • 모호함의 네 가지 유형(어휘적, 범위, 암묵적 가정, 문장 구조)을 구분하고 각각 예를 들 수 있다
  • 숫자가 적혀 있어도 기준점 때문에 모호할 수 있다는 것을 예로 설명할 수 있다
  • 한국어 문장을 괄호로 두 가지로 다시 써서 모호함을 확인할 수 있다
  • 요구사항에서 흔히 빠지는 다섯 가지 조건(예외, 권한, 상태 전이, 동시성, 비기능)을 나열할 수 있다
  • 동시성 결함이 왜 혼자 테스트할 때 재현되지 않는지, 어떤 형태로 나타나는지 설명할 수 있다
  • 상태 전이 표를 그려 빈칸에서 누락을 찾아낼 수 있다
  • "만약 ~라면?" 질문을 여섯 축으로 빠짐없이 만들어낼 수 있다
  • 같은 질문을 API·데이터 레벨로 한 겹 내려서 던질 수 있다
  • 모호함을 발견하는 것과 해소하는 것의 차이를, 그리고 혼자 해소하면 안 되는 이유를 설명할 수 있다
  • 리스크가 낮은 항목을 '가정으로 기록하고 진행'하는 것과 '혼자 판단하고 넘어가는 것'의 차이를 안다
  • 모호함이 왜 통합 단계에서야 드러나는 문제로 이어지는지 설명할 수 있다

흔한 실수

  • 모호함을 발견하고 스스로 판단해서 넘어간다. "아마 이런 뜻이겠지"로 혼자 해석하고 테스트 케이스를 짜면, 내 해석이 맞을 때는 얻는 게 없고 틀릴 때는 전부를 잃는다. 게다가 통과 보고까지 나가면 검증되지 않은 것이 검증된 것처럼 남는다.
  • 답을 구두로만 받고 문서에 반영하지 않는다. "회의에서 그렇게 정했잖아요"는 반년 뒤에 근거가 되지 못한다. 결정은 문서나 티켓에 글로 남아야 살아남는다.
  • 모든 모호함을 같은 무게로 질문한다. 사소한 것까지 전부 올리면 신뢰를 잃는다. 리스크가 낮은 것은 가정으로 명시하고 진행한다 — 침묵과 다르다.
  • "만약 ~라면?" 질문을 무한정 만들어 우선순위 없이 나열한다. 모든 질문이 같은 무게는 아니다. 리스크가 큰 것부터 추리는 판단(모듈 4에서 다룸)이 필요하다.
  • 동시성 문제를 간과한다. "동시에 여러 명이 접근하면?"은 신입이 가장 놓치기 쉬운 누락 유형이다 — 혼자 테스트할 때는 절대 재현되지 않기 때문이다. 개수가 정해진 자원(재고·쿠폰·좌석·잔액)이 보이면 반드시 질문한다.
  • 숫자가 적혀 있으면 명확하다고 믿는다. "하루 3회"의 '하루'가 언제 시작하는지, "30분 이내"를 어디서부터 재는지가 빠져 있으면 여전히 모호하다.
  • 정상 흐름만 따라 읽는다. 성공만 적힌 동사(보낸다·저장한다·결제한다)를 발견하면 그 자리에 반드시 "실패하면?"이 붙는다.
  • 문서에 없는 것은 '없어도 되는 것'이라고 생각한다. 누락은 결정이 아니라 대개 망각이다. 빠진 자리를 찾는 것 자체가 QA의 일이다.
  • 모호함 지적을 사람에 대한 지적처럼 전달한다. "이거 왜 이렇게 쓰셨어요"가 아니라 "(A)인가요 (B)인가요"로 묻는다. 전달 방식은 레슨 6에서 따로 다룬다.

참고 자료

  • ISTQB Foundation Level Syllabus — Requirements Reviews — 요구사항 리뷰에서 모호함·누락을 찾는 접근법
  • IEEE 830 / ISO/IEC/IEEE 29148 — 요구사항 명세의 품질 속성(명확성·완전성·검증 가능성)을 정의한 표준. 이 레슨의 유형 분류가 결국 이 속성들의 실무 버전이다
  • Michael Hunter, "The Low, Low Cost of Quality" — 요구사항 단계 결함의 비용에 대한 실무 관점 아티클
  • Gojko Adzic, Specification by Example — 모호한 문장 대신 구체적 예시로 합의하는 방법. 다음 레슨(수용 기준)의 배경이 되는 책

낯선 말 풀이

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

QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
DB — 데이터베이스
데이터를 넣어 두고 꺼내 쓰는 저장소. 보통 표 여러 개가 서로 연결된 형태다.
CS — 고객 지원 · 칩 선택 신호
이 커리큘럼에서 두 가지로 쓰인다. ① 고객 문의와 불만을 직접 받는 조직 ② 여러 부품이 한 선을 나눠 쓸 때 "지금은 네 차례" 라고 하나를 고르는 신호. 앞뒤에 문의·고객이 있으면 ①, 통신·배선 이야기면 ②다.
MB — 메가바이트
데이터 양의 단위. 사진 한 장이 대략 2~5 메가바이트쯤 된다.
API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
URL — 인터넷 주소
웹에서 무언가의 위치를 가리키는 주소 한 줄.
PO — 제품 책임자
무엇을 먼저 만들지 정하는 사람. 애자일 방식에서 쓰는 역할 이름이다.
AC — 수용 기준
"이 조건들을 만족하면 다 된 것으로 친다" 를 미리 글로 못 박아 둔 목록.
ID — 식별자
무엇 하나를 다른 것과 구별하기 위해 붙인 이름이나 번호.
ISTQB — 국제 소프트웨어 테스팅 자격 위원회
테스터 자격 시험을 만들고 용어를 정리하는 국제 단체.
IEEE — 전기전자기술자협회
전기·전자·컴퓨터 분야의 세계 최대 기술자 단체. 규격도 만든다.
ISO/IEC/IEEE — 세 단체 공동 표준
세 국제 단체가 함께 낸 표준이라는 표시.

용어집 전체 보기