목차
- 왜 단순 업로드 시간만 보면 자꾸 판단이 틀어질까
- 객체 스토리지 성능 측정에서 꼭 봐야 하는 지표
- S3/R2/GCS 객체 스토리지 성능 측정을 공정하게 만드는 설계
- S3 성능 벤치마크를 위한 실전 준비
- 1. 테스트 파일 세트 만들기
- 2. AWS CLI로 S3와 R2 조건 맞추기
- 3. GCS 처리량 측정은 gsutil 병렬 옵션을 분리해서 보기
- 클라이언트 병목을 같이 보지 않으면 숫자가 자꾸 거짓말합니다
- 실제 트러블슈팅: 멀티파트 조건이 달라서 비교가 깨졌던 사례
- 결과는 어떻게 읽어야 하나: 숫자보다 패턴을 봅니다
- 자주 받는 질문 정리
- 벤치마크는 몇 번 반복하면 좋을까요?
- 다운로드 테스트도 꼭 해야 하나요?
- 한 도구로 통일해야 하나요?
- 벤치마크 비용은 어떻게 줄이나요?
- 현업 기준으로 이렇게 추천드립니다
객체 스토리지 성능 측정 방법론: S3/R2/GCS 벤치마크
객체 스토리지 성능 측정은 숫자 하나 뽑는 일보다 비교 조건을 설계하는 일에 더 가깝습니다. 업로드 한 번 돌려서 나온 시간에는 그 순간의 네트워크 상태, TLS 세션 재사용 여부, 클라이언트 CPU 상태, 리전 거리까지 한꺼번에 섞이거든요. 저도 처음엔 단일 파일 복사 시간만 보고 판단했다가, 운영에 올린 뒤 작은 파일 다건 업로드와 메타데이터 조회가 병목이 되면서 완전히 다른 그림을 봤습니다. 그래서 이 글은 “누가 더 빠르다”를 단정하려는 글이 아니라, 객체 스토리지 성능 측정을 실무에서 재현 가능하게 만드는 방법론을 정리한 글입니다.
특히 S3, R2, GCS는 API 표면은 비슷해 보여도 측정 도구, 병렬화 방식, 재시도 전략, 멀티파트 또는 분할 업로드 동작이 꽤 다릅니다. 이 차이를 통제하지 않으면 저장소를 비교하는 게 아니라 각 벤치마크 도구의 기본값을 비교하게 됩니다. 현업에서는 이 실수가 진짜 치명적이더라고요. 비슷한 인프라 비교 글을 함께 정리해 두면, 나중에 CDN 캐시나 전송 비용 이슈까지 한 번에 판단하기도 훨씬 편합니다.

단일 벤치마크 클라이언트에서 S3, R2, GCS로 동일한 워크로드를 보내고 지표를 수집하는 구성 예시입니다.
왜 단순 업로드 시간만 보면 자꾸 판단이 틀어질까
객체 스토리지는 로컬 디스크 벤치마크처럼 순차 읽기·쓰기 하나로 설명되지 않습니다. 요청 하나마다 DNS, TCP, TLS, HTTP 연결 재사용, 인증, 서버 측 큐잉이 섞입니다. 같은 100GB 업로드라도 1GB 파일 100개와 256KB 파일 수십만 개는 완전히 다른 테스트예요. 전자는 스트림 처리량 문제고, 후자는 요청 수와 꼬리 지연 문제입니다.
- 대용량 백업이면 단일 스트림 처리량, 멀티파트 분할 기준, 재시도 시 복구 비용이 핵심입니다.
- 썸네일, 로그 조각, 문서 스니펫처럼 작은 객체가 많으면 평균 속도보다 요청당 지연 시간과 실패율이 더 중요합니다.
- 애플리케이션이 HEAD, LIST, GET 또는 메타데이터 조회를 자주 쓰면 PUT 성능보다 p95·p99 응답 시간이 체감에 더 크게 작용합니다.
제가 실무에서 제일 많이 보는 오판은 이것입니다. 큰 파일 하나는 빨랐는데 서비스는 느린 경우요. 이유는 단순합니다. 서비스는 큰 파일 한 번보다 작은 객체 수천 번을 더 자주 만지기 때문입니다. 그래서 벤치마크는 항상 워크로드를 먼저 정의해야 합니다. 저장소 이름보다 접근 패턴이 먼저예요.
객체 스토리지 성능 측정에서 꼭 봐야 하는 지표
표를 화려하게 만들 필요는 없습니다. 대신 운영 판단에 실제로 쓰이는 지표만 남겨야 합니다. 저는 아래 여섯 개를 기본 세트로 잡습니다.
- Throughput: 초당 전송 바이트 수입니다. 큰 파일 백업, 미디어 아카이브, 데이터 레이크 적재처럼 스트리밍 성격이 강한 워크로드에서 중요합니다.
- Latency: 요청 하나가 끝나는 시간입니다. 작은 객체 서비스는 이 값이 곧 체감 성능입니다.
- p95/p99 Tail Latency: 평균값이 멀쩡해도 느린 구간이 튀면 운영 품질은 나빠집니다. 사용자 불만은 거의 여기서 나옵니다.
- Error Rate / Retry Count: 4xx, 5xx, 타임아웃, 재시도 횟수입니다. 처리량이 조금 높아도 재시도가 많으면 운영 점수는 낮게 봐야 합니다.
- Concurrency Scaling: 동시성을 올렸을 때 얼마나 비례해서 늘어나는지 봅니다. 이 곡선이 평평해지는 지점이 병목 후보입니다.
- Client Resource Usage: CPU, NIC, 로컬 디스크 사용률입니다. 저장소를 재는 줄 알았는데 테스트 클라이언트의 암호화 비용이나 디스크 읽기 속도를 재는 경우가 생각보다 흔합니다.
여기서 하나 더 붙이자면 변동성입니다. 같은 조건에서 5번 돌렸을 때 편차가 큰 서비스는 평균값이 좋아도 운영 예측 가능성이 낮습니다. 백업 창이 촘촘하거나 배치 종료 시간이 중요한 팀이라면 최고 속도보다 흔들림이 작은 쪽이 더 낫습니다. 이거, 막상 운영 붙이면 차이가 꽤 크게 느껴집니다.
S3/R2/GCS 객체 스토리지 성능 측정을 공정하게 만드는 설계
툴보다 중요한 건 통제 변수입니다. S3 성능 벤치마크, R2 속도 측정, GCS 처리량 비교를 따로따로 보면 쉬워 보여도 실제로는 한 줄만 달라도 해석이 깨집니다. 아래 항목은 최소한 맞춰두셔야 합니다.
| 항목 | 왜 맞춰야 하나 | 권장 방식 |
|---|---|---|
| 클라이언트 위치 | 리전 거리와 네트워크 경로가 바뀌면 저장소 자체 차이가 가려집니다 | 같은 VM 또는 같은 베어메탈 호스트에서 모든 테스트 수행 |
| 파일 크기 분포 | 작은 파일과 큰 파일은 병목이 다릅니다 | 작은 파일, 중간 파일, 큰 파일, 혼합 패턴을 분리 측정 |
| 동시성 | 단일 연결 수치만으로는 확장 특성을 보기 어렵습니다 | 1, 4, 8, 16처럼 단계적으로 올리고 증가 곡선을 기록 |
| 재시도/타임아웃 | 도구 기본값이 다르면 실패율과 시간 값이 왜곡됩니다 | 가능하면 동일한 재시도 횟수와 타임아웃 정책을 명시 |
| 멀티파트/병렬 업로드 기준 | 큰 파일 성능에 직접 영향을 줍니다 | threshold, chunk size, 병렬 프로세스 수를 문서화해서 고정 |
| 워밍업 | 첫 실행은 DNS, TLS, 캐시 영향으로 튀는 경우가 많습니다 | 워밍업 1회 후 본 측정 5회 이상 |
제 기준으로는 한 서비스가 더 빨라 보일 때 바로 결론을 내리지 않습니다. 먼저 묻는 건 세 가지입니다. 같은 크기 분포였는지, 같은 동시성이었는지, 같은 재시도 정책이었는지. 이 셋이 다르면 사실상 다른 시험입니다.

큰 파일, 작은 파일, 혼합 워크로드와 동시성 단계별 측정 매트릭스를 한눈에 정리한 구성입니다.
S3 성능 벤치마크를 위한 실전 준비
1. 테스트 파일 세트 만들기
데이터 세트는 재현 가능해야 합니다. 운영 덤프를 그대로 쓰면 현실성은 좋지만, 개인정보 처리와 반복성 문제가 생깁니다. 그래서 저는 보통 크기 분포만 닮은 합성 데이터 세트를 따로 만듭니다. 빈 파일이나 <code>truncate로 만든 희소 파일은 피하시는 편이 낫습니다. 압축, 중복 제거, 페이지 캐시 영향 때문에 실제 업로드 비용과 동떨어질 수 있어서요.
mkdir -p ~/objbench/data/{small,medium,large}
cd ~/objbench/data
# 작은 파일 1000개: 요청 수와 지연 시간 측정용
for i in $(seq -w 1 1000); do
dd if=/dev/urandom of=small/small-${i}.bin bs=256K count=1 status=none
done
# 중간 파일 100개: 일반적인 애플리케이션 업로드 패턴 근사
for i in $(seq -w 1 100); do
dd if=/dev/urandom of=medium/medium-${i}.bin bs=8M count=8 status=none
done
# 큰 파일 4개: 멀티파트 처리량과 재시도 비용 확인용
for i in $(seq -w 1 4); do
dd if=/dev/urandom of=large/large-${i}.bin bs=64M count=16 status=progress
done
# 디렉터리별 총 용량 확인
find ~/objbench/data -type f -printf '%h\n' | sort | uniq -c
find ~/objbench/data -type f -exec du -ch {} + | tail -n 1
이렇게 나누는 이유는 단순합니다. 큰 파일은 스트리밍 경로를 재고, 작은 파일은 요청 처리 경로를 잽니다. 같은 저장소라도 두 결과가 정반대로 나올 수 있습니다.
2. AWS CLI로 S3와 R2 조건 맞추기
S3와 R2는 같은 S3 호환 API 축에 있으니, 비교용 도구는 하나로 맞추는 편이 낫습니다. 여기서 핵심은 기본값을 믿지 않는 겁니다. AWS CLI는 max_concurrent_requests, multipart_threshold, multipart_chunksize, addressing_style 같은 값이 결과에 직접 영향을 줍니다. 큰 파일 테스트에서는 이 네 개를 반드시 기록해 두세요.
# 기본 프로파일에 S3 전송 관련 설정 고정
aws configure set default.s3.max_concurrent_requests 16
aws configure set default.s3.multipart_threshold 64MB
aws configure set default.s3.multipart_chunksize 16MB
aws configure set default.s3.addressing_style path
# 선택: 대역폭 제한이 필요한 경우만 사용
# aws configure set default.s3.max_bandwidth 200MB/s
# 설정 확인
aws configure get default.s3.max_concurrent_requests
aws configure get default.s3.multipart_threshold
aws configure get default.s3.multipart_chunksize
aws configure get default.s3.addressing_style
# S3 업로드 측정
/usr/bin/time -f 'elapsed=%E cpu=%P mem=%MKB' \
aws s3 cp ~/objbench/data/large/large-01.bin s3://my-s3-bucket/bench/large-01.bin \
--only-show-errors
# R2 업로드 측정
/usr/bin/time -f 'elapsed=%E cpu=%P mem=%MKB' \
aws --endpoint-url https://ACCOUNT_ID.r2.cloudflarestorage.com \
s3 cp ~/objbench/data/large/large-01.bin s3://my-r2-bucket/bench/large-01.bin \
--only-show-errors
여기서 자주 놓치는 부분이 두 가지입니다. 하나는 경로 방식(path style)과 가상 호스트 방식 차이, 다른 하나는 도구 내부 기본 동작 차이입니다. R2는 현재 path style과 virtual-hosted style을 모두 지원하지만, 비교 목적이라면 주소 지정 방식까지 한 번 정해 고정하는 편이 해석이 깔끔합니다. 조건이 자꾸 바뀌면 저장소 비교가 흐려지거든요.
그리고 멀티파트를 너무 공격적으로 키우는 것도 능사는 아닙니다. 파트 수를 늘리면 처리량은 올라갈 수 있지만, 요청 수와 클라이언트 메모리 사용량도 같이 늘어납니다. 백업 창을 줄이는 게 목표라면 유효할 수 있지만, 공유 VM이나 제한된 NAT 환경에서는 오히려 타임아웃과 재시도가 늘 수 있습니다.
3. GCS 처리량 측정은 gsutil 병렬 옵션을 분리해서 보기
GCS 쪽은 여기서 많이 헷갈립니다. gsutil -m은 단순한 장식 옵션이 아니라 결과 해석을 바꾸는 변수입니다. 공식 문서 기준으로도 -m은 병렬 작업을 켜며, 여러 객체 작업에서 동작 특성이 달라집니다. 그래서 단일 실행 결과와 병렬 실행 결과를 같은 줄에 섞으면 안 됩니다.
또 한 가지는 최신 상태입니다. 2026년 8월 30일 기준으로 Google Cloud는 새 자동화에는 gcloud storage 사용을 권장하고 있고, gsutil은 권장 CLI가 아닙니다. 게다가 공식 문서에는 2027년 3월 이후 gsutil이 Google Cloud CLI 설치 패키지에 더 이상 포함되지 않고 독립 도구로 배포된다고 안내돼 있습니다. 기존 스크립트 검증이라면 gsutil로 재도 되지만, 새 벤치마크 체계를 만든다면 gsutil 결과와 gcloud storage 결과를 혼용하지 않는 것이 좋습니다. 도구가 다르면 기본 병렬화와 출력 형식이 다르기 때문입니다.
# gsutil 단일 실행
/usr/bin/time -f 'elapsed=%E cpu=%P mem=%MKB' \
gsutil cp ~/objbench/data/large/large-01.bin gs://my-gcs-bucket/bench/
# gsutil 병렬 실행: 작은/중간 파일 다건 처리 패턴 확인용
/usr/bin/time -f 'elapsed=%E cpu=%P mem=%MKB' \
gsutil -m cp ~/objbench/data/medium/*.bin gs://my-gcs-bucket/bench/
# 병렬 관련 boto 설정 예시
cat > ~/.boto <<'EOF'
[GSUtil]
parallel_process_count = 4
parallel_thread_count = 8
resumable_threshold = 64M
EOF
# 객체 메타데이터 확인
gsutil stat gs://my-gcs-bucket/bench/large-01.bin
# 새 자동화 체계 예시: gcloud storage 기준으로 별도 측정
/usr/bin/time -f 'elapsed=%E cpu=%P mem=%MKB' \
gcloud storage cp ~/objbench/data/large/large-01.bin gs://my-gcs-bucket/bench/
제가 권하는 방식은 간단합니다. GCS는 최소 두 시나리오로 나누세요. 1) 단일 객체 업로드 성능 2) 다건 병렬 처리 성능. 이 둘을 분리해야 S3/R2와 비교할 때 어디서 차이가 나는지 보입니다.
클라이언트 병목을 같이 보지 않으면 숫자가 자꾸 거짓말합니다
저장소 성능 테스트에서 가장 억울한 순간은, 나중에 보니 저장소가 아니라 내 테스트 머신이 병목이었던 경우입니다. 특히 암호화 오프로딩이 약한 VM, 공유 네트워크 인터페이스, 느린 로컬 디스크 위에서는 이런 일이 자주 납니다. 그래서 벤치마크 로그에는 저장소 지표와 함께 클라이언트 지표를 남겨야 합니다.
sar, mpstat, iostat는 보통 Linux의 sysstat 패키지에 포함되니, 없는 환경이라면 먼저 설치 여부부터 확인해 두세요. 이런 사전 점검이 생각보다 시간을 많이 아껴줍니다.
# 1초 간격으로 네트워크, CPU, 디스크 상태 확인
sar -n DEV 1
mpstat -P ALL 1
iostat -x 1
# DNS와 TCP/TLS가 병목인지 분리해서 보기 위한 curl 예시
curl -s -o /dev/null \
-w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} starttransfer=%{time_starttransfer} total=%{time_total} code=%{http_code}\n' \
https://storage.googleapis.com/
저는 해석을 이렇게 합니다.
- 동시성을 1, 4, 8, 16으로 올렸는데 처리량이 거의 그대로면 저장소보다 클라이언트 NIC, CPU, TCP 윈도우, NAT 세션 한도를 먼저 의심합니다.
- CPU 한 코어만 유독 높으면 CLI의 단일 스레드 구간이나 TLS 처리 비용이 병목일 수 있습니다.
await나%util이 높은 디스크에서 업로드 테스트를 하면, 사실은 원본 파일 읽기 성능을 재고 있을 가능성이 큽니다.- 평균은 괜찮은데 체감이 느리면 p95/p99를 따로 적어야 합니다. 서비스 품질은 평균보다 꼬리 지연에 훨씬 민감합니다.
여기서 하나 더. 공인 인터넷을 거치는 테스트라면 시간대 편차도 로그에 남기세요. 같은 조건인데 낮과 밤이 다르면 저장소보다 네트워크 경로 혼잡도가 결과를 더 크게 흔들고 있다는 뜻일 수 있습니다.

저장소 자체 성능과 클라이언트 CPU·디스크·네트워크 병목을 함께 확인하는 실전 점검 화면 예시입니다.
실제 트러블슈팅: 멀티파트 조건이 달라서 비교가 깨졌던 사례
실무에서 가장 자주 보는 실패 모드는 화려하지 않습니다. 대개는 비교 조건이 숨은 곳에서 달라져 있는 문제입니다. 제가 크게 데인 사례도 그랬습니다. S3와 R2는 AWS CLI로, GCS는 별도 CLI로 측정했는데, 한쪽은 큰 파일을 여러 파트로 나눠 병렬 전송하고 있었고 다른 쪽은 사실상 단일 흐름에 가까웠습니다. 표만 보면 특정 서비스가 느려 보이는데, 저장소가 느린 게 아니라 전송 방식이 달랐던 거죠.
증상은 이랬습니다.
- 큰 파일 업로드에서 한 서비스만 유독 시간이 길었습니다.
- 작은 파일 묶음 테스트에서는 차이가 크지 않았습니다.
- 클라이언트 CPU와 NIC는 한계에 닿지 않았고, 재시도 로그도 많지 않았습니다.
이럴 때는 저장소를 탓하기 전에 먼저 전송 단위를 확인하셔야 합니다. 멀티파트 threshold, part size, 병렬 프로세스 수, 재시도 정책이 같지 않으면 결과 해석이 불가능합니다. 저는 그 뒤로 아예 아래 체크리스트를 벤치마크 시트 첫 줄에 적어둡니다.
- 도구와 버전이 동일한가
- 멀티파트 또는 병렬 업로드 기준이 동일한가
- 동시성과 재시도 정책이 동일한가
- 첫 실행을 버리고 워밍업 뒤 본 측정을 했는가
- 클라이언트 CPU, NIC, 디스크 병목 여부를 함께 기록했는가
이 체크리스트를 통과하면 그제야 숫자가 설명되기 시작합니다. 벤치마크는 예쁜 수치보다 왜 그런 결과가 나왔는지 설명 가능한 상태가 먼저입니다.
결과는 어떻게 읽어야 하나: 숫자보다 패턴을 봅니다
같은 결과표라도 읽는 기준이 없으면 결론이 흔들립니다. 저는 아래처럼 해석합니다.
| 시나리오 | 기록할 값 | 읽는 방법 |
|---|---|---|
| 큰 파일 업로드 | 경과 시간, 평균 처리량, 재시도 횟수, 멀티파트 설정 | 동시성 증가에 따라 처리량이 오르는지, 특정 지점에서 평평해지는지 봅니다 |
| 작은 파일 다건 업로드 | 총 소요 시간, 파일당 평균 시간, 오류 수, p95/p99 | 평균보다 편차와 실패율을 더 무겁게 봅니다 |
| 메타데이터 요청 | HEAD/LIST 응답 시간 또는 메타데이터 조회 시간, 타임아웃 여부 | 애플리케이션 체감과 직접 연결되므로 꼬리 지연을 우선 봅니다 |
| 반복 실행 안정성 | 실행별 분포, 중앙값, 최댓값/최솟값 차이 | 가장 빠른 값보다 흔들림이 작은 쪽이 운영 예측 가능성이 높습니다 |
운영 관점에서 읽으면 기준이 더 선명해집니다.
- 동시성을 올려도 처리량이 안 늘면 그 지점이 현재 병목입니다. 저장소가 아니라 클라이언트나 네트워크일 가능성도 큽니다.
- 큰 파일은 빠른데 작은 파일이 느리면, 그 저장소가 나쁜 게 아니라 현재 워크로드와 안 맞는 겁니다.
- 반복 5회 중 1회만 튄다면 최고 기록보다 안정성 리스크를 먼저 봐야 합니다.
- 오류나 재시도가 보이면 평균 처리량이 좋아도 운영 점수는 낮게 잡는 편이 안전합니다.

처리량, p95 지연 시간, 재시도 횟수를 한 화면에서 비교해 패턴을 읽는 결과 대시보드 예시입니다.
자주 받는 질문 정리
벤치마크는 몇 번 반복하면 좋을까요?
워밍업 1회 후 본 측정 5회 이상은 잡으시는 게 좋습니다. 그보다 적으면 편차를 해석하기 어렵습니다. 가능하면 시간대도 나눠 보세요. 저장소보다 네트워크가 흔들리는지 구분하는 데 도움이 됩니다.
다운로드 테스트도 꼭 해야 하나요?
네. 업로드와 다운로드는 병목이 다를 수 있습니다. 서비스 제공용이면 GET 패턴이 더 중요할 때도 많고, 다운로드 경로에서 CDN이나 캐시 전략을 같이 볼 수도 있습니다.
한 도구로 통일해야 하나요?
가능하면 좋습니다. 다만 서비스별 공식 도구 차이가 있으니 현실적으로 완전 통일이 어려울 수는 있습니다. 그럴수록 비교 문서에 도구, 버전, 병렬화 옵션, 재시도 설정을 더 자세히 남겨야 합니다.
벤치마크 비용은 어떻게 줄이나요?
저는 먼저 작은 파일 세트와 중간 파일 세트로 병목 구간을 찾고, 마지막에만 큰 파일 반복 측정을 합니다. 큰 파일 다회 측정은 전송 비용과 시간 비용이 커서, 초반 탐색 단계에서는 효율이 좋지 않습니다.
현업 기준으로 이렇게 추천드립니다
판단 기준은 생각보다 명확합니다. 백업, 로그 아카이브, 대용량 적재처럼 큰 파일 중심이면 S3/R2/GCS 중 무엇이든 먼저 볼 것은 단일 업로드 성공률, 멀티파트 설정, 동시성 증가 시 처리량 곡선입니다. 여기서는 최고 속도 한 줄보다 재시도와 안정성이 더 중요합니다. 처리량이 조금 낮아도 흔들림이 작고 재시도가 적은 쪽이 운영에선 더 낫습니다.
반대로 이미지, 썸네일, 문서 조각, 메타데이터 조회가 많은 서비스라면 p95 지연 시간, LIST/HEAD 응답, 반복 간 편차를 우선 보셔야 합니다. 이 경우 대역폭보다 요청당 지연이 더 아프게 들어옵니다. 큰 파일 업로드 수치가 좋아도 작은 객체에서 꼬리 지연이 크면 실제 서비스 만족도는 떨어집니다.
도구 선택도 이렇게 가져가시면 됩니다. S3와 R2를 비교할 때는 AWS CLI로 최대한 조건을 맞추세요. GCS는 기존 스크립트 검증이면 gsutil을 쓰되, 새 자동화 체계라면 gcloud storage로 넘어갈 계획까지 같이 잡는 편이 낫습니다. 다만 한 번의 비교 세트에서는 두 도구를 섞지 않는 게 안전합니다.
제가 현업에서 내리는 결론은 늘 비슷했습니다. “어느 서비스가 더 빠른가”보다 내 워크로드가 큰 파일 중심인지, 작은 객체 중심인지, 메타데이터 요청 중심인지부터 자르는 것. 그다음 같은 조건으로 재고, 평균보다 꼬리 지연과 변동성을 보고, 마지막에 비용과 운영 복잡도를 얹어 판단합니다. 벤치마크에서 진짜 가치가 있는 숫자는 가장 높은 숫자가 아니라, 운영에서 다시 재현되는 숫자입니다.
워크로드별로 어떤 지표를 우선 봐야 하는지 정리한 요약 인포그래픽입니다.