본문 바로가기
클라우드

클라우드 시대에도 TPS, CPU, Memory, IOPS 산정은 필요한가?

by gasbugs 2026. 7. 7.
반응형

성능과 용량 산정 이야기를 하면 늘 비슷한 질문이 나옵니다.

  • “TPS는 얼마로 잡아야 하나요?”
  • “CPU는 몇 개가 필요할까요?”
  • “Memory는 얼마나 있어야 하나요?”
  • “IOPS는 어떻게 계산하나요?”
  • “동시 접속자 500명을 받으려면 서버가 몇 대 필요하죠?”

 

그런데 실무를 해보면 이런 생각이 듭니다.

어차피 계산해도 틀리는 것 아닌가?

 

맞습니다. 대부분 틀립니다.
특히 서비스가 아직 만들어지지도 않았거나, 실제 사용자의 행동 패턴을 모르는 상태에서 계산한 TPS, CPU, Memory, IOPS, Network 수치는 거의 정확하지 않습니다.

 

그렇다면 클라우드에서는 이런 계산을 하지 않아도 될까요?

  • “클라우드는 Auto Scaling이 되니까 그냥 확장 가능하게 만들면 되는 것 아닌가?”
  • “어차피 틀릴 계산이라면 처음부터 크게 고민하지 않아도 되는 것 아닌가?”

 

 

 

이 질문에 대한 제 생각은 이렇습니다.

정확한 용량 산정은 불가능에 가깝다.
하지만 용량 산정 자체가 무의미한 것은 아니다.
용량 산정은 정답을 맞히기 위한 계산이 아니라, 가정을 숫자로 드러내고 검증 가능한 초기 설계를 만들기 위한 과정이다.

1. 용량 산정은 왜 자주 틀릴까?

용량 산정이 틀리는 가장 큰 이유는 계산식이 부족해서가 아닙니다.
입력값이 부정확하기 때문입니다.

예를 들어 다음과 같은 요구사항이 있다고 해보겠습니다.

전체 사용자 3,000명
동시 접속자 500명
이 사용자를 처리할 수 있는 아키텍처 설계

 

겉으로 보기에는 꽤 명확해 보입니다.
하지만 이 정보만으로는 TPS를 계산할 수 없습니다.

왜냐하면 “동시 접속자 500명”이라는 말이 실제로 무엇을 의미하는지 불분명하기 때문입니다.

500명이 로그인만 해두고 화면을 보고 있는 상태일 수도 있습니다.

500명이 30초에 한 번씩 버튼을 누르는 상태일 수도 있습니다.

500명이 1초에 한 번씩 API 요청을 보내는 상태일 수도 있습니다.
사용자 한 명의 업무 요청이 내부적으로 API 1개를 호출할 수도 있고, API 5개를 호출할 수도 있습니다.

 

즉 동시 접속자 수만으로는 실제 부하를 알 수 없습니다.

조건 실제 부하
500명이 로그인만 유지 TPS 매우 낮음
500명이 30초마다 1회 요청 약 16.7 TPS
500명이 10초마다 1회 요청 약 50 TPS
500명이 1초마다 1회 요청 약 500 TPS
업무 1건이 내부 API 5개 호출 API 기준 최대 2,500 RPS 가능

 

그래서 용량 산정의 첫 번째 단계는 서버 스펙을 고르는 것이 아닙니다.
요구사항을 더 정확한 부하 모델로 바꾸는 것입니다.

 

2. 동시 접속자와 TPS는 다르다

성능 산정에서 가장 흔한 오해는 이것입니다.

동시 접속자 500명 = 500 TPS

 

이렇게 보면 안 됩니다.

  • 동시 접속자는 특정 시점에 시스템에 접속해 있는 사용자 수입니다.
  • TPS는 초당 처리되는 업무 트랜잭션 수입니다.
  • RPS는 초당 API 요청 수입니다.

 

이 세 가지는 서로 다릅니다.

전체 사용자 수: 서비스를 사용할 수 있는 전체 사용자 규모
동시 접속자 수: 특정 시점에 접속 중인 사용자 수
TPS: 초당 처리되는 업무 트랜잭션 수
RPS: 초당 API 요청 수

 

성능 모델링에서는 동시성, 처리량, 체류시간 사이의 관계를 설명할 때 Little’s Law를 자주 참고합니다. Little’s Law는 평균 시스템 내 작업 수 L이 도착률 λ와 평균 체류시간 W의 곱이라는 관계를 설명합니다. 즉 L = λW 형태로 표현됩니다.

실무에서는 이를 다음과 같이 단순화해서 사용할 수 있습니다.

업무 TPS ≒ 동시 사용자 수 / (평균 응답시간 + Think Time)

API RPS ≒ 업무 TPS × 업무 1건당 API 호출 수

DB QPS ≒ 업무 TPS × 업무 1건당 DB 쿼리 수

 

여기서 Think Time은 사용자가 다음 행동을 하기 전까지 기다리는 시간입니다.
예를 들어 사용자가 목록을 보고, 내용을 읽고, 다음 버튼을 누르기까지 걸리는 시간이 Think Time입니다.

이 값을 무시하면 실제보다 훨씬 과도한 TPS가 계산됩니다.

 

3. 클라우드에서는 계산하지 말고 확장 가능하게만 만들면 될까?

반은 맞고, 반은 틀립니다.

클라우드 환경에서는 예전처럼 서버를 정확히 몇 대 구매해야 하는 식의 용량 산정은 중요도가 줄었습니다.


Auto Scaling, Managed Database, Load Balancer, CDN, Queue, Serverless 같은 서비스를 활용하면 수요 변화에 훨씬 유연하게 대응할 수 있습니다.

 

하지만 그렇다고 계산이 필요 없는 것은 아닙니다.

계산이 필요한 이유는 다음과 같습니다.

초기 인프라 규모를 정하기 위해
Auto Scaling의 최소/최대 용량을 정하기 위해
비용 범위를 예측하기 위해
DB, Storage, Network 병목을 미리 찾기 위해
부하테스트 기준을 만들기 위해
요구사항을 검증 가능한 숫자로 바꾸기 위해

 

AWS Well-Architected의 성능 효율성 관점에서도 클라우드 리소스를 효율적으로 사용해 성능 요구사항을 충족하고, 그 효율성을 유지하는 것을 중요한 원칙으로 다룹니다.

 

또한 AWS는 클라우드 부하테스트를 예상 사용자 부하를 현실적인 조건에서 측정하고, production-like 환경에서 메트릭을 분석하는 과정으로 설명합니다. 즉 계산만으로 끝내는 것이 아니라, 실제와 유사한 환경에서 부하를 걸고 검증해야 한다는 의미입니다.

따라서 클라우드에서의 용량 산정은 다음과 같이 봐야 합니다.

정확한 예측: 거의 불가능
대략적인 초기 산정: 필요
확장 가능한 설계: 필수
부하테스트 검증: 필수
운영 지표 기반 보정: 필수

4. 3,000명 사용자와 동시 접속자 500명 예시

이제 예시를 들어보겠습니다.

요구사항은 다음과 같습니다.

전체 사용자: 3,000명
피크 동시 접속자: 500명

 

여기에 다음과 같은 가정을 추가합니다.

사용자 1명은 평균 10초에 한 번 주요 업무 요청을 수행
업무 1건은 내부 API 4개를 호출
업무 1건당 DB read 3회
업무 1건당 DB write 1회
평균 응답 크기 50KB
평균 요청 크기 5KB
피크 여유 계수 2배

 

그러면 업무 TPS는 다음과 같이 계산할 수 있습니다.

업무 TPS = 500명 / 10초 = 50 TPS

 

업무 1건이 내부적으로 API 4개를 호출한다면 API RPS는 다음과 같습니다.

API RPS = 50 TPS × 4 = 200 RPS

 

피크 여유 계수 2배를 반영하면 다음과 같습니다.

피크 API RPS = 200 × 2 = 400 RPS

 

DB 요청량은 다음과 같이 계산할 수 있습니다.

DB read/sec = 50 TPS × 3 × 2 = 300 read/sec
DB write/sec = 50 TPS × 1 × 2 = 100 write/sec

 

Network Out은 다음과 같이 계산할 수 있습니다.

Network Out = 400 RPS × 50KB
            = 20,000KB/s
            ≒ 20MB/s
            ≒ 160Mbps

 

이 값은 정답이 아닙니다.
하지만 설계 출발점으로는 충분히 의미가 있습니다.

 

이제 우리는 막연히 “500명 동시 접속 가능하게 해주세요”가 아니라 다음과 같이 말할 수 있습니다.

피크 기준 약 400 API RPS를 처리할 수 있어야 한다.
DB는 초당 read 300회, write 100회 수준을 초기 기준으로 본다.
응답 트래픽은 약 160Mbps 이상을 예상한다.
이 값은 부하테스트를 통해 검증하고 보정한다.

 

이렇게 바꾸는 것이 용량 산정의 핵심입니다.

5. CPU는 어떻게 산정할까?

CPU 산정은 계산식만으로 정확히 맞히기 어렵습니다.

애플리케이션 언어, 프레임워크, 쿼리 방식, 캐시 사용 여부, JSON 직렬화 비용, 암호화, 외부 API 호출 여부에 따라 크게 달라집니다.

 

그래서 CPU는 보통 다음 방식으로 산정합니다.

1. 기준 인스턴스 또는 컨테이너를 정한다.
2. 부하테스트를 통해 해당 단위가 처리 가능한 RPS를 측정한다.
3. 목표 RPS를 단위 처리량으로 나눈다.
4. 장애, 배포, 피크 여유를 반영한다.

 

예를 들어 다음과 같은 테스트 결과가 나왔다고 가정해보겠습니다.

2 vCPU / 4GB 컨테이너 1개
CPU 사용률 60~70%
p95 응답시간 300ms 이하
에러율 1% 이하
처리량 100 RPS

 

앞에서 계산한 피크 API RPS가 400 RPS라면 단순 계산은 다음과 같습니다.

필요 컨테이너 수 = 400 RPS / 100 RPS = 4개

 

하지만 실무에서는 4개로 딱 맞추지 않습니다.

장애 상황, 배포 중 용량 감소, 특정 AZ 장애, 트래픽 급증을 고려해 여유를 둡니다.

평상시 최소 용량: 2~3개
피크 예상 용량: 4~6개
Auto Scaling 최대 용량: 8~10개

 

이런 식으로 설계하는 것이 현실적입니다.

6. Memory는 어떻게 산정할까?

Memory는 애플리케이션 구조에 따라 크게 달라집니다.

대략적인 계산식은 다음과 같습니다.

필요 Memory =
OS/Runtime 기본 사용량
+ 애플리케이션 Heap
+ 커넥션/세션당 메모리
+ 내부 캐시
+ 버퍼 20~30%

 

하지만 클라우드 아키텍처에서는 더 중요한 원칙이 있습니다.

애플리케이션 서버는 가능한 Stateless하게 설계해야 한다.

 

세션을 서버 메모리에 저장하면 서버 수를 늘리기 어렵습니다.
특정 사용자의 세션이 특정 서버에 묶이기 때문입니다.

따라서 세션 정보는 다음과 같은 방식으로 분리하는 것이 좋습니다.

JWT
Redis / ElastiCache
Database Session Store
외부 인증 서비스

 

이렇게 하면 API 서버는 언제든 늘리고 줄일 수 있습니다.
클라우드에서 확장 가능한 구조를 만들려면 Memory 산정보다 먼저 상태 관리 방식을 점검해야 합니다.

 

7. IOPS는 어떻게 산정할까?

IOPS 산정은 특히 조심해야 합니다.

DB 쿼리 수와 디스크 IOPS는 1:1로 대응하지 않습니다.
SELECT 1회가 항상 디스크 read 1회를 의미하지 않습니다.
캐시에 올라와 있으면 디스크를 읽지 않을 수도 있고, 반대로 조인, 정렬, 임시 테이블, 인덱스 접근 때문에 더 많은 I/O가 발생할 수도 있습니다.

write도 마찬가지입니다.

INSERT 또는 UPDATE 1회가 단순한 IOPS 1회로 끝나지 않습니다.
트랜잭션 로그, 인덱스 갱신, 복제, 체크포인트, 스토리지 계층 동작까지 영향을 받습니다.

그래서 초기 IOPS 산정은 다음과 같은 수준으로 접근하는 것이 좋습니다.

DB read/sec = 업무 TPS × 업무당 read 쿼리 수 × 피크 계수
DB write/sec = 업무 TPS × 업무당 write 쿼리 수 × 피크 계수
예상 IOPS = read/write 요청량 × 보정계수

 

예를 들어 앞의 예시에서는 다음과 같습니다.

업무 TPS: 50
피크 계수: 2
업무당 read: 3
업무당 write: 1

read 요청 = 50 × 2 × 3 = 300/sec
write 요청 = 50 × 2 × 1 = 100/sec

 

이 값은 DB 인스턴스와 스토리지를 고르는 초기 기준입니다.
최종 판단은 반드시 DB 모니터링과 부하테스트로 해야 합니다.

확인해야 할 지표는 다음과 같습니다.

DB CPU 사용률
DB Connection 수
Read IOPS / Write IOPS
Disk Queue Depth
Buffer Cache Hit Ratio
Slow Query
Lock Wait
Replication Lag
p95 / p99 Query Latency

 

DB는 애플리케이션 서버처럼 무한히 쉽게 늘릴 수 있는 영역이 아닙니다.
따라서 클라우드 설계에서도 DB 병목은 반드시 별도로 다뤄야 합니다.

8. Network는 어떻게 산정할까?

Network는 상대적으로 계산이 단순합니다.

Network Out = RPS × 평균 응답 크기
Network In = RPS × 평균 요청 크기

 

예를 들어 다음과 같다고 해보겠습니다.

피크 API RPS: 400
평균 응답 크기: 50KB
평균 요청 크기: 5KB

 

그러면 다음과 같이 계산할 수 있습니다.

Network Out = 400 × 50KB = 20,000KB/s ≒ 160Mbps
Network In = 400 × 5KB = 2,000KB/s ≒ 16Mbps

 

다만 여기에는 주의할 점이 있습니다.

정적 파일, 이미지, 동영상, 첨부파일 다운로드가 API 서버를 통해 나가면 Network 산정이 크게 달라집니다.

 

그래서 일반적인 클라우드 아키텍처에서는 정적 리소스를 다음과 같이 분리합니다.

정적 파일: S3 또는 Object Storage
전송 최적화: CloudFront / CDN
동적 요청: API Server

 

이렇게 하면 API 서버는 비즈니스 로직 처리에 집중하고, 대용량 트래픽은 CDN과 Object Storage가 담당하게 됩니다.

9. Auto Scaling은 계산을 대체하지 않는다

Auto Scaling이 있으니 계산이 필요 없다고 생각할 수 있습니다.
하지만 Auto Scaling도 기준이 필요합니다.

 

AWS EC2 Auto Scaling의 Target Tracking 정책은 CPU 사용률, 네트워크, ALB Request Count per Target, 사용자 정의 CloudWatch Metric 같은 목표 지표를 기준으로 용량을 조정합니다. AWS 문서에서는 Target Tracking이 목표 메트릭 값을 기준으로 Auto Scaling Group의 용량을 자동 조정한다고 설명합니다.

 

즉 Auto Scaling을 설정하려면 이런 질문에 답해야 합니다.

CPU 60%를 목표로 할 것인가?
ALB RequestCountPerTarget 100을 목표로 할 것인가?
p95 응답시간을 Custom Metric으로 쓸 것인가?
최소 인스턴스 수는 몇 개인가?
최대 인스턴스 수는 몇 개인가?
Scale-out은 얼마나 빠르게 할 것인가?
Scale-in은 얼마나 보수적으로 할 것인가?

 

결국 Auto Scaling도 용량 산정의 결과를 필요로 합니다.

다만 차이가 있습니다.

예전 방식의 용량 산정은 “서버 몇 대면 충분한가?”에 가까웠습니다.
클라우드 방식의 용량 산정은 “어떤 기준으로 얼마나 확장하고, 어느 지점에서 병목이 생기는가?”에 가깝습니다.

10. 3,000명 / 동시 접속자 500명 기준 권장 아키텍처

요구사항이 “3,000명 사용자, 동시 접속자 500명”이라면 다음과 같은 구조를 기본 아키텍처로 제안할 수 있습니다.

사용자
  ↓
Route 53 / DNS
  ↓
CloudFront + WAF
  ↓
Application Load Balancer
  ↓
ECS / EKS / Auto Scaling Group
  ↓
Stateless API Server
  ↓
Redis / ElastiCache
  ↓
RDS / Aurora Multi-AZ
  ↓
S3 / Object Storage

 

비동기 처리가 필요한 업무가 있다면 다음 구성을 추가합니다.

API Server
  ↓
SQS / EventBridge / Kafka
  ↓
Worker Auto Scaling
  ↓
Database / External API

 

핵심은 모든 요청을 동기 처리로 밀어 넣지 않는 것입니다.

예를 들어 다음과 같은 작업은 비동기화 대상입니다.

이메일 발송
문자 발송
대용량 리포트 생성
이미지 처리
외부 API 연동
결제 후 후속 처리
로그 분석
AI 추론 작업

 

이런 작업을 Queue 기반으로 분리하면 사용자가 느끼는 응답시간을 줄이고, 순간 트래픽도 더 안정적으로 흡수할 수 있습니다.

Google Cloud Well-Architected Framework도 보안, 효율성, 복원성, 고성능, 비용 최적화, 지속가능성 관점에서 클라우드 토폴로지를 설계하고 운영하는 권장사항을 제공합니다. 결국 클라우드 아키텍처는 성능 하나만 보는 것이 아니라 비용, 운영, 안정성까지 함께 봐야 합니다.

 

11. 어떻게 다루는 것이 좋을까?

만약 “TPS, CPU, Memory, IOPS, Network를 계산해서 3,000명 사용자와 동시 접속자 500명을 처리하는 아키텍처를 설계하라”는 주제로 출강 요청을 받았다면, 단순 계산식으로 가면 위험합니다.

 

실무적으로는 다음 흐름이 좋습니다.

1. 사용자 수와 동시 접속자의 차이
2. 동시 접속자를 TPS/RPS로 변환하는 방법
3. 업무 시나리오 정의
4. API 호출 수, DB 쿼리 수, 응답 크기 추정
5. CPU, Memory, IOPS, Network 초기 산정
6. 확장 가능한 클라우드 아키텍처 설계
7. Auto Scaling 정책 설계
8. 부하테스트 수행
9. 병목 분석
10. 비용과 안정성 균형 조정

 

 반드시 강조해야 할 메시지는 이것입니다.

용량 산정은 정답을 맞히는 문제가 아니다.
가정을 세우고, 숫자로 표현하고, 부하테스트로 검증하고, 운영 지표로 보정하는 과정이다.

 

특히 “동시 접속자 500명”이라는 요구사항은 다음 질문으로 쪼개야 합니다.

500명은 로그인 세션 기준인가, 활성 사용자 기준인가?
사용자는 몇 초마다 요청하는가?
업무 1건은 API 몇 개를 호출하는가?
API 1건은 DB 쿼리를 몇 번 발생시키는가?
평균 응답 크기는 얼마인가?
p95 응답시간 목표는 얼마인가?
장애 상황에서도 500명을 처리해야 하는가?
피크는 5분인가, 1시간인가, 하루 종일인가?
정적 파일 트래픽은 API 서버가 처리하는가, CDN이 처리하는가?

 

이 질문에 답하지 않고 CPU, Memory, IOPS부터 계산하면 대부분 의미 없는 숫자가 됩니다.

 

12. 간단한 용량 산정 코드

강의나 실습에서는 아래와 같은 간단한 계산기를 만들어 보여주면 좋습니다.

import math

def estimate_capacity(
    concurrent_users: int,
    think_time_sec: float,
    avg_response_time_sec: float,
    api_calls_per_business_tx: int,
    peak_factor: float,
    avg_response_kb: float,
    avg_request_kb: float,
    db_reads_per_tx: int,
    db_writes_per_tx: int,
    rps_per_app_instance_at_target: int,
    ha_buffer: float = 1.25,
):
    # 업무 TPS 계산
    # 사용자가 요청 후 다음 요청까지 기다리는 시간까지 포함
    business_tps = concurrent_users / (think_time_sec + avg_response_time_sec)

    # API RPS 계산
    api_rps = business_tps * api_calls_per_business_tx

    # 피크 계수 반영
    peak_api_rps = api_rps * peak_factor

    # DB 요청량 계산
    db_read_per_sec = business_tps * db_reads_per_tx * peak_factor
    db_write_per_sec = business_tps * db_writes_per_tx * peak_factor

    # 네트워크 대역폭 계산
    network_out_mbps = peak_api_rps * avg_response_kb * 8 / 1024
    network_in_mbps = peak_api_rps * avg_request_kb * 8 / 1024

    # 앱 인스턴스 수 계산
    required_instances = math.ceil(
        (peak_api_rps / rps_per_app_instance_at_target) * ha_buffer
    )

    return {
        "business_tps": round(business_tps, 2),
        "api_rps": round(api_rps, 2),
        "peak_api_rps": round(peak_api_rps, 2),
        "db_read_per_sec": round(db_read_per_sec, 2),
        "db_write_per_sec": round(db_write_per_sec, 2),
        "network_out_mbps": round(network_out_mbps, 2),
        "network_in_mbps": round(network_in_mbps, 2),
        "required_app_instances": required_instances,
    }


result = estimate_capacity(
    concurrent_users=500,
    think_time_sec=10,
    avg_response_time_sec=0.5,
    api_calls_per_business_tx=4,
    peak_factor=2,
    avg_response_kb=50,
    avg_request_kb=5,
    db_reads_per_tx=3,
    db_writes_per_tx=1,
    rps_per_app_instance_at_target=100,
)

for key, value in result.items():
    print(f"{key}: {value}")

 

예상 결과는 다음과 비슷합니다.

business_tps: 47.62
api_rps: 190.48
peak_api_rps: 380.95
db_read_per_sec: 285.71
db_write_per_sec: 95.24
network_out_mbps: 148.81
network_in_mbps: 14.88
required_app_instances: 5

 

이 결과를 보고 “서버는 무조건 5대면 된다”고 판단하면 안 됩니다.
이 값은 초기 가정에 따른 출발점입니다.

실제 강의에서는 이 값을 기준으로 부하테스트를 수행하고, 다음 지표를 관찰하는 방식으로 이어가면 좋습니다.

CPUUtilization
MemoryUtilization
RequestCount
TargetResponseTime
HTTPCode_ELB_5XX
HTTPCode_Target_5XX
DB CPU
DB Connections
ReadIOPS / WriteIOPS
p95 / p99 Latency
Queue Depth

결론: 계산은 틀린다. 그래도 계산해야 한다.

성능과 용량 산정은 대부분 틀립니다.
특히 실제 사용자 행동, 데이터 크기, 쿼리 패턴, 코드 성능을 모르는 상태에서 계산한 값은 정답이 될 수 없습니다.

하지만 그렇다고 용량 산정이 무용지물인 것은 아닙니다.

 

클라우드 시대의 용량 산정은 서버 수를 정확히 맞히는 작업이 아닙니다.
가정을 숫자로 드러내고, 아키텍처 설계의 기준선을 만들고, 부하테스트와 운영 지표로 검증하기 위한 과정입니다.

 

정리하면 다음과 같습니다.

계산만 믿으면 위험하다.
계산 없이 설계하면 더 위험하다.
클라우드에서는 확장 가능하게 설계해야 한다.
하지만 확장 기준을 만들기 위해 초기 산정은 반드시 필요하다.
최종 답은 계산식이 아니라 부하테스트와 운영 데이터가 준다.

 

따라서 “3,000명 사용자와 동시 접속자 500명을 처리하는 아키텍처”를 설계할 때는 이렇게 접근하는 것이 가장 현실적입니다.

1. 동시 접속자를 TPS/RPS로 변환한다.
2. 업무 시나리오와 API 호출 구조를 정의한다.
3. CPU, Memory, IOPS, Network를 초기 산정한다.
4. Stateless, CDN, Cache, Queue, Auto Scaling 기반으로 설계한다.
5. 부하테스트로 검증한다.
6. 운영 지표를 보고 보정한다.

 

정확히 맞히는 것이 목표가 아닙니다.
틀릴 것을 전제로, 빨리 검증하고 안전하게 확장할 수 있는 구조를 만드는 것이 목표입니다.

 

반응형