개념
기기 내장 기능으로는 못 하는 것
레슨 3의 방법에는 공통된 한계가 있다. 전부 아니면 전무 라는 점이다. NLC를 켜면 기기의 모든 통신이 느려진다. Android 속도 제한도 마찬가지다.
그런데 실무에서 자주 필요한 건 이런 것이다.
"결제 승인 API만 5초 느리게 하고 나머지는 정상으로 두고 싶다"
"상품 목록은 정상인데 이미지 CDN만 느린 상황을 만들고 싶다"
"이 API가 500을 반환하면 화면이 어떻게 되는지 보고 싶다"
"응답은 오는데 본문이 잘려서 오는 상황을 만들고 싶다"원인을 격리하려면 조건도 격리할 수 있어야 한다. 전체를 느리게 하면 어느 호출 때문에 화면이 멈췄는지 알 수 없다. 프록시 스로틀링이 이 자리를 채운다.
구성 — 폰 트래픽을 PC로 우회시킨다
레슨 2에서 "PC를 통과하는 트래픽은 PC 도구가 못 본다"고 했는데, 프록시는 예외다. 핫스팟처럼 '통과'시키는 게 아니라, 폰이 명시적으로 PC를 목적지로 삼아 요청을 보내기 때문 이다. 계층 문제가 발생하지 않는다.
1. PC와 폰을 같은 Wi-Fi에 연결한다
2. PC에서 프록시를 실행한다 (기본 포트 8888)
3. 폰의 Wi-Fi 고급 설정 > 프록시 > 수동
호스트: PC의 IP, 포트: 8888
4. HTTPS 검사가 필요하면 루트 인증서를 설치한다
(브라우저로 프록시 인증서 배포 주소 접속 → 설치 → 신뢰 설정)
5. Throttle 설정을 켜고 테스트를 시작한다4단계가 중요하다. 인증서를 설치하지 않으면 HTTPS 트래픽은 내용이 보이지 않고, 많은 도구에서 제어도 제한된다. 그리고 이 인증서는 테스트가 끝나면 반드시 제거해야 한다 — 남겨두면 그 기기의 모든 HTTPS 통신을 누군가 가로챌 수 있는 상태가 된다.
도구 비교
| 도구 | 비용 | 특징 |
|---|---|---|
| Charles Proxy | 유료 (평가판 제공) | Throttle Settings에 3G·56kbps 등 프리셋 내장. 국내 QA 사용 사례가 많아 정보를 구하기 쉽다 |
| Proxyman | 무료 · 유료 | macOS·Windows 지원. 최신 UI, 요청별 지연과 응답 조작이 편하다 |
| mitmproxy | 무료 | 명령행 기반. 스크립트로 지연·오류 주입을 자동화 할 수 있어 회귀에 붙이기 좋다 |
| Fiddler Classic | 무료 | Windows 환경. 모뎀 속도 흉내와 사용자 규칙 지원 |
선택 기준은 단순하다. GUI로 손으로 조작할 것인가, 스크립트로 반복할 것인가. 탐색적으로 이것저것 해볼 때는 Charles·Proxyman이 빠르고, 회귀에 넣어 매번 같은 조건을 만들 거라면 mitmproxy가 맞다.
이 방법의 진짜 가치 — 호스트별 제어와 오류 주입
대역폭·지연을 거는 것만으로는 레슨 5(tc netem)를 이길 수 없다. 프록시의 고유한 가치는 다른 데 있다.
① 호스트·경로별 조건 차등
api.example.com/payments/* → 지연 5,000 ms
cdn.example.com/* → 대역폭 50 kbps
그 외 → 정상이렇게 걸어두면 "결제만 느릴 때"와 "이미지만 느릴 때"의 화면이 각각 어떻게 되는지 분리해서 볼 수 있다. 결함 원인을 좁힐 때 결정적이다.
② 응답 조작 — 저하 테스트를 넘어선다
| 조작 | 확인하는 것 |
|---|---|
| 상태 코드 변경 (200 → 500, 503, 429) | 서버 오류 시 화면과 재시도 동작 |
| 응답 지연 후 정상 반환 | 타임아웃 직전 도착 시 처리 |
| 응답 본문 잘라내기 | 파싱 실패 시 앱이 죽는가 |
| 빈 본문 / 잘못된 JSON | 방어 코드가 있는가 |
| 연결 중 끊기 (reset) | 네트워크 예외 경로 |
Retry-After 헤더 부착 | 클라이언트가 이 헤더를 존중하는가 |
429 + Retry-After 조합은 특히 자주 빠진다. 서버가 "3초 뒤에 다시
오라"고 알려줬는데 클라이언트가 무시하고 즉시 재시도하면, 장애 상황에서
서버를 더 밀어붙이게 된다. 레슨 7에서 자세히 다룬다.
③ 조건부 실패 — 특정 횟수만 실패시키기
mitmproxy 스크립트로 "이 API는 처음 두 번 실패하고 세 번째에 성공" 같은 조건을 만들 수 있다. 재시도 로직이 실제로 동작하는지 확인하는 가장 정확한 방법이다.
# mitmproxy 스크립트 골격 — 처음 2회는 503, 이후 정상
count = 0
def request(flow):
global count
if "/api/orders" in flow.request.pretty_url:
count += 1
if count <= 2:
flow.response = http.Response.make(
503, b'{"error":"unavailable"}',
{"Content-Type": "application/json",
"Retry-After": "2"}
)한계 ① — 인증서 피닝
앱이 인증서 피닝(certificate pinning) 을 적용했다면, 프록시의 루트 인증서를 신뢰하지 않는다. 앱은 연결을 거부하고, 프록시에는 아무것도 잡히지 않는다.
증상: 브라우저는 프록시를 통과하는데 앱만 통신이 안 된다
→ 피닝을 의심한다대응은 셋이다.
- 디버그 빌드에서 피닝을 끈다 — 가장 정상적인 방법. 개발과 협의해 디버그 빌드에 피닝 예외를 넣는다
- 피닝 우회 도구를 쓴다 — 루팅·탈옥이 필요하고 사내 정책과 충돌할 수 있다
- 프록시를 포기하고 레슨 5로 간다 — tc netem은 TLS 계층 아래에서 동작하므로 피닝과 무관하다
1번을 요청할 수 있는 관계를 만들어두는 것 이 QA 입장에서 가장 값싸다.
한계 ② — QUIC / HTTP/3
이게 요즘 더 큰 문제다. 많은 서비스가 HTTP/3(QUIC) 를 쓰는데, QUIC은 TCP가 아니라 UDP 위에서 동작 한다. HTTP 프록시는 이 트래픽을 잡지 못한다.
증상: 일부 요청만 프록시에 잡히고 나머지는 안 잡힌다
→ HTTP/3로 붙고 있을 가능성이 높다확인과 대응:
- 프록시 세션 목록에 예상한 요청이 전부 있는지 센다. 빠진 게 있으면 의심
- 테스트 중에는 서버·클라이언트에서 HTTP/3를 비활성화하고 HTTP/2로 내려 붙이게 하는 방법이 있다(개발과 협의 필요)
- 또는 레슨 5의 tc netem으로 간다. UDP도 똑같이 제어된다
QUIC이 저하 테스트 결과를 바꾼다
단순히 "안 잡힌다"가 아니라, 결과 해석 자체가 달라진다는 점 이 중요하다.
TCP 기반 HTTP/2에서는 하나의 패킷이 손실되면 그 연결의 모든 스트림이 함께 멈춘다 (전송 계층 head-of-line blocking). 반면 HTTP/3에서는 손실된 스트림만 멈추고 나머지는 계속 흐른다.
실측에서도 이 차이가 크게 나타난다. 패킷 손실 3% 조건에서 HTTP/3의 p99 페이지 완료 시간이 1.1초, HTTP/2가 2.4초 로 보고된 사례가 있다. 꼬리 지연에서 절반 수준이다.
QA에게 이게 주는 결론은 둘이다.
- 손실 조건 테스트 결과를 프로토콜과 함께 기록한다. "손실 5%에서 3초"는 HTTP/2인지 HTTP/3인지에 따라 전혀 다른 의미다
- 프로토콜이 바뀌는 변경(HTTP/3 도입 등)은 네트워크 저하 회귀를 다시 돌려야 하는 변경이다. 기능은 그대로인데 저하 특성이 달라진다
한계 ③ — 소켓·비 HTTP 트래픽
WebSocket 초기 핸드셰이크는 HTTP라 잡히지만, 이후의 프레임은 도구에 따라 제어가 제한적이다. 게임·실시간 통신의 커스텀 UDP 프로토콜은 아예 대상이 아니다.
실시간 기능이 핵심인 제품이라면 프록시는 부분 해법 이라고 보는 편이 정확하다.
실무에서 왜 필요한가
원인 격리가 된다
"주문 화면이 느리다"는 제보를 받았을 때, 전체를 느리게 하면 "느리네요"로 끝난다. 호스트별로 차등을 주면 어느 호출이 병목인지 가 드러난다.
실험 1: 결제 API만 지연 → 화면 멈춤 재현 ✅
실험 2: 이미지 CDN만 지연 → 재현 안 됨
→ 원인은 결제 API 대기. 개발에 넘길 때 근거가 명확하다서버 없이 오류 경로를 테스트한다
500·503·429 응답에서 화면이 어떻게 되는지 보려면 원래는 서버를 죽이거나 개발 환경을 만져야 한다. 프록시로는 클릭 몇 번이다. QA가 개발에 의존하지 않고 독립적으로 검증할 수 있는 범위가 넓어진다.
이건 모듈 12(API·계약 테스트)의 사고방식과 이어진다. 계약을 위반하는 응답을 만들어 클라이언트의 방어를 확인하는 것이다.
자동화에 넣을 수 있다
mitmproxy 스크립트는 CI에 붙일 수 있다. "재시도 3회 후 성공" 같은 시나리오를 매 빌드마다 자동으로 확인하게 만들 수 있다. 레슨 8에서 자동화 전체 그림을 다룬다.