AWS 기술 블로그
“같은 트래픽, CPU는 86% 덜 쓴다” — 100만 사이트 플랫폼 아임웹의 Valkey 9.1 실측 결과
들어가며
아임웹은 2026년 7월 10일 새벽, Amazon ElastiCache 기반 운영 캐시들을 Redis 6.x/Valkey 7.2 에서 Valkey 9.1로 업그레이드했습니다. 대표 범용 캐시는 SSR(Server-Side Rendering) 경로와 여러 서비스 로직에서 반복적으로 조회되는 캐시로, 비교 구간 3.5시간 동안 7억 건 이상의 명령어를 처리했습니다.
업그레이드 이후 전날 동일 시간대 대비 전체 CPU는 86.6%, Engine CPU는 31.6%, GET latency는 30.5%, SET latency는 53.6% 감소했습니다. 명령 수 차이를 보정한 Engine CPU / 1M commands도 27.4% 낮아져, 단순 트래픽 차이가 아니라 엔진 효율 개선을 운영 메트릭으로 확인할 수 있었습니다.
이 글에서는 아임웹이 왜 캐시 엔진 효율을 중요하게 여겼는지, Valkey 9.1 업그레이드 전 어떻게 캐시 전반을 점검했는지, 그리고 실제 운영 메트릭에서 어떤 변화가 나타났는지 공유합니다.
아임웹 소개

아임웹은 누구나 쉽게 브랜드 웹사이트와 쇼핑몰을 만들고 운영할 수 있도록 돕는 노코드 기반 브랜드 빌더 플랫폼입니다. 사용자는 디자인 모드와 80개 이상의 템플릿, AI 웹빌더를 활용해 웹사이트를 빠르게 만들 수 있고, 상품 등록, 결제, 주문 관리, 예약, CRM 캠페인, 통계, 마케팅 기능까지 하나의 관리자 환경에서 운영할 수 있습니다.
아임웹은 단순한 웹사이트 제작 도구를 넘어, 온라인 비즈니스의 시작과 성장을 지원하는 운영 플랫폼으로 확장하고 있습니다. 공식 페이지 기준 2025년 누적 사이트 개설 수는 100만 개, 고객사 거래액은 7조 원 규모이며, 전국 4,000명의 디자이너·전문가 생태계와 함께 다양한 브랜드의 온라인 성장을 지원하고 있습니다.
이처럼 다양한 업종과 규모의 사이트가 아임웹 위에서 운영되기 때문에, 페이지 렌더링 경로의 응답성과 안정성은 사용자 경험에 직접적인 영향을 줍니다. 특히 아임웹의 주요 페이지는 서버 기반으로 렌더링되며, 사이트 설정, 메뉴, 권한, 세션 상태, 상품·콘텐츠 표시 조건 등 여러 데이터를 요청 경로에서 반복적으로 조회합니다. 이 구조에서 캐시는 DB 부하를 줄이는 보조 계층을 넘어, 서비스 응답성과 인프라 효율을 좌우하는 핵심 계층입니다.
왜 캐시 엔진 효율이 중요했나
아임웹의 주요 트래픽은 SSR(Server-Side Rendering) 기반 페이지 렌더링 경로를 많이 포함합니다. 하나의 페이지를 렌더링할 때 사이트 설정, 메뉴, 권한, 세션 상태, 상품/콘텐츠 표시 조건, TTL 기반 임시 데이터 등 여러 종류의 데이터를 빠르게 조회해야 합니다.
이때 캐시는 단순히 DB 쿼리 몇 개를 줄이는 보조 장치가 아닙니다. 사용자 요청 전반에서 반복적으로 호출되며, DB 병목을 완화하고 렌더링 지연 시간[KK1] 을 낮추는 핵심 계층입니다. 따라서 캐시 엔진의 CPU 효율과 명령어 지연은 전체 서비스 응답성에 직접적인 영향을 줍니다.
대표 샘플로 본 아임웹 범용 캐시는 특정 기능 하나에만 묶이지 않고 TTL cache, lock, 중복 요청 방지, 임시 상태 저장 등 다양한 목적으로 쓰입니다. 평소에도 전체 cache fleet 중 높은 처리량을 꾸준히 유지하기 때문에, Valkey 9.1 업그레이드 효과를 관찰하기에 적합했습니다.
Valkey는 왜 더 빠르고 효율적이며 비용 효과적인가
Valkey는 Redis OSS와 호환되는 오픈소스 in-memory data store입니다. ElastiCache for Valkey를 사용하면 기존 Redis OSS 계열 워크로드와 호환성을 유지하면서 최신 Valkey 엔진의 성능, 메모리 효율, 운영 안정성 개선을 활용할 수 있습니다.
Valkey 7.2부터 9.1까지는 많은 개선이 누적되었지만, 이번 글에서는 아임웹의 캐시 워크로드와 직접 맞닿아 있는 주요 개선만 추려 살펴보겠습니다. 개선 지점은 크게 I/O, 메모리 효율, 명령어 처리, 클러스터 운영 안정성 네 가지로 나눌 수 있습니다.
1. I/O 개선
Valkey의 I/O 개선은 main thread가 네트워크 I/O, polling, parsing, memory free, lookup 준비 작업에 쓰는 시간을 줄이고 실제 명령어 실행에 더 집중하도록 만드는데 목적이 있습니다.
1.1 I/O threading 구조 재설계 – Valkey 8.0, 8.1
기존 I/O thread는 read/write를 일부 도와주긴 했지만, main thread가 I/O thread 작업을 동기적으로 기다리는 구조였습니다. 이 때문에 main thread가 명령어를 실행하는 동안 I/O thread가 유휴상태가 되거나 반대로 I/O 관련 작업 때문에 main thread가 막히는 구간이 있었습니다.
Valkey 8.0에서는 I/O thread를 더 비동기적으로 바꿨습니다. main thread와 I/O thread가 병렬로 동작하고, I/O thread는 client read, command parsing, response write 같은 작업을 맡습니다. 그 결과로 main thread는 명령어 실행에 더 많은 시간을 쓸 수 있습니다.

1.2 Command batching & memory prefetching – Valkey 8.0
Valkey는 key를 찾을 때 내부 dictionary를 탐색합니다. keyspace가 커지면 이 탐색은 pointer chasing이 많아지고, CPU cache에 없는 메모리를 자주 읽게 됩니다. 공식 분석에서는 main thread가 lookupKey에 40% 이상 시간을 쓰는 구간이 관찰됐습니다.
Valkey 8.0은 I/O thread에서 넘어온 명령어를 batch로 보고, 실행 전에 필요한 key lookup 경로를 미리 CPU cache로 당겨옵니다. 즉 명령어를 하나씩 순차 탐색하는 대신, 여러 key의 위치를 미리 확인해 CPU cache에 올려두고 실제 실행 시 대기시간을 줄이는 방식입니다.
예를 들어 여러 GET site:* 요청이 동시에 들어오면, 기존에는 각 command를 실행할 때마다 key를 dictionary에서 찾으며 random memory access를 기다려야 했습니다.
Valkey 8.0은 batch 안의 여러 key에 대해 dictionary lookup 경로를 미리 따라가고 필요한 메모리 주소를 CPU cache로 당겨옵니다. 그 결과 실제 command 실행 시 lookupKey에서 외부 메모리 접근을 기다리는 시간이 줄어듭니다.
1.3 I/O threading communication model 개선 – Valkey 9.1
Valkey 9.1은 main thread와 I/O thread 사이의 통신을 queue 기반으로 재설계했습니다. 기존에는 main thread가 pending client list를 반복 scan하고 thread별 작업 분배를 직접 조정해야 했지만, 9.1에서는 shared queue와 response queue를 통해 작업 전달과 완료 처리를 분리했습니다. idle I/O thread가 shared queue에서 직접 작업을 가져가면서 부하 분산이 자연스러워졌습니다.

이러한 I/O 경로 개선은 같은 노드에서 더 많은 요청을 처리하는 기반이 됩니다. 하지만 캐시 엔진의 효율은 CPU만으로 결정되지 않습니다. key/value를 얼마나 적은 메모리와 적은 pointer access로 저장하는지도 운영 비용과 지연 시간직접적인 영향을 줍니다.
2. Memory 효율 개선
Valkey의 메모리 개선은 단순히 압축을 추가한 것이 아니라, key/value를 저장하는 내부 자료구조의 포인터 수, allocation 수, random memory access를 줄여 같은 메모리에서 더 많은 keyspace를 담도록 만든 변화입니다.
2.1 작은 key/value [KK1] 워크로드에서 메모리 최대 20% 절감 – Valkey 8.0
기존 cluster mode에서는 slot migration을 위해 key마다 slot-to-key linked list 메타데이터를 추가로 들고 있었습니다. 이 구조는 key마다 slot-prev, slot-next 포인터가 필요했고, 64-bit 환경에서는 key당 16 bytes 오버헤드가 생겼습니다.
Valkey 8.0은 slot마다 별도 dictionary를 두는 구조로 바꿔 이 slot-to-key 메타데이터를 제거했습니다. 여기에 key를 별도 SDS pointer로 들고 있지 않고 dictionary entry 안에 직접 embedding하면서 key pointer와 추가 memory lookup도 줄였습니다.
2.2 New hashtable – Valkey 8.1
기존 dict는 chained hash table 구조였습니다. key를 찾을 때 bucket → dictEntry → key/value처럼 여러 포인터를 따라가야 하고, hash collision이 있으면 linked list를 더 따라가야 했습니다. 이 구조는 포인터 저장 비용도 크고, CPU cache에 없는 메모리를 여러 번 읽게 만들 수 있습니다.
새 hashtable은 64-byte cache line 단위의 bucket을 사용합니다. 하나의 bucket에 여러 entry와 metadata를 함께 배치하고, 기존 dictEntry를 제거했습니다. key/value 정보는 serverObject 쪽에 통합됩니다.

Valkey의 메모리 개선은 단순히 저장 공간을 줄이는 데서 끝나지 않습니다. pointer chasing과 allocation 수가 줄면 CPU cache locality가 좋아지고, command 처리 비용도 함께 낮아질 수 있습니다.
3. Command 처리 개선
Command 처리 개선은 단순히 명령어 구현을 빠르게 한 것이 아니라, 명령 실행 전후에 붙는 TLS 처리, reply 생성, object 접근, client 초기화 비용을 줄여 GET/SET 중심 캐시 워크로드의 latency와 throughput을 개선한 변화입니다.
3.1 Zero-copy responses – Valkey 9.0
GET/MGET처럼 값을 읽어 client에게 돌려줄 때, 기존에는 value 데이터를 응답 버퍼에 한 번 복사한 뒤 socket으로 다시 전송해야 했습니다. 값이 커질수록 이 복사 비용은 main thread의 CPU와 memory bandwidth를 더 많이 사용합니다.
Valkey 9.0의 zero-copy response는 큰 string 값을 응답할 때 value 전체를 reply buffer에 다시 복사하지 않습니다. 대신 reply buffer에는 “이 value를 보내라”는 참조만 남기고, 실제 전송 시점에 writev를 사용해 value object에서 socket으로 바로 내보냅니다. 즉 큰 응답을 만들 때 불필요한 메모리 복사를 줄여 main thread의 부담을 낮추는 방식입니다.

4. Cluster 효율 개선
Valkey의 cluster 개선은 단순히 더 많은 노드를 붙일 수 있다는 의미가 아니라, resharding, failover, large cluster gossip, failure report 처리처럼 운영 중 가장 흔들리기 쉬운 구간의 비용과 복잡도를 줄이는 변화입니다.
| Metric | Before | After | Change |
| FreeableMemory | 30.6GB | 31.2GB | +627MB |
| DatabaseMemoryUsagePercentage | 5.36% | 3.75% | -30.1% |
| MemoryFragmentationRatio | 1.37 | 1.17 | -14.9% |
4.1 Atomic slot migration – Valkey 9.0
Valkey 9.0은 resharding의 핵심인 slot migration을 replication 기반으로 재설계했습니다. 기존에는 key를 하나씩 옮기며 ASK redirect와 multi-key retry가 발생할 수 있었지만, atomic slot migration은 slot 데이터를 먼저 target에 복제하고 target이 따라잡은 뒤 ownership을 원자적으로 넘깁니다. 이 방식은 large key 이동과 장애 상황에서 더 안전하고, 공식 실험에서는 legacy 방식 대비 최대 약 9배 빠른 migration 시간을 보였습니다.

4.2 대량 동시 failover 시[KK1] 안전성 향상
대규모 cluster에서는 하나의 primary 장애보다 여러 primary가 동시에 실패하는 상황이 더 어렵습니다. replica election 요청이 서로 충돌하거나, 살아남은 노드들이 실패 노드에 반복적으로 reconnect하고 failure report를 정리하느라 CPU를 소모할 수 있기 때문입니다. Valkey는 shard ranking 기반 failover 조정, reconnect throttling, failure report tracking 최적화 등을 통해 대량 동시 장애 상황에서도 cluster가 더 예측 가능한 시간 안에 회복되도록[KK1] 개선했습니다.
4.3 1B RPS benchmark 달성
지금까지 이런 다양한 개선들은 2,000 node cluster에서 1B RPS를 달성한 대규모 benchmark로도 확인되었습니다. 해당 benchmark는 1,000 primaries와 1,000 replicas 구성, AWS r7g.2xlarge 기반, 750 client instances로 수행되었습니다. 이 수치를 일반적인 웹 서비스 cache workload와 직접 비교할 수는 없지만, Valkey cluster가 대규모 shard 수, cluster bus overhead, 다중 primary 장애 회복까지 고려해 개선되고 있다는 점을 보여줍니다.
업그레이드 중 당면 과제
- 서비스 영향 최소화: endpoint는 유지되더라도 업그레이드 중 짧은 연결 끊김이 발생할 수 있으므로 애플리케이션[KK1] 오류로 증폭되지 않아야 했습니다.
- 클라이언트 동작 검증: connection retry, command retry, offline queue, timeout, connection pool 정책이 클라이언트 라이브러리마다 달라 사전 점검이 필요했습니다.
- 원인 분리: 엔진 업그레이드와 노드 크기 최적화를 동시에 진행하면 CPU, memory, latency 변화의 원인을 구분하기 어렵습니다.
업그레이드 전 확인한 클라이언트 동작
ElastiCache 엔진 업그레이드는 endpoint DNS를 유지할 수 있지만, 기존 클라이언트 연결이 계속 유지된다는 의미는 아닙니다. 업그레이드 과정에서 새 엔진 버전의 노드가 붙고 데이터 복제와 cutover가 진행되며, 이때 failover 또는 connection reset이 발생할 수 있습니다.
결국 업그레이드 안정성의 핵심은 서버보다 클라이언트였습니다. Redis/Valkey 클라이언트에서 retry는 하나의 기능처럼 보이지만, 실제로는 여러 층으로 나뉩니다.
- connection retry: 연결이 끊겼을 때 다시 붙는 동작
- command retry: 실패한 명령어를 다시 실행
- offline queue: 연결이 끊긴 동안 명령어를 queue에 쌓는 동작
- application fallback: cache 실패 시 DB 또는 기본값으로 우회하는 동작
GET처럼 멱등적인 조회 명령어는 제한적인 retry가 비교적 안전합니다. 반면 lock, counter, deduplication처럼 상태를 바꾸는 명령어는 중복 실행이 큰 문제가 될 수 있기에, retry 정책은 클라이언트 라이브러리 [KK1] 기본값이 아니라 cache 사용 목적 기준으로 정해야 했습니다.
또 하나 확인한 부분은 stale connection입니다. TCP keepalive는 half-open connection을 감지하는 보조 장치일 뿐, failover 이후 오래된 connection을 즉시 정리해주지는 않습니다. 그래서 timeout, health check, connection lifetime, reconnect 정책을 함께 봐야 합니다.
예를 들어 Node.js 환경에서 ioredis를 사용한다면, 다음과 같이 timeout과 reconnect 정책을 명시할 수 있습니다.
connection pool을 직접 관리하는 구조라면, pool 단에서도 오래된 connection을 검증하고 주기적으로 폐기하는 정책을 둘 수 있습니다.
ElastiCache 인플레이스 업그레이드 진행
클라이언트 동작을 점검한 뒤에는 영향도가 낮은 캐시부터 순차적으로 Valkey 9.1 업그레이드를 진행했습니다. ElastiCache의 엔진 업그레이드는 endpoint DNS를 유지할 수 있지만, 내부적으로는 새 엔진 버전의 노드가 준비되고 데이터 복제와 cutover가 진행됩니다. 이 과정에서 짧은 failover 또는 connection reset이 발생할 수 있기 때문에, 각 캐시는 트래픽이 낮은 시간대에 하나씩 업그레이드했습니다.
대표 범용 캐시의 경우 2026년 7월 10일 03:42 KST에 업그레이드가 시작되었고, 04:01 KST에 완료되었습니다.
업그레이드 후 실제 메트릭 변화
아래 수치는 대표 범용 캐시의 CloudWatch 메트릭을 기준으로 전날 동일 시간대와 비교한 결과입니다. 비교 구간은 업그레이드 직후 안정화 구간인 2026-07-10 04:30~08:00 KST입니다.
CPU 효율


| Metric | Before | After | Change |
| EngineCPUUtilization | 8.72% | 5.97% | -31.6% |
| CPUUtilization | 24.98% | 3.35% | -86.6% |
| Engine CPU / 1M commands | 0.012 | 0.008 | -27.4% |
| CPU / 1M commands | 0.033 | 0.005 | -85.8% |
전체 CPU는 86.6%[KK1] , Engine CPU는 31.6% 감소했습니다. 명령 수 차이를 보정한 Engine CPU / 1M commands도 27.4% 낮아져, 같은 명령어들을 처리하는 데 필요한 CPU 비용이 줄어든 것으로 해석할 수 있었습니다.
Memory 효율


| Metric | Before | After | Change |
| FreeableMemory | 30.6GB | 31.2GB | +627MB |
| DatabaseMemoryUsagePercentag | 5.36% | 3.75% | -30.1% |
| MemoryFragmentationRatio | 1.37 | 1.17 | -14.9% |
FreeableMemory는 약 627MB 증가했고, DatabaseMemoryUsagePercentage는 5.36%에서 3.75%로 낮아졌습니다. MemoryFragmentationRatio도 1.37에서 1.17로 개선되어 동일한 workload를 더 낮은 memory pressure로 처리하는 모습을 확인했습니다.
GET/SET latency


| Metric | Before | After | Change |
| GetTypeCmdsLatency | 1.04 | 0.72 | -30.5% |
| SetTypeCmdsLatency | 5.26 | 2.44 | -53.6% |
GET/SET 계열 latency도 함께 낮아졌습니다. 범용 캐시의 주요 workload가 단순 조회와 TTL 기반 쓰기 중심이라는 점을 고려하면, 이 변화는 SSR 렌더링 경로에서 의미 있는 개선으로 볼 수 있습니다.
명령어 family별 latency
| 명령어 family | Latency change |
| StringBasedCmdsLatency | -28.5% |
| KeyBasedCmdsLatency | -67.0% |
| SortedSetBasedCmdsLatency | -21.7% |
| ClusterBasedCmdsLatency | -92.3% |
| NonKeyTypeCmdsLatency | 70.3% |
| GetTypeCmdsLatency | -30.5% |
| SetTypeCmdsLatency | -42.6% |
String, Key, Sorted Set, Cluster 명령어 계열에서도 latency 개선이 관찰되었습니다. 특정 명령어 하나만 개선된 것이 아니라 명령어 프로세스 전반이 가벼워진 것으로 볼 수 있었습니다.
부작용 확인


| Metric | Before | After | Change |
| CurrConnections | 1,334 | 1,320 | -1.1% |
| NewConnections | 3,404 | 3,401 | -0.1% |
| Evictions | 0 | 0 | no change |
| ReplicationLag | 0 | 0 | normal |
성능 개선과 함께 확인해야 할 것은 부작용입니다. 업그레이드 이후 connection 지표는 안정화되었고, Evictions와 ReplicationLag는 0으로 유지되었습니다. 즉 CPU, memory, 명령어 latency 개선이 관찰되는 동안 capacity pressure나 replication 이상은 함께 발생하지 않았습니다.
비용 관점
캐시 엔진 효율 개선은 성능 지표에서 끝나지 않습니다. 같은 노드 타입에서 CPU와 메모리 여유가 늘어나면 peak traffic 대응 여유가 커지고, 충분한 관찰 기간 이후에는 타입 조정 후보를 검토할 수 있습니다.
다만, 엔진 업그레이드와 노드 다운사이즈를 동시에 진행하지 않는 것이 중요합니다. 두 작업을 한 번에 묶으면 latency 변화, CPU 변화, eviction 증가, 클라이언트 에러 스파이크가 발생했을 때 원인이 엔진인지 용량인지 구분하기 어렵습니다. 따라서 [KK1] 아임웹은 먼저 Valkey 9.1 업그레이드로 엔진 개선 효과와 안정성을 확인하고, 이후 장기 메트릭을 기반으로 사양 최적화 가능성을 판단하는 접근을 선택했습니다.
또한 Valkey는 엔진 가격 자체에서도 비용 이점이 있습니다. 서울 리전의 On-Demand cache.r7g.2xlarge 기준으로 Redis OSS는 $1.045/node-hour, Valkey는 $0.836/node-hour입니다. 아임웹 기준 동일한 28개 노드를 한 달 730시간 운영한다고 가정하면, 엔진 전환만으로 연간 약 $51,264, 원화 기준 약 7,560만 원의 비용 절감 효과를 기대할 수 있습니다.
맺음말
Valkey 9.1 업그레이드는 단순히 최신 버전을 적용한 작업이 아니라, 아임웹의 SSR 중심 서비스 구조에서 캐시 엔진 효율이 실제 운영 지표로 어떻게 나타나는지 확인한 작업이었습니다.
대표 범용 캐시에서 초당 6만 건의 명령어가 지속적으로 처리되는 환경에서도, 업그레이드 이후 Engine CPU, memory usage, GET/SET latency가 모두 개선되었습니다. 이 결과는 캐시 계층을 단순 저장소가 아니라 서비스 응답성과 비용 효율을 좌우하는 핵심 인프라로 보고 관리해야 한다는 점을 보여줍니다.
참고자료
- Valkey 9.1 official blog: https://valkey.io/blog/valkey-9-1-delivers-improvements-in-security-performance-and-more/
- Amazon ElastiCache Valkey 9.1 announcement: https://aws.amazon.com/blogs/database/announcing-valkey-9-1-for-amazon-elasticache/
- Valkey 9.0 official blog: https://valkey.io/blog/introducing-valkey-9/
- Amazon ElastiCache Valkey 9.0 announcement: https://aws.amazon.com/blogs/database/announcing-valkey-9-0-for-amazon-elasticache/
- Valkey 8.1 official blog: https://valkey.io/blog/valkey-8-1-0-ga/
- Valkey 8.0 performance and reliability: https://valkey.io/blog/valkey-8-0-0-rc1/
- Valkey 8.0 memory efficiency: https://valkey.io/blog/valkey-memory-efficiency-8-0/
- Unlock 1 Million RPS with Valkey: https://valkey.io/blog/unlock-one-million-rps/
- Valkey new hash table: https://valkey.io/blog/new-hash-table/
- Valkey atomic slot migration: https://valkey.io/blog/atomic-slot-migration/
- Scaling a Valkey Cluster to 1 Billion RPS: https://valkey.io/blog/1-billion-rps/
- ElastiCache version management: https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/VersionManagement.html
- AWS ElastiCache Pricing: https://aws.amazon.com/elasticache/pricing/
- AWS Price List API: https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonElastiCache/current/ap-northeast-2/index.json
- ioredis reconnect/retry behavior: https://github.com/redis/ioredis#auto-reconnect
- node-redis production usage: https://redis.io/docs/latest/develop/clients/nodejs/produsage/
- Lettuce production usage: https://redis.io/docs/latest/develop/clients/lettuce/produsage/
- 아임웹 공개 소개 참고: https://imweb.me/blog?idx=348