⚡ Redis 완벽 가이드: 빠르고 똑똑한 데이터 저장소
"DB가 있는데 왜 Redis가 필요한가요?"
이 질문에 명확히 답할 수 있는 순간, 당신의 백엔드 설계 능력은 한 단계 도약합니다! 🚀
📋 목차
1️⃣ Redis란 무엇인가?
🎯 한 문장 정의
Redis는 RAM에 데이터를 저장해 매우 빠르게 읽고 쓰는 Key-Value 데이터베이스입니다.
💡 쉽게 이해하기
일반 DB를 서랍장이라고 생각해보세요.
서랍을 열고 닫는 데는 시간이 걸립니다.
Redis는 책상 위에 놓인 메모장입니다.
필요한 정보를 즉시 볼 수 있고, 즉시 쓸 수 있습니다.
MySQL (서랍장) → 디스크에 저장, 안전하지만 느림
vs
Redis (책상 위) → 메모리에 저장, 빠르지만 휘발성
🔍 Redis의 핵심 특징
⚡ 1. 초고속 성능
- 메모리 기반 - 디스크가 아닌 RAM 사용
- 읽기/쓰기 속도 - 밀리초(ms) 이하
⏳ 2. TTL (Time To Live) 지원
- 데이터에 만료 시간 설정 가능
- 시간이 지나면 자동 삭제
SET email:verify:user@example.com "123456" EX 300
# 300초(5분) 후 자동 삭제
🔑 3. Key-Value 구조
- 단순하고 직관적
- 빠른 조회 보장
Key Value
email:verify:user@example.com → "123456"
session:abc123 → {"userId": 1, "name": "홍길동"}
product:top10 → [1, 5, 9, 13, 22]
🧠 4. 다양한 자료구조 지원
| 자료구조 | 설명 | 사용 예시 |
|---|---|---|
| String | 단순 문자열 | 인증번호, 토큰 |
| List | 순서 있는 목록 | 최근 게시글, 알림 |
| Set | 중복 없는 집합 | 좋아요 목록, 태그 |
| Hash | 필드-값 쌍 | 사용자 정보, 상품 정보 |
| Sorted Set | 정렬된 집합 | 리더보드, 랭킹 |
📊 Redis vs 일반 DB
비교표
| 구분 | Redis | MySQL |
|---|---|---|
| 저장 위치 | 💾 메모리(RAM) | 💿 디스크 |
| 속도 | ⚡ 매우 빠름 (0.001초) | 🐢 상대적으로 느림 (0.01~0.1초) |
| TTL | ✅ 기본 지원 | ❌ 직접 구현 필요 |
| 영구 저장 | 🔄 선택 사항 | ✅ 기본 제공 |
| 데이터 구조 | 🧠 다양 (String, List, Set...) | 📋 테이블 (행/열) |
| 주 용도 | 🚀 캐시, 임시 데이터, 세션 | 📚 영구 데이터, 복잡한 쿼리 |
| 비용 | 💰 메모리 비용 高 | 💵 디스크 비용 低 |
🎯 핵심 차이점
Redis → "빠르지만 휘발성" (메모리)
MySQL → "느리지만 영구적" (디스크)
실무에서는 두 개를 함께 사용합니다!
Redis: 캐시 + 임시 데이터
MySQL: 영구 데이터 + 복잡한 쿼리
2️⃣ Redis는 언제 사용하나?
🎯 핵심 원칙
"빠르고, 잠깐만 필요하고, 자주 접근하는 데이터"
이 세 가지 조건을 만족하면 Redis가 정답입니다!
🏆 실무 활용 사례 TOP 5
1️⃣ 이메일/SMS 인증번호 ⭐⭐⭐
가장 대표적이고 완벽한 Redis 활용 사례!
시나리오
사용자가 회원가입 → 이메일로 인증번호 발송
→ 5분 내 입력해야 함 → 입력 후 삭제
Redis 구현
# 인증번호 저장 (5분 TTL)
SET email:verify:user@example.com "483920" EX 300
# 인증번호 확인
GET email:verify:user@example.com
# → "483920"
# 5분 후 자동 삭제 또는 인증 성공 시 수동 삭제
DEL email:verify:user@example.com
Java + Spring Boot 예시
@Service
public class EmailVerificationService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
// 인증번호 저장
public void saveVerificationCode(String email, String code) {
String key = "email:verify:" + email;
redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
}
// 인증번호 확인
public boolean verifyCode(String email, String inputCode) {
String key = "email:verify:" + email;
String savedCode = redisTemplate.opsForValue().get(key);
if (savedCode != null && savedCode.equals(inputCode)) {
redisTemplate.delete(key); // 인증 성공 시 삭제
return true;
}
return false;
}
}
✅ 왜 Redis가 최적인가?
- ⏳ 5분 후 자동 삭제 - TTL 기능 활용
- 🗑️ DB 테이블 불필요 - 임시 데이터이므로
- ⚡ 빠른 조회 - 인증 시도 시 즉시 확인
- 🧹 자동 정리 - 만료된 데이터 관리 불필요
💡 Tip: 이메일/문자 인증은 Redis가 정답입니다!
2️⃣ 로그인 세션 / 토큰 관리 🔐
시나리오 A: 세션 관리
# 세션 저장 (1시간 TTL)
SET session:abc123 '{"userId":1,"name":"홍길동"}' EX 3600
# 세션 조회
GET session:abc123
Java 예시
@Service
public class SessionService {
public void createSession(String sessionId, User user) {
String key = "session:" + sessionId;
String value = objectMapper.writeValueAsString(user);
redisTemplate.opsForValue().set(key, value, 1, TimeUnit.HOURS);
}
public User getSession(String sessionId) {
String key = "session:" + sessionId;
String value = redisTemplate.opsForValue().get(key);
return objectMapper.readValue(value, User.class);
}
}
시나리오 B: JWT 블랙리스트
# 로그아웃된 토큰을 블랙리스트에 추가
SET blacklist:token:xyz789 "logout" EX 86400
# 요청 시 블랙리스트 확인
GET blacklist:token:xyz789
# 존재하면 → 접근 거부
3️⃣ 캐시(Cache) 💾
사용 사례
- 🔥 인기 상품 목록
- 📰 메인 페이지 데이터
- 📝 자주 조회되는 게시글
Before: Redis 없이
매번 요청마다 DB 조회 → 느림 + 부하 증가
After: Redis 캐시 적용
1차: Redis 조회 (0.001초) → 있으면 반환
2차: 없으면 DB 조회 → Redis에 저장 → 반환
실무 예시
@Service
public class ProductService {
// 인기 상품 TOP 10 조회
public List<Product> getTop10Products() {
String key = "product:top10";
// 1. Redis에서 먼저 확인
String cached = redisTemplate.opsForValue().get(key);
if (cached != null) {
return objectMapper.readValue(cached, List.class);
}
// 2. Redis에 없으면 DB 조회
List<Product> products = productRepository.findTop10ByOrderBySalesDesc();
// 3. Redis에 저장 (10분 TTL)
redisTemplate.opsForValue().set(
key,
objectMapper.writeValueAsString(products),
10,
TimeUnit.MINUTES
);
return products;
}
}
📈 성능 개선 효과
DB 조회 시간: 100ms
Redis 조회 시간: 1ms
→ 100배 빠름!
DB 조회 횟수: 1000회/분 → 10회/분
→ 99% 감소!
💡 Tip: 캐시 TTL은 데이터 특성에 맞게 설정하세요. 실시간성이 중요하면 짧게, 변경이 적으면 길게!
4️⃣ Rate Limiting (요청 제한) 🚦
사용 사례
- 🔒 인증번호 요청 제한 (1분에 3회)
- 🔐 로그인 시도 제한 (5분에 5회)
- 🛡️ API 남용 방지 (1시간에 100회)
Redis 구현
# IP별 요청 횟수 추적
INCR rate:192.168.0.1
EXPIRE rate:192.168.0.1 60
# 현재 횟수 확인
GET rate:192.168.0.1
# → 10 (10회 요청함)
Java 구현 예시
@Service
public class RateLimitService {
public boolean isAllowed(String ip, int maxRequests, int seconds) {
String key = "rate:" + ip;
// 현재 요청 횟수 증가
Long count = redisTemplate.opsForValue().increment(key);
// 첫 요청이면 TTL 설정
if (count == 1) {
redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
}
// 최대 요청 횟수 초과 여부 확인
return count <= maxRequests;
}
}
// 컨트롤러에서 사용
@PostMapping("/send-verification")
public ResponseEntity<?> sendVerification(@RequestParam String email,
HttpServletRequest request) {
String ip = request.getRemoteAddr();
// 1분에 3회 제한
if (!rateLimitService.isAllowed(ip, 3, 60)) {
return ResponseEntity.status(429)
.body("너무 많은 요청입니다. 잠시 후 다시 시도하세요.");
}
// 인증번호 발송 로직
emailService.sendVerification(email);
return ResponseEntity.ok("인증번호가 발송되었습니다.");
}
🛡️ 실제 효과
- DDoS 공격 방어
- 무차별 대입 공격(Brute Force) 차단
- 서버 리소스 보호
5️⃣ 임시 상태 관리 📋
사용 사례
A. 비밀번호 재설정 토큰
SET reset:token:xyz123 "user@example.com" EX 1800
# 30분 유효
B. 결제 진행 상태
SET payment:session:abc "pending" EX 600
# 10분 내 결제 완료해야 함
C. 멀티스텝 폼
# 1단계 정보 저장
HSET form:session:abc step1 '{"name":"홍길동","email":"user@example.com"}'
# 2단계 정보 저장
HSET form:session:abc step2 '{"address":"서울시 강남구"}'
# 30분 TTL
EXPIRE form:session:abc 1800
Java 예시
@Service
public class FormService {
// 단계별 저장
public void saveStep(String sessionId, int step, Object data) {
String key = "form:session:" + sessionId;
String field = "step" + step;
redisTemplate.opsForHash().put(
key,
field,
objectMapper.writeValueAsString(data)
);
// 30분 TTL
redisTemplate.expire(key, 30, TimeUnit.MINUTES);
}
// 전체 폼 데이터 조회
public Map<String, String> getAllSteps(String sessionId) {
String key = "form:session:" + sessionId;
return redisTemplate.opsForHash().entries(key);
}
}
❌ Redis를 쓰면 안 되는 경우
🚫 절대 사용 금지
| 경우 | 이유 | 대안 |
|---|---|---|
| 영구 저장 데이터 | 서버 재시작 시 유실 가능 | MySQL, PostgreSQL |
| 금융/정산 핵심 데이터 | 안정성이 최우선 | 관계형 DB |
| 대용량 로그 저장 | 메모리 낭비 | Elasticsearch, MongoDB |
| 복잡한 조인 쿼리 | Key-Value 구조 한계 | 관계형 DB |
| 감사(Audit) 로그 | 영구 보관 필수 | 관계형 DB |
⚠️ 주의해서 사용
| 경우 | 주의사항 |
|---|---|
| 대용량 데이터 | 메모리 용량 제한 고려 |
| 빈번한 쓰기 | 디스크 동기화 설정 필요 |
| 크리티컬 데이터 | 백업 전략 필수 |
💡 핵심 원칙
"사라져도 되는 데이터"만 Redis에 저장하세요!
잃어버리면 안 되는 데이터는 무조건 DB에 저장하고,
Redis는 성능 향상을 위한 보조 수단으로 활용하세요.
🧠 빠른 의사결정 가이드
🔍 Redis 사용 여부 결정 플로우
질문 1: 이 데이터가 사라지면 문제가 되나요?
├─ YES → DB 사용 (MySQL, PostgreSQL)
└─ NO → 질문 2로
질문 2: 빠른 조회가 중요한가요?
├─ NO → DB 사용
└─ YES → 질문 3으로
질문 3: 자동 만료(TTL)가 필요한가요?
├─ YES → Redis 강력 추천! ⭐⭐⭐
└─ NO → 질문 4로
질문 4: 자주 조회되는 데이터인가요?
├─ YES → Redis (캐시)
└─ NO → DB 사용
✅ 체크리스트
Redis를 사용해야 하는지 확인하세요:
- 데이터가 임시적인가? (사라져도 괜찮은가?)
- 빠른 응답 속도가 필요한가? (0.001초 단위)
- TTL(자동 만료)이 필요한가?
- 자주 읽히는 데이터인가?
- 간단한 Key-Value 구조로 충분한가?
3개 이상 체크 → Redis 사용 추천!
1~2개 체크 → 상황에 따라 판단
0개 체크 → DB 사용
🎯 실무 조합 패턴
패턴 1: Redis + MySQL 황금 조합
사용자 정보 (User)
├─ MySQL: 영구 저장 (id, email, password, created_at)
└─ Redis: 세션 캐싱 (로그인 상태, 최근 활동)
상품 정보 (Product)
├─ MySQL: 영구 저장 (id, name, price, stock)
└─ Redis: 인기 상품 캐싱 (TOP 10, 최근 본 상품)
주문 정보 (Order)
├─ MySQL: 영구 저장 (주문 이력, 결제 정보)
└─ Redis: 진행 중 주문 (결제 대기, 배송 준비)
패턴 2: Write-Through 캐시
// 데이터 저장 시
public void saveProduct(Product product) {
// 1. DB에 저장
productRepository.save(product);
// 2. 캐시 업데이트
redisTemplate.opsForValue().set(
"product:" + product.getId(),
objectMapper.writeValueAsString(product),
1,
TimeUnit.HOURS
);
}
패턴 3: Cache-Aside (Lazy Loading)
// 데이터 조회 시
public Product getProduct(Long id) {
String key = "product:" + id;
// 1. 캐시 확인
String cached = redisTemplate.opsForValue().get(key);
if (cached != null) {
return objectMapper.readValue(cached, Product.class);
}
// 2. DB 조회
Product product = productRepository.findById(id).orElseThrow();
// 3. 캐시 저장
redisTemplate.opsForValue().set(
key,
objectMapper.writeValueAsString(product),
1,
TimeUnit.HOURS
);
return product;
}
🚀 Redis 시작하기
Spring Boot 설정
1. 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
2. application.yml 설정
spring:
redis:
host: localhost
port: 6379
password: # 필요시 설정
3. RedisTemplate 설정
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(
RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
}
4. 사용 예시
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void set(String key, String value, long seconds) {
redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
}
💡 마무리
✨ 핵심 정리
Redis는 다음과 같은 데이터에 최적화되어 있습니다:
- ⏳ 임시 데이터 - 인증번호, 세션, 토큰
- ⚡ 빠른 조회 - 캐시, 인기 목록
- 🔒 요청 제한 - Rate Limiting
- 📋 진행 상태 - 멀티스텝 폼, 결제 진행
🎯 한 문장 결론
Redis는 "빠르고 잠깐 쓰는 데이터"를 위한 도구이며,
인증·세션·캐시·요청 제한에 최적화된 저장소입니다.
🔥 실무 팁
- DB를 대체하지 마세요 - Redis는 보조 수단입니다
- TTL을 적극 활용하세요 - 자동 정리가 핵심입니다
- 메모리를 모니터링하세요 - 용량 관리가 중요합니다
- 캐시 전략을 세우세요 - Write-Through vs Cache-Aside
- 백업을 고려하세요 - RDB 또는 AOF 설정