
"상품 페이지가 안 뜨는데요?"
릴리스 직후 테스트 중에 선배가 불렀다. 개발팀이 모여서 원인을 찾기 시작했다. 누군가 "Redis 캐시 확인해볼까요?"라고 말하고 있었다.
당시 나는 Redis라는 단어는 들어봤지만, 실제로 뭘 하는 건지, 어떻게 확인해야 하는지 전혀 몰랐다. 결국 그 자리에서 아무것도 못하고 그냥 지켜보기만 했다.
나중에 들으니 원인은 Redis 캐시 설정 오류였다고 한다. 기본 지식만 있었어도 원인 파악에 더 빨리 기여할 수 있었을 텐데.
그날 이후로 Redis는 피할 수 없는 기술이라는 걸 절실히 느꼈다. 이번에는 현장에서 실제로 사용하는 Redis에 대해 공유하려고 한다.
Redis는 인메모리 Key-Value 스토어다. 쉽게 말하면 데이터베이스와 애플리케이션 사이에 끼어있는 '고속 캐시 레이어' 역할을 한다.
예를 들어 이커머스 사이트에서 상품 정보를 가져오는 API가 있다고 치자.
Redis 없을 때:
1. 사용자가 요청
2. 매번 데이터베이스 접근
3. 응답 느림
Redis 있을 때:
1. 첫 요청 → 데이터베이스에서 가져옴 → Redis에 저장
2. 두 번째부터 → Redis에서 빠르게 가져옴
3. 응답 속도 확 빨라짐
즉, 자주 쓰는 데이터를 메모리에 올려놓는 방식으로 시스템 전체 성능을 끌어올리는 구조다.
Redis에 저장한 데이터는 TTL(Time To Live)을 설정할 수 있다.
# 상품 정보를 60초간 캐싱
SET product:1001 "{\"name\":\"노트북\",\"price\":89800}" EX 60
60초가 지나면 이 키는 자동으로 삭제된다. 오래된 데이터가 계속 남아있지 않도록 하는 메커니즘이다.
솔직히 처음엔 "개발자들이 쓰는 거 아닌가?"라고 생각했다. 근데 실제 현장에서는 달랐다.
부하 테스트 할 때 Redis 상태를 확인 못하면 얘기가 안 된다.
"왜 응답이 느린 거지?"
"Redis 히트율은?"
"캐시가 제대로 작동하나?"
이런 질문에 답 못하면 성능 병목 지점을 찾을 수가 없다.
사용자 세션, 재고 수량, 로그인 상태 — 이런 건 UI에 직접 표시되지 않지만 Redis에 저장되어 있다.
화면만 봐서는 내부에서 데이터가 제대로 유지되고 있는지 알 수 없다. Redis를 직접 확인해야 한다.
"상품이 안 보여요"라는 버그가 발생했을 때,
Redis를 확인할 수 있으면 원인 분리가 압도적으로 빨라진다.
"핫키 만료 대책 세웠어?"
"Cache Avalanche 리스크는?"
이런 대화에 참여할 수 있으면 개발팀의 신뢰도 올라간다.
모든 데이터는 Key(키)로 접근한다.
# 사용자 정보 키 예시
user:123:profile
user:123:cart
session:abc123
콜론(:)으로 구분하는 게 일반적이고, 가독성도 높아진다.
Redis는 메모리에 데이터를 올려놓기 때문에 읽기/쓰기가 엄청 빠르다.
단, 서버가 재시작되면 데이터가 날아간다(영속화 설정 안 했을 경우).
이게 Redis의 특징이자 제약이다.
Redis는 단순 문자열뿐만 아니라 여러 데이터 타입을 지원한다.
| 데이터 타입 | 특징 | 사용 예시 | 테스트 확인 사항 |
|---|---|---|---|
| String | 단순 Key-Value | 카운터, HTML 조각, 분산 락 | 값 정확성, 숫자 증감 |
| Hash | 여러 필드를 가진 딕셔너리 | 사용자 정보, 설정 정보 | 특정 필드 값 |
| List | 순서가 있는 리스트 | 큐, 타임라인 | 순서, 요소 개수 |
| Set | 중복 없는 집합 | 태그, 추첨, 중복 제거 | 요소 존재 확인 |
| Sorted Set | 스코어가 있는 집합 | 랭킹, 우선순위 큐 | 정렬 순서와 스코어 |
테스트 환경에서는 redis-cli나 GUI 툴(AnotherRedisDesktopManager 등)을 쓴다.
# 키 존재 확인
EXISTS user:123
# 키 타입 확인
TYPE user:123
# TTL 확인 (-1: 만료 없음, -2: 존재하지 않음)
TTL session:abc123
# 키 삭제
DEL test:user:999
# 패턴 매칭으로 키 검색 (프로덕션에서는 주의)
KEYS user:*
String 타입
# 값 가져오기
GET product:1001
Hash 타입
# 전체 필드 가져오기
HGETALL user:123:profile
# 특정 필드 가져오기
HGET user:123:profile email
List 타입
# 전체 요소 가져오기
LRANGE queue:orders 0 -1
Set 타입
# 전체 요소 가져오기
SMEMBERS tags:article:1001
Sorted Set 타입
# 스코어 내림차순으로 가져오기 (랭킹 확인)
ZREVRANGE ranking:daily 0 9 WITHSCORES
상품 상세 API 호출 후 Redis에 제대로 캐싱되었는지 확인한다.
# API 요청 후
GET product:detail:1001
# 기대 결과: 상품 정보 JSON
캐싱이 안 되어 있으면 캐시 로직에 문제가 있을 가능성이 크다.
세일 상품 재고를 Redis로 관리하는 경우, 구매 전후로 숫자가 제대로 줄어드는지 확인한다.
# 구매 전
GET seckill:stock:1001
# 결과: 100
# 구매 후
GET seckill:stock:1001
# 결과: 99
로그인 후 세션 정보가 Redis에 저장되어 있는지 확인한다.
HGETALL session:abc123
# 기대 결과
# user_id: 123
# login_time: 2025-12-02 10:00:00
# role: admin
테스트 종료 후에는 테스트 데이터를 삭제한다.
DEL test:user:999
DEL test:order:*
주의: FLUSHDB는 전체 데이터를 삭제하므로 프로덕션 환경에서는 절대 쓰면 안 된다.
문제:
존재하지 않는 데이터에 대한 요청이 대량으로 들어오면 Redis를 건너뛰고 데이터베이스에 직접 접근하게 된다.
테스트 방법:
존재하지 않는 ID로 연속 요청을 보내서 데이터베이스 부하를 확인한다.
# 존재하지 않는 상품 ID로 연속 요청
for i in {9999..10099}; do
curl "https://api.example.com/product/$i"
done
대책:
문제:
인기 상품의 캐시가 만료되는 순간 대량의 요청이 데이터베이스로 몰린다.
테스트 방법:
TTL이 끝나는 타이밍에 동시 요청을 발생시킨다.
# TTL 확인
TTL product:hot:1001
# 만료 직전에 부하 테스트
ab -n 1000 -c 100 https://api.example.com/product/1001
대책:
문제:
대량의 키가 동시에 만료되면서 시스템 전체가 다운된다.
테스트 방법:
같은 TTL을 가진 키를 대량으로 생성하고 만료 시점의 동작을 확인한다.
대책:
문제:
데이터베이스를 업데이트했는데 Redis 캐시는 예전 값 그대로.
테스트 방법:
1. 데이터베이스 직접 업데이트
2. API로 가져온 값 확인
3. Redis 값 확인
# 데이터베이스 업데이트 후
GET product:1001
# 예전 값이 나오면 불일치
대책:
수동으로 Redis 확인하는 건 귀찮고 실수도 많이 난다.
Apidog을 쓰면 API 테스트와 Redis 검증을 하나의 워크플로우로 자동화할 수 있다.
실제 사용법:
이렇게 하면 "API는 정상인데 Redis에 저장 안 됨" 같은 문제를 조기에 발견할 수 있다.
수동 CLI보다 재현성이 높고 팀 전체가 공유할 수 있다는 게 큰 장점이다.
Redis는 이제 테스트 엔지니어에게 필수 기술이다.
최소한 알아야 할 것:
KEYS, TYPE, TTL로 기본 정보를 확인할 수 있다GET, HGETALL, SMEMBERS 등)이것만 되면 성능 테스트도 장애 조사도 지금보다 훨씬 매끄러워진다.
개발자와 대화도 잘 통하게 되고, "이 QA 엔지니어 좀 아는구나"라는 평가를 받을 수 있다.
Redis를 이해하면 테스트 퀄리티가 한 단계 올라간다. 실제 현장에서 꼭 써보길 바란다.