본문으로 건너뛰기
중급약 24분

네트워크 상태 모델 — 무엇을 느림이라 부르고 무엇을 사용 불가로 판정할 것인가

네트워크 상태를 정상·저하·Limited Service·단절 네 단계로 정의하고, 대역폭·지연·지터·손실 4축으로 수치화한다. 비대칭과 버퍼블로트처럼 흔히 빠뜨리는 축까지 포함해 팀 공통 기준을 만든다.

  • #네트워크테스트
  • #상태정의
  • #지연
  • #패킷손실
  • #지터
  • #버퍼블로트

개념

기준이 없으면 결함이 닫힌다

"네트워크 느릴 때 앱이 이상해요."

이 문장만 적힌 결함 리포트는 거의 예외 없이 재현 불가로 닫힌다. 느리다는 게 얼마나 느린 건지, 지연이 문제인지 손실이 문제인지, 아예 끊긴 건지 연결은 되어 있었는지가 없기 때문이다. 개발자는 자기 자리에서 정상 속도로 열어보고 "잘 되는데요"라고 답한다.

그래서 이 모듈의 첫 레슨은 도구가 아니라 용어 합의 다. 팀이 같은 단어로 같은 상태를 가리킬 수 있어야 그다음이 있다.

네트워크 상태 4단계

모바일 서비스 기준의 실무 기준값이다. 절대적인 수치는 아니지만, 팀이 이 표를 벽에 붙여두고 같은 이름을 쓰기 시작하는 순간 결함 리포트의 품질이 달라진다.

상태체감다운로드 대역폭응답 지연(RTT)패킷 손실테스트 목적
정상지연 없음30 Mbps 이상0 ~ 60 ms0 %기본 성능 기준선 확보
저하 (느림)눈에 띄는 대기1 ~ 10 Mbps100 ~ 300 ms0.5 ~ 5 %로딩 표시·타임아웃 정책 검증
사용 불가 (Limited)연결은 되나 실패50 ~ 200 kbps1,000 ms 이상20 ~ 50 %재시도·부분 로딩·오류 안내 검증
단절연결 없음0응답 없음100 %오프라인 처리 경로 검증

전통적으로 QA 가이드는 Ping 값만으로 기준을 잡아왔다 — 정상 0~60ms, 눈에 띄는 딜레이 100ms 이상, 제품 사용 불가 170ms 이상. 이 기준은 여전히 유효하지만 한 축뿐이다. 여기에 대역폭과 패킷 손실 축을 더해야 비로소 '연결은 되었으나 사용 불가'가 독립된 상태로 분리된다.

Limited Service를 왜 따로 세우는가

네 상태 중 실무에서 가장 많은 사고가 나는데 가장 적게 테스트되는 것이 Limited Service 다.

단절                          Limited Service
────────────────             ─────────────────────────
소켓이 즉시 실패한다            TCP 연결은 성립한다
OS가 오프라인을 알려준다        OS는 "연결됨"이라고 말한다
앱이 오프라인 분기를 탄다        앱은 정상 경로를 탄 채로 기다린다
                             → 타임아웃까지 무한 스피너
                             → 재시도가 폭주한다
                             → 사용자는 버튼을 연타한다

앱 입장에서 단절은 오히려 쉽다. 명확한 실패 신호가 즉시 오기 때문이다. Limited Service는 신호가 애매한 채로 오래 끌기 때문에 어렵고, 그래서 중복 결제·중복 주문 같은 비싼 사고가 여기서 나온다.

지하철 환승 구간, 엘리베이터, 지하주차장 입구, 공연장, 혼잡한 카페 와이파이 — 사용자가 실제로 자주 겪는 상태가 정확히 이것이다.

네트워크 품질의 4축

상태를 수치로 말하려면 축이 필요하다. 흔히 대역폭 하나만 생각하지만 실제로는 넷이다.

① 대역폭 (bandwidth)   초당 얼마나 많이 옮기는가
                       → 큰 파일·이미지·영상에 영향
                       → 작은 API 호출에는 거의 영향 없음
 
② 지연 (latency, RTT)  한 번 왕복에 얼마나 걸리는가
                       → API 호출 수가 많을수록 치명적
                       → 순차 호출 5개 × 300ms = 1.5초
 
③ 지터 (jitter)        지연이 얼마나 들쭉날쭉한가
                       → 평균은 같아도 체감이 완전히 다르다
                       → 실시간(통화·게임·스트리밍)에 치명적
 
④ 손실 (packet loss)   패킷이 얼마나 사라지는가
                       → 재전송 유발 → 지연 폭증
                       → TCP에서는 손실 1%가 체감 속도를 크게 깎는다

③ 지터가 실무에서 가장 자주 빠진다. 많은 테스트 조건표가 대역폭·지연· 손실 세 칸만 갖고 있다. 그런데 평균 지연 150ms로 안정된 회선과, 평균은 같지만 50ms와 400ms를 오가는 회선은 사용자 체감이 전혀 다르다. 후자에서는 애니메이션이 끊기고, 스트리밍 버퍼가 마르고, 재생이 멈춘다.

지터를 조건에 넣는 방법은 간단하다. tc netem에서 지연 뒤에 편차를 한 칸 더 적으면 된다(레슨 5에서 다룬다).

흔히 빠지는 축 ① — 상·하향 비대칭

조건표를 만들 때 업로드와 다운로드에 같은 값을 넣는 실수 가 매우 흔하다. 실제 모바일 회선은 비대칭이다. 다운로드는 쓸 만한데 업로드가 형편없는 경우가 훨씬 많다.

이게 왜 중요한가:

  • 사진·영상 업로드, 파일 첨부, 로그 전송이 업로드 경로를 탄다
  • 요청 본문이 큰 API (폼 제출, 이미지 포함 게시글)도 업로드 영향을 받는다
  • 업로드가 막히면 화면은 "전송 중"에서 멈추는데, 다운로드 속도만 측정하면 정상으로 보인다
전형적인 실제 조건 (다운로드 ≠ 업로드)
  4G 혼잡      다운 5 Mbps  / 업로드 0.5 Mbps
  지하철 이동   다운 2 Mbps  / 업로드 0.2 Mbps
  공용 와이파이 다운 10 Mbps / 업로드 0.3 Mbps

업로드 경로를 가진 기능이 있다면 비대칭 조건을 최소 하나는 반드시 넣는다. 대칭 조건만으로 테스트하면 업로드 결함이 통째로 빠진다.

흔히 빠지는 축 ② — 부하 중 응답성(버퍼블로트)

속도 측정 앱은 대개 아무것도 안 하는 상태에서 속도를 잰다. 그런데 사용자의 실제 상황은 다르다. 영상이 백그라운드로 다운로드되는 중에 버튼을 누른다. 사진이 업로드되는 중에 목록을 새로고침한다.

이때 나타나는 현상이 버퍼블로트(bufferbloat) 다. 회선이 포화되면 중간 장비의 큐에 패킷이 쌓이고, 대역폭 수치는 그대로인데 지연이 수백 ms에서 수 초까지 치솟는다.

유휴 상태          RTT 30ms,  100Mbps   ← 속도 측정 앱이 보는 값
부하 중 (포화)     RTT 1200ms, 100Mbps  ← 사용자가 실제로 겪는 값
                        ↑
                 대역폭은 안 변했는데 앱은 먹통이 된다

이걸 재는 표준적인 지표가 RPM(Round-trips Per Minute) — 회선을 포화시킨 "작업 부하 상태"에서 1분간 몇 번의 왕복을 처리할 수 있는지를 센다. 값은 대략 100대(나쁨)에서 수천(좋음) 범위다.

macOS·iOS에는 이걸 재는 도구가 내장돼 있다.

networkQuality -v

기본 동작은 다운로드와 업로드를 동시에 포화시키고 그 상태의 응답성을 측정하는 것이라, 영상통화나 음성통화 같은 실사용 상황에 훨씬 가깝다.

QA에게 이게 주는 실용적 결론은 하나다. "속도는 잘 나오는데 앱이 느려요" 라는 제보를 받으면 유휴 속도가 아니라 부하 중 응답성을 의심한다.

상태 정의를 팀 기준으로 만드는 법

표를 만들었다고 기준이 되는 게 아니다. 세 가지가 따라와야 한다.

1. 조건에 이름을 붙인다. 저하-B, Limited-A처럼 짧은 식별자를 정한다. 결함 리포트 제목에 그대로 들어갈 수 있어야 한다.

2. 조건마다 도구 설정값을 못 박는다. "열악"이라는 단어만으로는 사람마다 다르게 설정한다. 레슨 8의 환산표가 이 역할을 한다.

3. 결함 리포트 양식에 조건 칸을 넣는다. 양식에 칸이 없으면 아무도 안 적는다. 칸이 있으면 적는다. 이 작은 변화가 재현율을 크게 바꾼다.

실무에서 왜 필요한가

재현 불가로 닫히는 결함이 줄어든다

[Before]
제목: 느릴 때 주문이 두 번 들어감
내용: 네트워크가 안 좋을 때 가끔 그럽니다
결과: 재현 불가로 종료
 
[After]
제목: [Limited-A] 주문 버튼 연타 시 중복 주문 생성
조건: 다운 100kbps / RTT 1,000ms / 손실 30% (tc netem, 스크립트 limited.sh)
측정: 적용 후 fast.com 0.1Mbps 확인 (스크린샷 첨부)
절차: 장바구니 → 주문하기 3회 연타 → 15초 대기
결과: 주문 3건 생성. 서버 로그상 동일 payload 3건
기대: 멱등키로 1건만 생성되어야 함
결과: 개발자가 30분 만에 원인 특정

조건명과 측정값이 붙는 순간 결함이 살아난다. 이게 이 모듈 전체의 실용적 목표다.

릴리즈 판정 기준이 생긴다

"네트워크 테스트 했나요?"에 "했습니다"로 답하는 것과, "정상·저하· Limited·단절 4개 조건 × 핵심 시나리오 12개 = 48건 중 46건 통과, 미통과 2건은 결함 #481·#482"로 답하는 것은 다르다. 모듈 4에서 배운 종료 조건을 네트워크 축에도 적용할 수 있게 된다.

사용자 제보를 조건으로 번역할 수 있다

"지하철에서만 그래요"라는 제보는 그 자체로는 행동 불가다. 그런데 상태 모델이 있으면 번역이 된다 — 지하철 이동 중은 잦은 핸드오버 + 간헐적 Limited + 높은 지터 조합이다. 그 조합을 조건으로 만들어 재현하면 된다.

실습 과제

과제 1 — 우리 팀의 상태 정의표 만들기

본문의 4단계 표를 출발점으로 삼되, 우리 제품에 맞게 수치를 조정한 표를 만든다. 조정할 때 근거를 함께 적는다.

  • 우리 사용자의 실제 회선 분포는 어떤가 (분석 도구에 데이터가 있다면 확인)
  • 우리 제품에서 "느리다"고 불평이 들어오는 지점은 어디인가
  • 우리가 감당해야 할 최악 조건은 무엇인가

각 상태에 짧은 식별자 를 붙인다.

과제 2 — 4축 민감도 분석

우리 제품의 주요 화면 5개에 대해 4축 중 어느 축에 가장 민감한지 를 표로 정리한다.

화면대역폭지연지터손실가장 민감한 축
상품 목록(이미지 다수)높음중간낮음중간대역폭
로그인낮음높음낮음중간지연
실시간 채팅낮음높음높음높음지터

판단 근거: 그 화면이 호출하는 API 개수와 크기, 순차 호출인지 병렬인지, 실시간성이 필요한지.

이 표가 있으면 화면마다 어떤 조건을 우선 테스트할지가 정해진다.

과제 3 — 업로드 경로 목록화

우리 제품에서 업로드 방향 트래픽이 발생하는 기능 을 전부 나열한다. 사진 첨부, 프로필 이미지, 파일 업로드, 긴 텍스트 제출, 로그·크래시 리포트, 분석 이벤트 전송 등.

각각에 대해 "업로드가 0.2Mbps일 때 화면이 어떻게 되는가"를 적는다. 모르면 그것이 테스트해야 할 목록이다.

과제 4 — 부하 중 응답성 측정

macOS가 있다면 networkQuality -v를 유휴 상태에서 한 번 실행하고, 큰 파일을 다운로드하면서 한 번 더 실행해 값을 비교한다.

macOS가 없다면 대안: 큰 파일 다운로드를 켜둔 채로 다른 창에서 ping 을 돌려 RTT가 얼마나 치솟는지 관찰한다.

ping -c 30 1.1.1.1

유휴 시 RTT와 부하 중 RTT의 차이를 기록한다. 10배 이상 벌어진다면 버퍼블로트가 있는 회선이다.

과제 5 — 제보를 조건으로 번역하기

실제 CS 문의나 사내 제보 문장 3개를 가져와(없으면 아래 예시) 각각을 4단계 상태와 4축 값으로 번역한다.

  • "엘리베이터에서 앱이 멈춰요"
  • "와이파이 잡혀 있는데 아무것도 안 돼요"
  • "사진 올릴 때만 실패해요"

번역 결과에는 반드시 상태 이름 + 4축 수치 가 들어가야 한다.

자가 체크리스트

  • 네트워크 상태 4단계를 이름과 수치 범위로 말할 수 있다
  • Limited Service가 단절과 어떻게 다른지, 왜 더 위험한지 설명할 수 있다
  • 네트워크 품질의 4축을 나열하고 각 축이 어떤 기능에 영향을 주는지 안다
  • 지터가 왜 평균 지연과 별개의 축인지 설명할 수 있다
  • 상·하향 비대칭을 조건에 넣어야 하는 이유를 기능 단위로 설명할 수 있다
  • 버퍼블로트가 무엇이고, 왜 유휴 속도 측정으로는 안 잡히는지 설명할 수 있다
  • RPM이 무엇을 재는 지표인지 알고, 측정 방법을 하나 이상 안다
  • 우리 제품의 화면별로 가장 민감한 축을 판단할 수 있다
  • 결함 리포트에 조건명과 측정값이 왜 필요한지 사례로 설명할 수 있다
  • 사용자 제보 문장을 상태 이름과 4축 수치로 번역할 수 있다

흔한 실수

대역폭만 조건으로 잡는다. "3G 환경"이라고만 적힌 조건표가 흔하다. 지연과 손실이 빠지면 재시도·타임아웃 결함은 절대 안 나온다. 작은 API 호출은 대역폭을 거의 안 쓰기 때문에, 대역폭만 줄여서는 아무 일도 일어나지 않는다.

업로드와 다운로드에 같은 값을 넣는다. 조건표가 대칭이면 업로드 경로 결함이 통째로 빠진다. 실제 회선은 거의 항상 비대칭이다.

지터를 빠뜨린다. 평균 지연만 고정하면 실시간 기능의 끊김을 재현할 수 없다. 조건표에 편차 칸을 하나 더 만든다.

유휴 속도만 측정하고 통과로 본다. 사용자는 아무것도 안 하는 상태에서 앱을 쓰지 않는다. 부하 중 응답성을 함께 본다.

"느림"을 단어로만 정의한다. 열악·나쁨·최악 같은 단어는 사람마다 다르게 해석된다. 수치와 식별자가 붙어야 기준이 된다.

단절만 테스트하고 Limited를 건너뛴다. 비행기 모드로 오프라인 분기만 확인하고 끝낸다. 사고는 대부분 그 사이 상태에서 난다.

참고 자료

낯선 말 풀이

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

RTT — 왕복 시간
요청을 보내고 답이 돌아오기까지 걸린 시간.
QA — 품질보증
만든 것이 쓸 만한지 확인하고, 애초에 덜 망가지게 만드는 방법을 정하는 일. "테스트"는 그 일의 일부다.
API — 응용 프로그램 인터페이스
프로그램끼리 주고받는 창구. 사람이 화면 버튼을 누르는 대신, 프로그램이 정해진 주소로 요청을 보내 답을 받는다.
CS — 고객 지원 · 칩 선택 신호
이 커리큘럼에서 두 가지로 쓰인다. ① 고객 문의와 불만을 직접 받는 조직 ② 여러 부품이 한 선을 나눠 쓸 때 "지금은 네 차례" 라고 하나를 고르는 신호. 앞뒤에 문의·고객이 있으면 ①, 통신·배선 이야기면 ②다.

용어집 전체 보기