개념
화면이 멀쩡해도 실패했을 수 있다
탐색적 테스팅의 성패는 관찰력에 달려 있다 — 아무리 잘 탐험해도, 이상한 걸 알아채지 못하면 아무 소용이 없다. 그런데 UI는 종종 실패를 숨긴다.
사용자가 "저장" 버튼을 누른다. 화면에 "저장되었습니다" 메시지가 뜬다. 하지만 실제로는 서버가 500 에러를 반환했고, 프론트엔드 코드가 그 에러를 제대로 처리하지 못해 무조건 "성공" 메시지를 띄우게 되어 있었다.
화면만 보면 이 결함은 절대 안 보인다. 화면 뒤에서 실제로 무슨 일이 일어났는지까지 봐야 한다.
이 구조를 한 번 보고 나면 "왜 그런 일이" 가 사라진다.
[화면] "저장되었습니다" ← 사용자가 보는 것
↑
[프론트] 성공 메시지를 띄우는 코드 ← 응답을 제대로 안 보고 있다
↑
[창구 응답] 500 서버 오류 ← 실제로는 실패
↑
[서버] 예외 발생, 로그에 기록사용자가 보는 것은 맨 위 한 줄뿐이다. 아래 세 줄은 보려고 해야 보인다. 그래서 이 레슨은 "무엇을 열어 두고 볼 것인가" 가 전부다.
관찰에는 네 겹이 있다
열어 볼 것을 정리하면 네 겹이 된다. 아래로 갈수록 보기 어렵고, 아래로 갈수록 결함이 조용하다.
| 겹 | 무엇을 보나 | 여기서만 보이는 것 |
|---|---|---|
| 1. 화면 | 글자·색·배치·반응 속도 | 잘못된 안내 문구, 깜빡임, 멈춤 |
| 2. 창구(네트워크) | 요청과 응답의 실제 내용 | 화면 값과 응답 값의 불일치 |
| 3. 저장소 | 실제로 저장된 행과 값 | 화면엔 하나인데 두 건 저장 |
| 4. 기록(로그) | 예외·경고가 쌓이는지 | 아무도 모르게 계속 실패 중 |
1번만 보는 QA 와 4번까지 보는 QA 는 찾는 결함의 종류가 다르다. 전자는 "보이는 것이 틀렸다" 를 찾고, 후자는 "보이는 것이 맞는데 틀렸다" 를 찾는다. 뒤쪽이 사용자에게 훨씬 나쁜 종류다 — 잘못된 줄 모르고 지나가기 때문이다.
3번(저장소)은 모듈 61에서, 4번(기록)은 모듈 14의 관측성에서 더 깊이 다룬다. 여기서는 탐험하는 동안 곁눈질로 본다는 습관을 만드는 것이 목표다.
열어두고 탐험해야 할 것들
- 브라우저 개발자 도구 콘솔: JavaScript 에러, 경고 메시지가 화면에는 안 나타나도 여기엔 찍힌다. 화면이 멈추거나 버튼이 안 먹을 때 가장 먼저 볼 곳이다 — 대개 여기에 이유가 한 줄로 적혀 있다.
- 네트워크 탭: 실제 API 요청과 응답을 확인한다. 화면에 표시된 값과 실제 응답 데이터가 다르다면(예: 화면엔 10% 할인, 응답엔 0% 할인이 왔는데 프론트가 잘못 계산해 표시) 이것도 결함이다.
- 서버·애플리케이션 로그 (접근 가능하다면): 예외, 스택 트레이스가 여기 남는다. 화면엔 아무 문제 없어 보여도 서버 로그엔 에러가 쌓이고 있을 수 있다.
- 다른 화면·다른 계정: 로그에 접근할 수 없을 때의 현실적인 대안이다. 방금 만든 것이 목록 화면·관리자 화면·다른 계정에서도 같게 보이는지 본다. 같은 데이터가 두 군데 이상 보이는 곳이 거의 항상 있고, 그 둘을 맞춰 보는 것만으로 꽤 많은 결함이 드러난다.
네 가지를 다 열어 둘 필요는 없다. 차터에 따라 고른다 — 계산을 보는 세션이면 창구와 저장소를, 화면 동작을 보는 세션이면 콘솔을 주로 본다. 레슨 2에서 차터의 "자원" 칸에 도구를 적으라고 한 이유가 이것이다.
이걸 탐험 내내 습관적으로 곁눈질하는 것이 이 레슨의 핵심 기술이다. 탐험이 끝난 뒤에 확인하는 게 아니라, 액션을 취하는 동시에 계속 확인한다.
무엇을 이상하다고 볼 것인가
"열어 두고 본다" 까지는 쉽다. 어려운 것은 뜬 것 중 무엇이 신호인지 가리는 일이다. 콘솔을 처음 열면 빨간 줄이 수십 개라 전부 무시하게 된다.
가려내는 기준 네 가지가 있다.
하나, 내 행동과 시간이 맞는가. 버튼을 누른 직후에 새로 뜬 것만 본다. 페이지를 열 때부터 있던 것은 일단 제쳐 둔다. 콘솔을 비우고(지우고) 행동 하나를 하는 습관을 들이면 이 판단이 쉬워진다.
둘, 반복되는가. 같은 행동에서 매번 뜨면 구조적인 것이고, 한 번만 떴으면 타이밍 문제일 수 있다. 둘 다 중요하지만 보고하는 방식이 다르다 — 후자는 재현 조건을 더 적어야 한다(레슨 12).
셋, 숫자가 맞는가. 화면의 값과 응답의 값을 눈으로 비교한다. 특히 금액·개수·날짜 세 가지는 습관적으로 맞춰 본다. 이 셋이 어긋나는 결함이 가장 비싸다.
넷, 요청이 몇 번 나갔는가. 버튼 한 번에 요청이 두 번 나가면 그 자체로 결함 후보다. 네트워크 탭에서 줄 수만 세어도 알 수 있고, 중복 결제·중복 가입 같은 큰 사고가 여기서 시작된다.
네 가지 다 보는 법을 배우면 1초 안에 판단된다. 처음에는 느리지만 곧 눈에 익는다.
상태 코드가 200이어도 실패일 수 있다
가장 흔한 함정이다. 응답 상태가 200(성공)이면 넘어가기 쉬운데, 본문 안에 실패가 적혀 있는 경우가 많다.
요청: POST /api/orders
응답: 200 OK
본문: { "success": false, "code": "COUPON_EXPIRED", "orderId": null }이 응답을 받은 화면이 "주문이 완료되었습니다" 를 띄우고 있다면 그게 결함이다. 상태 코드는 "요청이 서버까지 잘 갔다" 를 뜻할 뿐, "일이 성공했다" 를 뜻하지 않는다.
반대 방향도 있다. 사용자에게는 아무 문제가 없어 보이는데 응답이 4xx·5xx 로 오는 경우다. 화면이 실패를 조용히 삼키고 다음에 다시 시도해서 결국 성공한 것일 수 있다. 사용자는 몰라도 서버는 두 번 처리했을 수 있고, 그게 중복 생성으로 이어진다.
그래서 보는 순서를 습관으로 정해 둔다 — 상태 코드 → 본문 → 요청 횟수.
왜 이게 어려운가
이유가 셋 있고, 셋 다 사람의 한계라서 의지로는 안 고쳐진다. 장치를 만들어야 한다.
하나, 주의는 한 곳에만 간다. 화면에서 할인 금액을 확인하는 동안 콘솔은 사실상 안 보인다. 그래서 두 창을 나란히 두고, 중요한 순간에는 손을 멈추고 한 번 훑는 것이 낫다. 동시에 보려 하지 말고 번갈아 본다.
둘, 기대한 것만 보인다. "저장되었습니다" 를 기대하고 눌렀으면 그 글자가 떴다는 것만 확인하고 넘어간다. 그래서 기대를 먼저 적어 두는 것이 도움이 된다 — "이 버튼을 누르면 요청 한 번, 응답 200, 목록에 한 건 추가" 라고 생각하고 누르면 셋 중 하나만 어긋나도 걸린다.
셋, 익숙해지면 안 보인다. 같은 화면을 열 번 보면 눈이 지나친다. 그래서 탐험에서는 일부러 다른 경로로 같은 곳에 간다. 레슨 6의 순서 바꾸기가 관찰에도 도움이 되는 이유다.
화면에 집중하다 보면 콘솔이나 네트워크 탭을 잊기 쉽다. 그래서 의식적으로 "이 액션을 하기 전에 개발자 도구를 열어둔다" 를 탐험 세션 시작 루틴으로 만드는 게 효과적이다. 화면과 콘솔을 나란히 두고 보는 것만으로도 발견하는 결함의 종류가 완전히 달라진다.
사례 — 한 결함이 네 겹을 타고 내려간다
실제로 어떻게 내려가는지 한 건을 끝까지 따라가 보자. 쿠폰을 적용했는데 가끔 할인이 안 된다는 제보다.
1겹 화면. 쿠폰을 적용한다. 할인이 적용된 금액이 보인다. 정상이다. 몇 번 반복해도 정상이다. 여기서 멈추면 "재현 안 됨" 으로 닫힌다.
2겹 창구. 네트워크 탭을 켜고 다시 해 본다. 쿠폰 적용 요청이 나가고 응답에 할인 금액이 온다. 그런데 주문 생성 요청을 보니 할인 금액이 아니라 원래 금액이 실려 있다. 화면은 2겹에서 받은 값을 보여 주고, 주문은 다른 값을 보내고 있었다.
3겹 저장소. 주문 행을 조회한다. 원래 금액으로 저장돼 있다. 화면만 할인 가격이었다. 사용자는 결제 내역을 보기 전까지 모른다.
4겹 기록. 서버 로그를 본다. 같은 시각에 경고가 하나 찍혀 있다 — 쿠폰 정보를 주문에 붙이는 단계에서 값을 못 찾아 기본값을 썼다는 내용이다. 원인이 특정됐다.
여기서 중요한 것은 각 겹이 다른 사실을 알려 준다는 점이다.
| 겹 | 알게 된 것 |
|---|---|
| 화면 | (아무것도) — 멀쩡해 보였다 |
| 창구 | 화면 값과 전송 값이 다르다 |
| 저장소 | 사용자가 실제로 손해를 본다 |
| 기록 | 어디서 끊겼는지 |
1겹만 봤으면 "재현 안 됨" 이고, 2겹까지 봤으면 "이상한데요" 다. 4겹까지 가면 리포트에 원인 가설이 들어간다. 모듈 9 레슨 1에서 본 "추측을 사실로 바꾸는 것" 이 바로 이 과정이다.
세션 시작 루틴 — 30초
매번 "뭘 열어야 하지" 를 생각하면 그냥 안 열게 된다. 순서를 정해 두고 기계적으로 한다. 30초면 된다.
- 개발자 도구를 연다. 화면 옆에 나란히 둔다(아래에 두면 화면이 좁아진다)
- 콘솔 탭을 비운다. 페이지를 열 때 나는 잡음을 지워 둬야 새 것이 보인다
- 네트워크 탭을 켜고 기록을 시작한다. "로그 보존" 을 켜면 화면이 바뀌어도 기록이 안 지워진다
- 녹화를 켠다(가능하면)
- 세션 노트를 연다
4번과 5번은 선택이지만, 재현 안 되는 것을 만났을 때 둘이 있고 없고가 결과를 가른다. 레슨 12에서 다시 나온다.
반대로 하지 말아야 할 것도 하나 있다. 개발자 도구를 열어 둔 채로만 탐험하면 실제 사용자의 화면 크기와 달라진다. 레이아웃 결함을 놓치게 되므로, 중간에 한 번은 닫고 보는 것이 좋다.
화면 쪽에서도 놓치는 것들
네 겹 중 1번(화면)도 생각보다 많이 놓친다. 눈이 바뀐 곳만 보도록 되어 있기 때문이다.
| 놓치는 것 | 왜 안 보이나 | 보는 법 |
|---|---|---|
| 잠깐 떴다 사라진 오류 | 0.5초면 눈이 못 따라간다 | 녹화해 두고 느리게 돌려 본다 |
| 화면 밖의 변화 | 스크롤 아래는 안 보인다 | 끝까지 내려 확인한다 |
| 버튼이 두 번 눌리는 느낌 | 결과가 같아 보인다 | 요청 횟수를 센다 |
| 글자가 미묘하게 잘림 | 말줄임표가 자연스러워 보인다 | 전체 값과 대조한다 |
| 자릿수·소수점 | 숫자는 모양이 비슷하다 | 소리 내어 읽는다 |
마지막 줄은 농담이 아니다. "일천이백삼십사" 라고 읽으면 1,234 와 12,340 을 구별하게 된다. 눈으로만 보면 비슷한 모양의 숫자는 그냥 통과한다.
녹화도 실무에서 많이 쓴다. 탐험 세션을 화면 녹화해 두면 두 가지가 생긴다 — 잠깐 뜬 것을 다시 볼 수 있고, 재현이 안 될 때 증거가 남는다(레슨 12).
눈이 아니라 비교가 결함을 찾는다
관찰력이 좋다는 말은 눈이 밝다는 뜻이 아니다. 비교할 기준을 들고 본다는 뜻이다. 기준 없이 보면 무엇이든 "그런가 보다" 가 된다.
탐험 중에 쓸 수 있는 기준은 네 가지다.
- 직전과 비교 — 방금 전 화면과 지금이 어떻게 다른가
- 다른 경로와 비교 — 목록에서 본 값과 상세에서 본 값이 같은가
- 다른 겹과 비교 — 화면 값과 응답 값이 같은가(위의 네 겹)
- 기대와 비교 — 상식적으로 이래야 하는데 그런가
2번이 가장 값싸고 자주 통한다. 같은 데이터가 두 군데 이상에 보이는 서비스가 대부분이고, 그 둘이 어긋나는 결함은 흔하다. 목록의 금액과 상세의 금액, 장바구니 개수와 배지 숫자, 알림 수와 실제 목록 길이 — 눈으로 맞춰 보기만 하면 된다.
4번은 모듈 1에서 본 "당연해서 문서에 안 적힌 것" 과 같은 이야기다. 합계가 음수가 되거나, 삭제한 것이 목록에 남거나, 날짜가 미래로 찍히는 것은 어디에도 안 적혀 있지만 전부 결함이다.
관찰은 기록까지가 한 묶음이다
본 것을 안 적으면 30분 뒤에 사라진다. 특히 아래 겹에서 본 것은 기억으로 재현이 안 된다 — 응답 본문의 코드 이름이나 로그의 예외 문구를 외우고 있을 수 없기 때문이다.
탐험 중에는 길게 적지 않는다. 네 가지만 집는다.
| 집는 것 | 형태 |
|---|---|
| 시각 | 14:32 — 로그를 나중에 찾을 열쇠 |
| 무엇을 했나 | 쿠폰 A 적용 후 주문 — 한 줄 |
| 어느 겹에서 이상했나 | 주문 요청 본문에 원래 금액 |
| 증거 | 캡처 또는 복사한 응답 한 덩어리 |
세 번째가 핵심이다. "이상함" 만 적으면 나중에 다시 재현해야 하고, "어느 겹" 이 적혀 있으면 바로 그 겹부터 다시 본다.
증거는 되도록 글자로 남긴다. 화면 사진보다 복사한 응답 본문이 쓸모가 많다 — 검색이 되고, 리포트에 그대로 붙일 수 있고, 개발자가 코드에서 그 문자열을 바로 찾을 수 있다.
실무에서 왜 필요한가
"화면은 성공했다고 표시하지만 실제로는 실패한" 패턴은 실무에서 놀랍도록 흔하다 — 프론트엔드가 에러 처리를 제대로 안 했거나, 성공/실패를 판단하는 로직 자체에 결함이 있는 경우다. 이런 결함은 사용자에게 "잘 됐다고 나왔는데 나중에 보니 안 됐더라"는 최악의 경험을 준다. 화면만 보는 QA는 이걸 절대 못 잡는다. 이 습관은 모듈 9(HTTP·DOM 기초)와 모듈 14(관측성)에서 다룰 내용의 실전 버전이기도 하다.
그리고 이 역량은 탐색적 테스팅 밖에서도 그대로 쓰인다. 스크립트 테스트를 실행할 때도, 자동화가 실패했을 때 원인을 가를 때도, 운영 중 장애를 확인할 때도 같은 네 겹을 내려간다. 사실상 QA 가 "확인했다" 고 말할 수 있는 범위를 정하는 능력이고, 그래서 이 레슨은 이 모듈 안에서보다 바깥에서 더 많이 쓰이게 된다.
반대로 이 습관이 없으면 생기는 일도 분명하다. "화면은 멀쩡했습니다" 가 곧 "확인했습니다" 가 된다. 그 상태로 넘어간 결함이 운영에서 터지면, 테스트를 안 한 것과 결과가 같다.
잡음이 너무 많을 때
실제 서비스의 콘솔과 로그는 깨끗하지 않다. 광고·분석 도구가 뱉는 경고, 외부 서비스의 오류, 개발 중 남은 메시지가 섞여 있다. 전부 보려 하면 아무것도 못 본다.
세 가지로 줄인다.
하나, 도메인으로 거른다. 네트워크 탭과 콘솔 모두 우리 서비스 주소의 것만 필터링할 수 있다. 외부 분석 도구의 경고는 대개 우리가 손댈 것이 아니다.
둘, 기준선을 먼저 잡는다. 아무것도 안 한 상태에서 페이지를 열고 콘솔에 무엇이 뜨는지 본다. 그게 평상시 잡음이다. 탐험 중에 뜨는 것은 그것과 비교한다.
셋, 심각도로 자른다. 콘솔은 오류만, 네트워크는 4xx·5xx 만 먼저 본다. 경고는 반복될 때만 본다 — 한 번 뜬 경고를 쫓다 보면 시간이 다 간다.
여기서 QA 가 자주 하는 좋은 일이 하나 있다. "이 경고는 무시해도 되는 것인가" 를 한 번 물어보는 것이다. 팀에서 아무도 안 보던 경고가 사실은 의미 있는 신호인 경우가 종종 있고, 아니라면 잡음을 줄이자는 제안이 된다. 잡음이 줄면 다음 사람이 신호를 더 잘 본다.
도구를 못 쓰는 환경이라면
모든 상황에서 개발자 도구를 열 수 있는 것은 아니다. 휴대전화 앱, 설치형 프로그램, 보안 때문에 접근이 막힌 환경. 그때도 네 겹의 발상은 그대로 쓴다 — 보는 방법만 바뀐다.
| 상황 | 대안 |
|---|---|
| 휴대전화 앱 | 중간에서 통신을 들여다보는 도구(모듈 9 레슨 10·모듈 19) |
| 통신을 못 볼 때 | 다른 화면에서 같은 데이터를 조회해 대조한다 |
| 저장소 접근 불가 | 관리자 화면·다른 계정·목록 화면으로 간접 확인 |
| 로그 접근 불가 | 운영팀에 시각을 찍어 요청한다. "14:32 에 가입 시도" |
마지막 줄이 실무에서 자주 쓰인다. 로그를 직접 못 보더라도 정확한 시각과 입력값을 적어 두면 운영팀이 찾아 줄 수 있다. 그래서 세션 노트에 시각을 남기는 습관이 여기서도 값을 한다.
채용시장에서의 위치
이 역량은 면접에서 "그래서 어떻게 알아내셨어요?" 라는 형태로 확인된다. 같은 결함을 찾았어도 답이 다르면 다르게 평가된다.
- "눌러 보다가 이상해서요" — 운이 좋았던 것으로 읽힌다
- "화면은 성공인데 응답 본문에 실패가 와 있어서, 저장소를 보니 행이 없었습니다" — 방법을 가진 사람으로 읽힌다
뒤쪽 답을 할 수 있는 사람은 결함 리포트의 질도 다르다. 그래서 경력 QA 공고에 "로그 분석", "API 응답 확인", "개발자 도구 활용" 같은 문구가 자주 들어간다. 전부 이 레슨의 네 겹을 다른 말로 적은 것이다.
한 가지 더. 이 역량은 개발자와의 대화를 바꾼다. "안 돼요" 로 시작하는 대화와 "이 요청이 500 을 반환합니다" 로 시작하는 대화는 그 뒤가 완전히 다르게 흘러간다. 모듈 6 레슨 3의 비난 없는 결함 커뮤니케이션이 실제로 가능해지는 지점이기도 하다.