개념
먼저 — 소프트웨어는 이렇게 만들어진다
이 커리큘럼의 첫 레슨이다. 이 분야가 처음이라면, 테스트 이야기를 꺼내기 전에 소프트웨어가 어떤 과정을 거쳐 사람 손에 닿는지부터 그려 두는 편이 낫다. 앞으로 나올 말들이 전부 이 과정 위의 어느 지점을 가리키기 때문이다.
크게 다섯 단계다.
- 정한다 — 무엇을 만들지 글로 적는다. "로그인은 이메일로 한다" 같은 문장들이다
- 만든다 — 개발자가 그 글을 코드로 옮긴다
- 확인한다 — 적은 대로 되는지, 쓸 만한지 확인한다. 이 자리가 QA다
- 내보낸다 — 만든 것을 실제 사용자가 쓰는 곳으로 옮긴다
- 지켜본다 — 사용자가 쓰는 동안 문제가 없는지 본다
여기서 가장 흔한 오해 하나를 미리 깨 두자. 3번만 QA의 자리가 아니다. 이 레슨이 끝날 때쯤이면, 1번에서 묻는 질문 하나가 3번에서 찾아내는 결함 열 개보다 쌀 때가 많다는 것을 알게 된다.
앞으로 계속 나올 말들
위 다섯 단계에 붙은 이름들이다. 이 사이트 전체에서 설명 없이 쓰이므로 여기서 한 번 정리한다. 지금 외울 필요는 없다. 읽다가 막히면 이 표로 돌아오면 된다.
| 말 | 뜻 | 위 단계 |
|---|---|---|
| 요구사항 | 무엇을 만들지 적은 것. "사용자는 비밀번호를 바꿀 수 있다" 같은 문장 | 1 |
| 명세 | 요구사항을 더 정확히 적은 문서. "비밀번호는 8자 이상, 숫자 포함" 처럼 | 1 |
| 이해관계자 | 그 결정에 걸린 사람들 — 기획자, 개발자, 영업, 고객, 법무 | 1 |
| 스프린트 | 2주쯤을 한 묶음으로 잡고 그 안에 만들 것을 정하는 방식 | 1~4 |
| 빌드 | 사람이 쓴 코드를 컴퓨터가 실행할 수 있는 형태로 바꾸는 일 | 2 |
| 배포 | 만든 것을 실제로 돌아가는 곳에 올리는 일 | 4 |
| 릴리스 | 사용자에게 공식적으로 내놓는 일. 배포보다 넓은 말이다 | 4 |
| 운영 | 사용자가 실제로 쓰고 있는 상태. "운영에서 터졌다" 는 사용자가 겪었다는 뜻 | 5 |
| 핫픽스 | 운영 중 급한 문제를 고쳐 바로 내보내는 일 | 5 |
표의 왼쪽 두 줄(요구사항·명세)과 오른쪽 끝(운영·핫픽스)이 특히 중요하다. 이 레슨의 핵심이 "맨 앞에서 잡으면 싸고, 맨 뒤에서 잡으면 비싸다" 이기 때문이다.
품질이란 무엇인가
"품질이 좋다"는 말은 애매하다. 소프트웨어에서 품질은 보통 두 가지 축으로 나눠 본다.
- 명세 충족(conformance to requirements): 요구사항에 적힌 대로 동작하는가
- 쓰임에 적합함(fitness for use): 실제 사용자가 목적을 달성할 수 있는가
두 축은 자주 어긋난다. 요구사항대로 정확히 만들었는데도 사용자가 못 쓰는 소프트웨어가 있고, 요구사항엔 없지만 사용자가 당연히 기대하는 동작(예: 뒤로가기 버튼이 데이터를 날리지 않는 것)이 빠져서 "버그"로 취급되는 경우도 있다. 테스트는 이 두 축을 모두 확인하는 활동이다 — 명세와 맞는지(이후 배울 "검증"), 그리고 실제로 쓸모 있는지(이후 배울 "확인")를 함께 본다.
두 축이 어긋나는 순간을 구체적으로 보자.
| 상황 | 명세 충족 | 쓰임에 적합 | 실제로 벌어지는 일 |
|---|---|---|---|
| 요구사항대로 정확히 구현 | ✅ | ✅ | 정상 |
| 비밀번호에 특수문자 필수 — 명세대로 구현 | ✅ | ❌ | 사용자가 가입 중 이탈. "명세는 지켰다"는 말은 위로가 안 된다 |
| 명세에 없는 뒤로가기 처리를 개발자가 알아서 넣음 | ❌ | ✅ | 아무도 불평 안 함. 오히려 명세를 갱신해야 할 신호 |
| 요구사항 자체가 사용자 흐름과 안 맞음 | ✅ | ❌ | 가장 비싼 실패. 다 만들고 나서야 드러난다 |
마지막 줄이 이 커리큘럼 전체가 다루는 문제다. 테스트 케이스를 아무리 촘촘히 짜도 명세 자체가 틀렸다면 전부 통과한다. 그래서 QA는 "명세대로 되는가"만 보는 사람이 아니라 "이 명세가 맞는가"까지 묻는 사람이어야 한다.
쉬운 비유로 다시 보기 — 우산
전문 용어를 다 걷어내고 우산 하나로 생각해보자.
- 명세 충족: "이 우산은 지름 1m, 비를 막는다"는 설명서대로 만들어졌다 → 검사해보니 정확히 그렇다. 통과.
- 쓰임에 적합함: 그런데 손잡이가 너무 무겁거나, 펴는 데 양손이 필요하다면? 설명서에는 없던 문제지만, 우산을 써본 사람은 누구나 "이건 별로다"라고 느낀다.
우산 공장은 "설명서대로 만들었으니 우리 책임은 끝났다"고 말할 수 있다. 하지만 실제로 그 우산을 들고 다니는 사람에게는 그 말이 아무 의미가 없다. 소프트웨어도 똑같다. "명세서대로 만들었다"는 말은 개발팀에게는 방어 논리가 되지만, 그 화면을 써야 하는 사용자에게는 위로가 되지 않는다.
이 우산 비유를 기억해두면 이 커리큘럼 전체에서 반복해서 쓰이는 "명세는 지켰는데 왜 문제죠?"라는 상황을 훨씬 빨리 알아챌 수 있다.
품질에는 눈에 안 보이는 축도 있다
위 두 축은 사용자가 체감하는 품질이다. 여기에 개발팀만 체감하는 축이 하나 더 있다.
- 내부 품질: 코드가 읽기 쉬운가, 고치기 쉬운가, 테스트하기 쉬운가
내부 품질은 사용자에게 직접 보이지 않지만, 낮아지면 결함 수정 속도가 느려지고 새 결함이 생길 확률이 올라간다. "간단한 수정인데 왜 2주 걸려요?"라는 질문의 답이 대개 여기 있다. QA가 코드를 읽을 수 있어야 하는 이유 중 하나이기도 하다(모듈 9).
국제 표준 ISO/IEC 25010은 품질을 기능 적합성·성능 효율성·호환성·사용성·신뢰성· 보안성·유지보수성·이식성 여덟 갈래로 더 잘게 나눈다. 지금 다 외울 필요는 없다 — 스테이지 5(비기능 테스트)에서 이 갈래들을 하나씩 실제 테스트로 다룬다. 지금 가져갈 것은 "품질은 하나의 값이 아니라 여러 축의 묶음" 이라는 감각이다.
결함이란 무엇인가
결함(Defect/Bug)은 소프트웨어가 기대한 대로 동작하지 않는 상태를 가리킨다. 다만 "기대"의 기준이 항상 명확한 건 아니다.
| 유형 | 설명 | 예시 |
|---|---|---|
| 명세 위반 | 문서에 적힌 것과 다르게 동작 | 요구사항: "이메일 형식만 허용" → 실제: 아무 문자열이나 통과 |
| 상식적 기대 위반 | 명세엔 없지만 당연히 기대되는 동작을 어김 | 합계 금액이 음수로 표시됨 |
| 이해관계자 간 기대 불일치 | 사람마다 "맞다"의 기준이 다름 | 기획자는 버그라 하고 개발자는 의도된 동작이라 함 |
세 번째 유형이 실무에서 가장 많은 갈등을 만든다. 그리고 이 유형은 코드를 고쳐서 해결되지 않는다 — 먼저 합의가 필요하다. 코드부터 고치면 다음 스프린트에 반대편 이해관계자가 "왜 마음대로 바꿨냐"고 되돌리는 일이 생긴다.
이 갈등을 줄이는 방법(수용 기준을 명확히 하는 법)은 모듈 2에서 다룬다. 지금은 "결함은 합의된 기대와의 차이"라는 정의만 가져간다.
왜 "당연히 그렇겠지"가 제일 위험한가
세 유형 중 QA가 가장 놓치기 쉬운 건 두 번째(상식적 기대 위반)다. 이유는 단순하다 — "당연한 것"은 문서에 안 적히기 때문이다. 아무도 "삭제 버튼은 실제로 삭제해야 한다"거나 "합계 금액은 음수가 아니어야 한다"는 걸 요구사항 문서에 쓰지 않는다. 너무 당연해서다.
그런데 바로 그 "너무 당연해서 안 적힌 것"이 코드에서는 종종 빠진다. 개발자가 그 경우를 놓쳤기 때문이 아니라, 애초에 그 경우를 결정해야 한다는 사실 자체를 아무도 인지하지 못했기 때문이다. 그래서 QA가 할 수 있는 가장 값싼 활동 중 하나가 바로 "이건 문서에 없지만, 당연히 이래야 하지 않나요?"를 소리 내어 묻는 것이다. 이 질문은 공짜에 가깝고, 답이 "네, 당연하죠"로 끝나도 손해가 없다 — 반대로 "어, 그러네요, 생각 안 해봤네요"가 나오면 결함 하나를 코드가 생기기도 전에 잡은 것이다.
비슷한 단어들 — 버그·결함·이슈·인시던트
실무에서 섞여 쓰이지만 문맥이 다르다. 대화가 어긋나는 걸 막으려면 구분해두는 게 좋다.
| 단어 | 주로 쓰이는 맥락 |
|---|---|
| 버그(Bug) | 일상 대화. 가장 넓고 느슨하게 쓰인다 |
| 결함(Defect/Fault) | 공식 문서·표준. 산출물에 남아 있는 잘못된 부분 |
| 이슈(Issue) | 이슈 트래커(할 일과 결함을 등록해 두는 웹 도구)에 등록된 항목 전반. 결함이 아닌 것도 포함(기능 요청, 질문, 개선 제안) |
| 인시던트(Incident) | 운영 중 실제로 발생한 사건. 원인이 결함일 수도, 설정 실수나 외부 장애일 수도 있다 |
"이슈 300건"이라는 말에 결함만 있는 게 아니라는 점이 특히 중요하다. 품질 지표를 보고할 때 이걸 섞으면 숫자가 사실을 왜곡한다(모듈 6에서 다룬다).
품질에 드는 돈은 두 종류다 — 막는 돈과 치르는 돈
"테스트에 돈과 시간을 쓴다"고 하면 흔히 비용으로만 느껴진다. 하지만 품질에 드는 돈을 나눠보면 그림이 달라진다.
| 종류 | 무엇에 쓰는 돈인가 | 예시 |
|---|---|---|
| 예방 비용 | 결함이 애초에 생기지 않게 막는 데 | 요구사항 리뷰, 코딩 표준, 팀 교육 |
| 평가 비용 | 결함이 있는지 찾아내는 데 | 테스트 설계·실행, 코드 리뷰, 정적 분석 |
| 내부 실패 비용 | 릴리즈 전에 발견된 결함을 고치는 데 | 재작업, 재테스트 |
| 외부 실패 비용 | 릴리즈 후에 발견된 결함을 처리하는 데 | 핫픽스, 고객 응대, 환불, 신뢰 손상 |
표에 처음 나온 말 셋만 짚고 가자. 코드 리뷰 는 다른 개발자가 고친 코드를 사람이 읽어 보는 일이고, 정적 분석 은 프로그램을 돌리지 않고 코드만 기계가 훑어 위험한 부분을 찾는 일이다. 커밋 은 코드를 고친 묶음 하나를 가리킨다 — "커밋 하나 수정" 은 "고친 덩어리 하나만 손보면 끝" 이라는 뜻이다.
앞의 두 줄(예방·평가)은 의도적으로 쓰는 돈이고, 뒤의 두 줄(내부·외부 실패)은 어쩔 수 없이 치르는 돈이다. 핵심은 앞에 쓰는 돈이 뒤에 치르는 돈을 줄인다는 것이다 — 그리고 뒤로 갈수록(외부 실패) 같은 결함이라도 액수가 훨씬 커진다. "테스트 예산을 줄이자"는 요청은 사실 "예방·평가에 쓸 돈을 줄이고, 대신 나중에 실패 비용을 더 치르겠다"는 결정과 같다. 이렇게 바꿔 말하면 그 요청이 진짜 무엇을 뜻하는지가 분명해진다.
이 네 가지 분류는 "품질 비용(Cost of Quality)"이라는 이름으로 불리며, ISTQB 실러버스를 비롯한 여러 표준 교재에 등장하는 정식 개념이다. 나중에 국제 자격증 (ISTQB Foundation Level 등)을 준비하게 된다면 이 표가 그대로 시험 범위에 나온다 — 지금 이해해두면 나중에 용어만 확인하면 되는 수준이 된다. ISTQB 자격증 체계 자체(Foundation → Advanced → Expert로 이어지는 단계와, Core·Agile· Specialist로 갈리는 트랙)는 이 사이트의 별도 자격증 로드맵에서 다룬다 — 지금은 "이 커리큘럼에서 배우는 개념들이 실제 국제 자격증의 시험 범위와 맞닿아 있다"는 것만 가져가면 충분하다.
왜 일찍 찾을수록 싼가
같은 결함이라도 발견 시점에 따라 수정 비용이 크게 달라진다. 이유는 단순하다 — 늦게 발견될수록 그 결함 위에 다른 코드와 결정이 쌓여 있기 때문이다.
| 발견 시점 | 무엇이 드는가 |
|---|---|
| 요구사항 리뷰 단계 | 문서 한 줄 수정 |
| 개발 중 (코드 리뷰) | 커밋 하나 수정 |
| 테스트 단계 | 결함 리포트 작성 → 재작업 → 재테스트 |
| 릴리즈 후 (운영) | 핫픽스 배포, 고객 대응, 신뢰 손상, 경우에 따라 데이터 복구 |
"쌓인다"는 게 정확히 무슨 뜻인지 하나씩 보면 이해가 빠르다. 요구사항 단계의 결함이 운영까지 살아남았다면, 그 사이에 이런 것들이 그 위에 얹혀 있다.
- 설계 결정 — 잘못된 요구사항을 전제로 아키텍처(전체 구조를 어떻게 짤지의 큰 결정)가 정해졌다
- 코드 — 그 설계를 따라 여러 파일에 흩어져 구현됐다
- 다른 기능 — 그 코드를 호출하는 다른 기능들이 생겼다
- 테스트 케이스 — 잘못된 동작을 "정상"으로 검증하는 테스트가 만들어졌다
- 문서·교육 자료 — 그 동작을 설명하는 매뉴얼이 배포됐다
- 실제 데이터 — 잘못된 로직으로 생성된 데이터가 DB에 쌓였다
6번이 특히 무섭다. 코드는 고치면 되지만 이미 잘못 저장된 데이터는 따로 복구해야 한다. 이 복구 작업이 원래 수정보다 몇 배 큰 경우가 흔하다.
이 비대칭이 왜 QA가 "테스트 단계에서 버그를 잡는 사람"에 머물지 않고, 요구사항 리뷰 같은 상위 활동에도 참여해야 하는가의 근거다. 테스트를 뒤로 미룰수록 같은 결함을 잡는 비용이 커진다.
다만 이 곡선을 절대 법칙으로 믿지는 말 것
"결함 비용은 단계마다 10배씩 커진다"는 식의 숫자를 자주 보게 되는데, 이건 특정 시대· 특정 프로젝트(기획을 전부 끝낸 뒤에야 개발을 시작하는 "폭포수" 방식의 대형 사업)에서 나온 관측이다. 현대적인 개발 환경에서는 격차가 줄어들기도 한다.
- 하루에도 여러 번 배포하는 조직은 운영 결함을 몇 분 만에 되돌릴 수 있다
- 기능 플래그(기능마다 켜고 끄는 스위치를 미리 심어 두는 것)로 문제 기능만 즉시 꺼버릴 수 있다
- 반면 임베디드 소프트웨어나 의료기기처럼 한 번 나가면 회수가 어려운 분야는 격차가 여전히 극단적으로 크다
그래서 핵심은 "10배"라는 숫자가 아니라 "늦게 발견될수록 대체로 더 많은 것이 얽혀 있다"는 경향, 그리고 "우리 제품은 얼마나 되돌리기 쉬운가"를 스스로 판단하는 것이다. 배포 되돌리기가 쉬운 조직과 어려운 조직은 테스트에 쏟아야 할 노력의 양이 다르다. 이 판단은 모듈 4(리스크 기반 테스트)로 이어진다.
테스트가 막으려는 것의 크기 — 실제 사례
"버그 하나가 뭐 그리 대단한가" 싶을 때 떠올릴 만한 사례들이다.
- Therac-25 (1985~1987): 방사선 치료기의 소프트웨어 결함으로 환자들이 치명적 과다 피폭을 당했다. 특정 순서로 빠르게 입력했을 때만 발생하는 경쟁 조건(두 처리가 동시에 일어나며 순서가 꼬이는 문제)이었다 — 정상 속도로 조작하는 테스트로는 절대 재현되지 않는 종류의 결함.
- Ariane 5 (1996): 발사 37초 만에 폭발. 이전 기종(Ariane 4)의 검증된 코드를 재사용했는데, 새 로켓의 더 큰 속도값이 변수 범위를 넘어섰다. "기존에 잘 돌던 코드"가 새 환경에서 실패한 것 — 재사용 코드도 새 조건에서 다시 테스트해야 한다.
- Knight Capital (2012): 배포 실수로 8대 서버 중 1대에 옛 코드가 남았고, 45분 만에 약 4.4억 달러를 잃었다. 코드 자체보다 배포 과정의 결함이었다.
세 사례가 각각 다른 교훈을 준다 — 순서·타이밍이 만드는 결함(모듈 5 탐색적 테스팅), 환경이 바뀌면 재검증해야 한다는 것(모듈 4), 배포 파이프라인(코드가 자동으로 빌드·시험· 배포되는 흐름)도 테스트 대상이라는 것 (모듈 14). 이 커리큘럼이 왜 이렇게 여러 갈래로 뻗어 있는지의 답이기도 하다.
실무에서 왜 필요한가
"품질은 QA 담당"이라는 생각이 실무에서 가장 흔한 착각이다. 결제 시스템에서 이중 결제가 발생하는 결함을 예로 들어본다. 이 결함이 요구사항 리뷰 단계에서 "동시 요청 처리" 조건이 빠진 걸 발견했다면 문서 한 줄을 고치면 끝난다. 하지만 실제 운영 중에 발견된다면 이미 여러 고객이 이중 결제를 겪었고, 환불 처리와 고객 대응, 그리고 "이 서비스는 결제가 불안하다"는 신뢰 손상까지 함께 온다. 같은 결함, 완전히 다른 비용이다.
그래서 실무에서 QA는 "다 만들어진 뒤 검사하는 사람"이 아니라 기획·설계 단계부터 "이 조건, 확인했나요?"를 묻는 사람에 가깝다. 구체적으로는 이런 질문들이다.
- "이 기능, 실패하면 사용자에게 뭐라고 보이나요?"
- "동시에 두 번 누르면요?"
- "이 값이 없을 때는 어떻게 되나요?"
- "기존에 이걸 쓰던 데이터는 어떻게 되나요?"
이 질문들은 코드가 한 줄도 없을 때 던질 수 있고, 그때 던지는 게 가장 싸다. 요구사항 단계에서 이 질문을 언제 어떻게 던지는지는 모듈 2에서 구체적으로 다룬다.
한 가지 더 — 테스트는 비용이 아니라 정보를 사는 일이다. "테스트에 얼마를 쓸 것인가"는 "얼마나 확신을 갖고 릴리즈할 것인가"와 같은 질문이다. 테스트를 줄이면 돈을 아끼는 게 아니라 불확실성을 그대로 안고 나가는 것이다. 이 관점이 있으면 "테스트 기간을 줄여달라"는 요청에 "그러면 어느 영역의 확신을 포기할지 같이 정하시죠"라고 답할 수 있다.