개념
두 가지를 한 레슨에 묶은 이유가 있다. TDD와 BDD는 같은 한 가지를 한다 — "나중에 확인하기" 를 "먼저 합의하기" 로 옮기는 것이다.
집을 다 짓고 나서 "이게 원하던 집인가" 를 확인하면, 틀렸을 때 고치는 비용이 집값만큼 든다. 도면을 먼저 그려 함께 보면 그 비용이 종이 한 장이다. 두 방식의 차이가 그것이고, 다른 점은 도면을 누가 읽느냐다.
| 누가 읽나 | 무엇을 합의하나 | |
|---|---|---|
| TDD | 개발자 | 코드가 어떻게 동작해야 하는가 |
| BDD | 기획자·개발자·QA 모두 | 시스템이 사용자에게 어떻게 보여야 하는가 |
QA에게 직접 쓸모가 큰 쪽은 BDD이지만, TDD가 있는 팀과 없는 팀에서 QA의 일이 달라지므로 둘 다 알아야 한다.
TDD — 테스트를 먼저 쓴다
TDD(Test-Driven Development)는 개발자가 기능 코드를 짜기 전에 그 기능을 검증할 테스트 코드를 먼저 쓰는 개발 방식이다. 순서는 다음과 같다.
1. 실패하는 테스트를 먼저 쓴다 (Red)
2. 테스트를 통과시키는 최소한의 코드를 짠다 (Green)
3. 코드를 정리한다, 테스트는 계속 통과해야 한다 (Refactor)이 사이클을 짧게 반복한다. TDD는 주로 개발자가 단위 테스트(모듈 10에서 다룬다) 수준에서 실천하는 습관이다.
TDD가 실제로 주는 것
"테스트를 먼저 쓰면 좋다" 는 말로는 왜 좋은지 안 보인다. 세 가지가 생긴다.
| 얻는 것 | 어떻게 |
|---|---|
| 설계 압력 | 테스트하기 쉬운 코드를 짜게 된다 → 의존이 줄고 단위가 작아진다 |
| 회귀 그물 | 바꿀 때마다 즉시 깨지는 것이 보인다 |
| 실행되는 문서 | 테스트 이름이 "이 함수는 무엇을 하는가" 를 말해 준다 |
첫 줄이 TDD의 진짜 효과다. 테스트를 먼저 쓰려면 그 코드를 독립적으로 호출할 수 있어야 하고, 그러려면 구조가 단순해져야 한다. 테스트 때문에 설계가 좋아지는 것이다.
이것이 QA에게 중요한 이유가 있다. 모듈 7 레슨 2에서 본 "반쯤 만들어진 상태" 를 만들기 어려운 제품은 대개 단위가 크고 의존이 많다. TDD가 있는 팀에서는 테스트용 상태를 만들기 쉬운 구조가 되어 있어서, QA의 데이터 준비도 수월해진다.
TDD가 있는 팀에서 QA의 일이 달라진다
QA가 체감하는 차이는 분명하다.
| TDD가 없는 팀 | TDD가 있는 팀 | |
|---|---|---|
| QA가 만나는 결함 | 계산 오류·널 처리 같은 기본 결함부터 | 기본은 걸러져 있다 |
| QA가 쓸 시간 | 기본 확인에 많이 쓴다 | 흐름·통합·사용성·탐색에 쓴다 |
| 수정 후 재검증 | 다른 곳이 깨질까 불안하다 | 단위 테스트가 먼저 알려 준다 |
두 번째 줄이 QA의 가치가 올라가는 지점이다. 기본 결함을 사람이 손으로 잡고 있으면 탐색적 테스팅(모듈 5)에 쓸 시간이 없다. 그래서 QA가 개발 단계 테스트를 요청하는 것은 자기 영역을 넘보는 일이 아니라 자기 시간을 되찾는 일이다(모듈 6 레슨 5의 "발견 단계" 지표가 그 근거다).
TDD를 오해하는 지점
| 오해 | 실제 |
|---|---|
| "테스트를 많이 쓰면 TDD" | 순서가 TDD다. 나중에 쓰면 테스트는 있지만 설계 압력은 없다 |
| "TDD를 하면 QA가 필요 없다" | 단위 테스트는 개발자가 생각한 것만 확인한다 |
| "TDD는 느리다" | 초기에는 느리고, 고치는 비용에서 회수한다 |
| "커버리지 100%면 안전" | 모듈 6 레슨 5와 같다 — 계획이 충분했나는 별개 |
두 번째 줄이 면접에서도 나온다. 단위 테스트는 개발자가 상상한 입력에 대해 돈다. 상상하지 못한 입력, 사용자가 실제로 하는 순서, 환경 차이는 그 바깥에 있다. 그래서 TDD가 잘 되는 팀에서도 QA가 보는 층이 달라질 뿐 없어지지 않는다.
BDD — 사람이 읽을 수 있는 문장으로 행위를 정의한다
BDD(Behavior-Driven Development)는 TDD의 사고방식을 확장해, 개발자가 아닌 사람도 읽고 이해할 수 있는 문장으로 시스템이 어떻게 동작해야 하는지 먼저 정의한다. 대표적인 형식이 Given-When-Then(Gherkin 문법)이다.
Given 로그인한 사용자가 장바구니에 상품 2개를 담아둔 상태에서
When 사용자가 유효한 쿠폰 코드를 입력하고 "적용" 버튼을 누르면
Then 주문 금액에서 쿠폰 할인이 반영되어야 한다- Given — 시작 상태(사전조건)
- When — 사용자의 행동
- Then — 기대하는 결과
이 구조는 모듈 3(레슨 1)에서 배운 테스트 케이스의 사전조건·절차· 기대결과와 본질적으로 같다 — 다만 BDD는 이걸 기획자·개발자·QA가 모두 같은 언어로 합의하는 산출물로 만든다는 점이 다르다.
Gherkin 문법을 조금 더
실무에서 쓰이는 키워드는 몇 개 더 있다. 외울 양이 적다.
| 키워드 | 쓰임 |
|---|---|
Feature | 기능 하나. 파일 맨 위에 목적을 적는다 |
Scenario | 시나리오 하나 |
Background | 모든 시나리오에 공통인 Given |
And / But | 같은 단계가 여러 개일 때 이어 쓴다 |
Scenario Outline + Examples | 값만 다른 시나리오를 표로 |
마지막이 특히 유용하다. 경계값을 시나리오 여러 개로 늘어놓는 대신 표 하나로 묶는다.
Scenario Outline: 비밀번호 길이 검증
Given 회원가입 화면에서
When 비밀번호에 <길이>자를 입력하고 가입을 누르면
Then 결과는 <결과>여야 한다
Examples:
| 길이 | 결과 |
| 7 | 거부 |
| 8 | 허용 |
| 64 | 허용 |
| 65 | 거부 |모듈 3의 경계값 분석이 그대로 표가 된다. 그리고 이 표는 기획자도 읽을 수 있어서, 경계가 어디인지에 대한 합의가 여기서 끝난다.
Background 는 편하지만 남용하면 시나리오가 안 읽힌다. 공통 Given이
다섯 줄이 되면, 각 시나리오를 읽을 때 위를 계속 올라가 봐야 한다.
좋은 시나리오와 나쁜 시나리오
BDD에서 가장 많이 실패하는 지점이 추상화 수준이다. 너무 낮으면 기획자가 못 읽고, 너무 높으면 무엇을 확인하는지 모른다.
| 수준 | 예 | 문제 |
|---|---|---|
| 너무 낮다 | "Given users 테이블에 grade='VIP' row가 있을 때 / When POST /api/coupons/apply 를 호출하면" | 기획자가 못 읽는다. 구현이 바뀌면 시나리오가 깨진다 |
| 적절하다 | "Given VIP 등급 사용자가 장바구니에 상품 2개를 담았을 때 / When 유효한 쿠폰을 적용하면 / Then 할인이 반영된다" | — |
| 너무 높다 | "Given 사용자가 쇼핑을 할 때 / When 쿠폰을 쓰면 / Then 잘 동작한다" | 무엇을 확인하는지 알 수 없다. 판정이 불가능 |
가늠하는 기준이 하나 있다. 그 시나리오를 기획자에게 읽어 주고 "맞나요" 를 물을 수 있는가다. 물을 수 없으면 너무 낮거나 너무 높다.
세 번째 줄은 레슨 1의 "기대 결과를 셀 수 있게" 와 같은 문제다. "잘 동작한다" 는 사람마다 판정이 다르다.
시나리오를 쓸 때의 다섯 규칙
- When은 하나만 — 행동이 둘이면 시나리오를 쪼갠다
- Then에 조작을 넣지 않는다 — Then은 확인만. "Then 저장하고 확인한다" 는 두 가지다
- 화면 조작 순서를 쓰지 않는다 — "버튼을 누르고 스크롤해서" 가 아니라 의도를 쓴다
- 구현 용어를 피한다 — 테이블·API·쿠키 대신 사용자 언어
- 시나리오 하나에 결과 하나 — 확인할 것이 셋이면 Then을
And로 잇되, 서로 다른 관심사면 쪼갠다
2번과 3번이 가장 자주 깨진다. 특히 3번은 BDD 시나리오를 자동화 스크립트처럼 쓰기 시작하면 바로 생긴다. 그러면 화면이 조금 바뀔 때마다 시나리오를 고쳐야 하고, 기획자는 더 이상 읽지 않는다.
BDD에서 QA의 역할
BDD 워크숍(흔히 "Three Amigos"라 불리는, 기획자·개발자·QA 세 역할이 함께 모이는 세션)에서 QA는 Given-When-Then 시나리오를 작성하거나 검토하며 엣지 케이스와 예외 상황을 미리 질문한다.
"Given에서 '유효한 쿠폰'이라고 했는데, 쿠폰이 만료됐거나 이미 쓴 쿠폰이면 어떻게 되나요? 그 시나리오도 필요하지 않을까요?"
이 질문은 모듈 2(레슨 6)에서 배운 "질문하는 QA"의 역할을, BDD라는 구체적인 산출물 위에서 실천하는 것이다. 이렇게 미리 합의된 시나리오는 자동화 테스트(Cucumber 같은 도구)로 그대로 옮겨지기도 한다 — 즉 BDD 시나리오가 살아있는 문서이자 테스트 코드의 원본이 된다.
Three Amigos 세션을 실제로 돌리는 법
"모여서 이야기한다" 로 두면 회의가 길어지고 결론이 안 난다. 틀을 정해 둔다.
| 항목 | 권장 |
|---|---|
| 언제 | 개발 시작 전. 스프린트라면 리파인먼트 즈음 |
| 누가 | 기획 1 · 개발 1~2 · QA 1. 셋이면 충분하다 |
| 얼마나 | 스토리 하나에 15~30분 |
| 다루는 범위 | 스토리 하나씩. 여러 개를 몰아 보지 않는다 |
| 산출물 | 시나리오 3~7개 + 답을 못 찾은 질문 목록 |
마지막 줄이 가장 중요하다. 세션에서 모든 질문에 답이 나오지는 않는다. "쿠폰과 포인트를 같이 쓰면?" 에 아무도 답을 못 하면 그것을 결정 대기 항목으로 적어 두고 넘어간다. 그 목록이 없으면 나중에 개발자가 임의로 정하게 되고, 그 선택이 결함으로 돌아온다.
QA가 던지는 질문의 유형
세션에서 무엇을 물을지 막막하면 유형별로 하나씩 꺼내면 된다. 모듈 5 레슨 14의 치트시트를 요구 단계에 쓰는 셈이다.
| 유형 | 질문 예 |
|---|---|
| 경계 | "쿠폰이 정확히 최소 주문 금액일 때는 적용되나요?" |
| 예외 | "쿠폰이 만료됐거나 이미 쓴 것이면 무엇이 보이나요?" |
| 상태 | "적용한 뒤 수량을 바꾸면 할인이 다시 계산되나요?" |
| 권한 | "비로그인 상태에서 쿠폰을 넣으면?" |
| 시간 | "결제 중에 쿠폰이 만료되면?" |
| 중복·동시 | "같은 쿠폰을 두 탭에서 동시에 쓰면?" |
| 되돌리기 | "주문을 취소하면 쿠폰이 돌아오나요?" |
마지막 줄이 기획에서 가장 많이 빠진다. 정상 흐름은 모두가 생각하지만 되돌리는 흐름은 자주 비어 있고, 그 공백이 운영에서 데이터 불일치로 나타난다(모듈 6 레슨 2의 "데이터가 상한다").
질문의 목적이 지적이 아니라 공백 발견이라는 점을 전달하는 것도 중요하다 (모듈 6 레슨 3). "이것도 안 정하셨네요" 가 아니라 "이 경우를 어떻게 하면 좋을까요" 로 묻는다.
BDD 자동화의 함정
BDD 시나리오를 그대로 자동화하는 도구(Cucumber 등)가 있다. 유용하지만 대가가 있다.
| 문제 | 어떻게 나타나나 |
|---|---|
| 두 겹 유지보수 | 시나리오 문장과 단계 구현 코드를 둘 다 고쳐야 한다 |
| 단계 재사용의 혼란 | 비슷한 문장이 여러 개 생기고 어느 것이 도는지 모른다 |
| 느린 실행 | 화면을 통해 돌면 시나리오 수에 비례해 느려진다 |
| 읽지 않는 문서 | 기획자가 안 읽으면 BDD의 목적이 사라진다 |
네 번째가 핵심 판단 기준이다. BDD 도구를 쓰는 이유는 비개발자가 읽을 수 있는 문서를 얻는 것이다. 그 사람이 안 읽는다면, 같은 테스트를 평범한 자동화 코드로 쓰는 편이 싸다.
그래서 현실적인 선택은 셋이다.
- BDD를 대화 도구로만 쓴다 — 시나리오는 합의용, 자동화는 일반 코드로
- 핵심 흐름만 Cucumber로 자동화한다
- 전부 BDD로 자동화한다 — 규제 산업처럼 문서가 산출물일 때
첫 번째가 가장 흔하고 가장 실용적이다. 그리고 그것만으로도 BDD의 가장 큰 가치(개발 전 공백 발견)는 이미 얻는다.
인수기준과 BDD는 같은 것인가
애자일 팀에서 인수기준(Acceptance Criteria) 이라는 말을 더 자주 쓴다. 관계를 정리해 두면 혼란이 없다.
| 형태 | 수준 | |
|---|---|---|
| 인수기준 | 목록 형태여도 된다 | "무엇이 되면 완료인가" |
| BDD 시나리오 | Given-When-Then 형식 | 인수기준을 실행 가능한 형태로 |
즉 BDD는 인수기준을 쓰는 한 가지 형식이다. 형식을 꼭 Gherkin으로 할 필요는 없다 — 중요한 것은 개발 전에 합의하고, 판정이 가능하게 쓰는 것이다. 레슨 8에서 인수기준과 완료의 정의를 더 다룬다.
반대로 형식만 Gherkin인데 개발 후에 쓰는 것은 BDD가 아니다. 그냥 예쁜 테스트 케이스 문서다.
사례 — 15분 세션이 결함 6건을 미리 없앴다
"쿠폰 적용" 스토리를 개발 전에 15분 세션으로 다룬 기록이다. 기획서에는 시나리오가 하나였다.
"사용자가 쿠폰 코드를 입력하면 할인이 적용된다."
QA가 질문 유형을 따라 일곱 개를 물었고, 그 자리에서 결론이 난 것이 넷, 결정 대기로 남은 것이 셋이었다.
| 질문 | 그 자리의 결론 |
|---|---|
| 만료된 쿠폰? | 안내 문구 표시, 적용 안 됨 |
| 이미 쓴 쿠폰? | 같은 처리 |
| 수량을 바꾸면 재계산? | 재계산해야 한다 ← 기획에 없었다 |
| 최소 주문 금액 경계? | 금액 이상이면 적용(같을 때 포함) |
| 쿠폰 + 포인트 동시? | 결정 대기 |
| 결제 중 만료? | 결정 대기 |
| 주문 취소 시 쿠폰 복원? | 결정 대기 |
시나리오가 1개에서 7개로 늘었고, 개발자가 그것을 보고 구현했다.
| 세션 없이 갔다면 | 실제 |
|---|---|
| 재계산 누락 → 결제 금액 오류 | 처음부터 구현됨 |
| 경계 처리 임의 결정 → 반려 논쟁 | 합의되어 있었다 |
| 쿠폰 복원 누락 → 데이터 불일치 | 결정 대기로 올려 다음 스프린트에 처리 |
비용은 15분이었고, 그중 가장 값진 산출물은 "결정 대기 3건" 이었다. 그 셋은 세션에서 답이 안 나온 것인데, 적어 두었기 때문에 잊히지 않았다. 적지 않았다면 개발자가 그 자리에서 임의로 정했을 것이다.
TDD와 BDD의 관계
TDD는 "코드가 옳게 동작하는가"를 개발자 관점에서 검증하는 습관이고, BDD는 "시스템이 사용자가 원하는 대로 행동하는가"를 비즈니스 언어로 먼저 합의하는 방식이다. 둘은 배타적이지 않고, 많은 팀이 BDD로 시나리오를 합의한 뒤 그 시나리오를 구현하는 코드를 TDD 방식으로 짠다.
실무에서 왜 필요한가
BDD 시나리오 작성 워크숍에 QA가 참여하는 팀에서는, 개발이 시작되기 전에 엣지 케이스가 이미 논의되어 있어 나중에 결함으로 발견되는 빈도가 줄어든다. 이건 모듈 2에서 배운 "요구사항 단계에서 결함을 막는다"는 원칙을 BDD라는 구체적인 실무 도구로 실천하는 것이다. "BDD/Cucumber 경험"을 요구하는 채용공고도 결국 이 협업 능력을 평가하려는 것이다.
결함을 막는 비용이 가장 싼 지점
모듈 1에서 "결함은 늦게 발견될수록 비싸다" 를 배웠다. 이 레슨의 활동은 그 곡선의 가장 왼쪽에 있다.
| 언제 발견 | 고치는 것 |
|---|---|
| 요구 합의 단계(이 레슨) | 문장 한 줄 |
| 개발 중 | 코드 몇 줄 |
| QA 단계 | 코드 + 재검증 + 왕복 |
| 운영 | 코드 + 긴급 배포 + 이미 나간 데이터 |
첫 줄과 마지막 줄의 차이가 수십 배다. 15분 세션으로 결함 하나를 막는 것이 QA가 할 수 있는 가장 효율적인 일인 이유다.
QA가 앞으로 이동하는 구체적인 방법
"QA가 앞단에 참여해야 한다" 는 말은 자주 들리지만 무엇을 하라는 것인지 가 모호하다. 이 레슨이 그 답이다 — 인수기준 작성과 Three Amigos 세션에 들어가는 것이고, 거기서 질문 유형 표를 따라 묻는 것이다.
그리고 이것은 권한이 필요한 일이 아니다. 회의에 들어가지 못해도 스토리를 읽고 질문 목록을 적어 보내는 것은 할 수 있다. 그 목록이 몇 번 유용했으면, 다음부터는 회의에 불린다.
TDD를 요청할 수 있게 된다
QA가 개발 방식에 관여하는 것이 월권처럼 느껴질 수 있다. 그런데 모듈 6 레슨 5의 발견 단계 지표가 있으면 이것은 사실 기반 요청이 된다.
"최근 3개 릴리즈에서 QA 단계 발견 결함의 40%가 입력 검증·계산 오류 입니다. 단위 테스트에서 잡히는 유형이라, 그쪽에 장치가 생기면 저희가 통합·흐름 쪽에 시간을 쓸 수 있습니다."
"테스트를 더 쓰세요" 가 아니라 "저희 시간을 이렇게 쓰고 싶습니다" 로 말하는 것이 차이다. 후자는 거절하기 어렵다.
채용시장에서의 위치
공고에 "BDD·TDD 경험" 또는 "Cucumber/Gherkin" 이 적히는 경우가 늘고 있다. 면접에서 묻는 것은 문법이 아니라 앞단에 참여해 본 경험이다.
| 질문 | 약한 답 | 강한 답 |
|---|---|---|
| "BDD 해보셨어요?" | "Gherkin으로 시나리오 썼습니다" | "개발 전에 Three Amigos로 시나리오를 합의했고, 답이 안 난 것은 결정 대기로 남겼습니다" |
| "TDD가 있으면 QA는 뭐가 달라요?" | "편합니다" | "기본 결함이 걸러지므로 통합·흐름·탐색에 시간을 씁니다. 단위 테스트는 개발자가 상상한 입력만 봅니다" |
| "Cucumber 꼭 써야 하나요?" | "쓰면 좋습니다" | "기획자가 그 문서를 읽지 않으면 일반 자동화 코드가 더 쌉니다" |
| "시나리오를 어떻게 쓰세요?" | "Given-When-Then으로요" | "When은 하나만, Then에 조작을 넣지 않고, 구현 용어를 피합니다" |
| "앞단 참여를 어떻게 시작했어요?" | "회의에 불러 주셨습니다" | "스토리를 읽고 질문 목록을 적어 보냈고, 몇 번 유용하니 회의에 불렸습니다" |
세 번째가 가장 변별력이 크다. 도구를 안 쓸 이유를 말할 수 있는 사람은 그 도구의 목적을 아는 사람이다. "BDD는 좋은 것" 으로만 아는 답과 분명히 다르게 읽힌다.
다섯 번째는 주니어가 쓸 수 있는 가장 좋은 답이다. 권한 없이 스스로 앞으로 이동한 경험은 직급과 무관하게 평가된다.
공고 표현으로는 "BDD", "TDD 환경", "Three Amigos", "인수기준 작성", "시프트 레프트" 가 이 레슨에 걸린다. 자동화 구현은 스테이지 4, 스크럼 안에서의 인수기준 운영은 레슨 8 에서 이어 받는다.