규모 추정은 자릿수를 맞추는 일이다
한 줄 요약
용량 산정의 목적은 정확한 숫자가 아니라 자릿수를 맞추는 것이다. 인스턴스 3대가 필요한지 30대가 필요한지가 갈리면 설계 전체가 달라진다.
왜 이게 필요했나
시스템 설계는 네 단계로 진행된다. 요구사항 명확화 → 규모 추정 → 고수준 설계 → 상세 설계(병목 파악과 해결). 두 번째 단계를 건너뛰면 나머지가 전부 공상이 된다.
간단한 예를 보자. 쓰기가 하루 1억 건이면 QPS 는 약 1,160 이다(1억 ÷ 86,400). 읽기가 그 10배면 QPS 약 11,600 이다. 5년치 1,800억 건에 레코드당 500바이트를 곱하면 약 90TB 다. 이 세 숫자가 나오면 "단일 인스턴스로 충분한가", "샤딩이 필요한가", "캐시 없이 가능한가" 같은 질문에 근거를 갖고 답할 수 있다.
어떻게 동작하나
측정에서 대수로 가는 길에는 두 개의 안전장치가 있다.
첫째는 헤드룸이다. 측정된 최대 처리량을 그대로 쓰면 안 된다. 안전 처리량은 측정값의 70% 정도로 잡는다. 나머지 30% 는 트래픽 변동, 배포 중 인스턴스 감소, 예상치 못한 느린 요청을 위한 자리다. 인스턴스당 190 RPS 를 측정했다면 안전 처리량은 133 RPS 다.
둘째는 올림이다. 목표 300 RPS 를 133 으로 나누면 2.25 대가 나오는데, 2대로는 부족하므로 3대다. 용량 계산에서 소수점 아래를 버리면 그 순간 계획은 실패한다.
풀 사이징에서도 같은 사고가 필요하다. 인스턴스 하나의 권장 풀 크기를 60 으로 정했다면 반드시 함대 단위로 곱해 본다. 인스턴스 40대 × 60 = 2,400 연결인데 데이터베이스의 max_connections 가 200 이라면, 각 인스턴스의 계산은 모두 옳았지만 시스템은 배포 직후 죽는다. 로컬 최적이 전역 최적이 아닌 전형적인 사례다.
현장에서 만나는 모습
용량 문서에서 가장 흔한 결함은 조건이 없다는 것이다. "우리 서비스는 초당 500건을 처리한다"는 문장에는 동시성도, p95 도, 에러율도, 측정 시점도 없다. 같은 서비스가 동시성 2에서는 p95 20ms 로 500 RPS 를 내고 동시성 50에서는 p95 900ms 로 520 RPS 를 낸다면, 두 번째 숫자는 용량이 아니라 이미 포화된 상태의 관측값이다.
그래서 용량은 항상 SLA 와 함께 적어야 한다. "p95 200ms 이하, 에러 0 조건에서 인스턴스당 133 RPS" 처럼 써야 다음 사람이 같은 기준으로 재현할 수 있다.
부하 시험의 네 종류
이름을 구분하면 무엇을 재는지가 분명해집니다.
| 종류 | 무엇을 하나 | 무엇을 아나 |
|---|---|---|
| 부하(load) | 예상 트래픽을 유지 | 목표 부하에서 지연·오류율 |
| 스트레스(stress) | 부하를 계속 올린다 | 무너지는 지점과 무너지는 방식 |
| 스파이크(spike) | 갑자기 열 배 | 자동 확장이 따라오는가 |
| 지구력(soak) | 평소 부하로 몇 시간 | 메모리 누수, 연결 누수, 디스크 참 |
스트레스 시험의 값어치는 한계 수치가 아니라 무너지는 방식 입니다. 우아하게 거절하는지(429), 전부 느려지는지, 아니면 죽는지가 설계의 품질을 보여 줍니다. "초당 5,000 요청까지 됩니다" 보다 "5,000 을 넘으면 429 를 내고 4,800 으로 돌아오면 회복합니다" 가 훨씬 쓸모 있는 문장입니다.
지구력 시험을 빠뜨리면 한 시간 뒤에 나타나는 문제 를 놓칩니다. 커넥션 풀이 새는 것, 파일 디스크립터가 쌓이는 것, GC 가 점점 길어지는 것은 5분짜리 시험에서 안 보입니다.
폐 루프와 개 루프
부하 도구가 요청을 만드는 방식이 두 가지고, 결과가 완전히 달라집니다.
폐 루프(closed): 가상 사용자 N 명이 응답을 받아야 다음 요청을 보낸다
→ 서버가 느려지면 부하도 저절로 줄어든다
개 루프(open): 초당 N 건을 서버 상태와 무관하게 보낸다
→ 서버가 느려지면 요청이 쌓인다. 현실에 가깝다
실제 사용자는 개 루프에 가깝습니다. 서버가 느리다고 사람들이 요청을 줄이지 않기 때문입니다. 폐 루프로만 시험하면 "가상 사용자 100명에서 지연 200ms" 같은 좋은 숫자가 나오는데, 실제로는 그 지점에서 이미 무너집니다.
k6 는 constant-arrival-rate, Gatling 은 constantUsersPerSec 로 개 루프를
만듭니다. 자동 확장을 시험하려면 반드시 개 루프 여야 합니다.
조정 누락(coordinated omission)
폐 루프 도구의 더 미묘한 문제입니다. 응답이 늦어지면 그동안 보내지 못한 요청이 아예 측정에 들어가지 않아 p99 가 실제보다 훨씬 좋게 나옵니다.
서버가 10초 멈췄다
폐 루프: 그동안 요청을 안 보냄 → 느린 요청 1건만 기록 → p99 정상
현실: 그동안 요청이 계속 옴 → 수천 건이 10초를 기다림 → p99 폭발
이것을 보정하는 도구(--latency-correction, HdrHistogram 기반)를 쓰거나, 개 루프로
시험합니다. p99 가 의심스럽게 좋으면 이것을 먼저 의심 합니다.
현장 판단의 순서
- 목표 트래픽을 정한다(피크 기준, 평균 아님).
- 인스턴스 하나의 안전 처리량을 SLA 조건에서 측정한다.
- 헤드룸을 반영해 70% 로 낮춘다.
- 나눠서 올림한다.
- 공유 자원(DB 커넥션, 캐시, 큐)의 상한과 곱셈으로 다시 검산한다.
다음 확인에서 볼 것
이 모듈은 실습 없이 개념과 계산을 확인하는 퀴즈로 마칩니다. 앞의 세 모듈에서 만든 기준선·사다리·병목 리포트의 숫자를 평균 QPS, 피크 배수, 헤드룸을 반영한 안전 처리량과 필요한 인스턴스 수로 바꾸는 과정을 검산합니다.