Redis 개념 → 설치 → 사용 → Spring 예제까지 한 번에 정리함.
📌 1. Redis란?
Redis (REmote DIctionary Server) 는 메모리(In-Memory)에 데이터를 저장하는 Key-Value 저장소다. 빠른 조회를 위한 캐시 + 만료되는 데이터 저장소이다.
✅ Redis의 핵심 특징
- 메모리 기반 → 매우 빠름 (ms 단위)
- Key-Value 구조
- TTL(만료시간) 지원
- 캐시 / 세션 / 토큰 / 임시 데이터 관리에 최적
⚠️ 캐시는 DB처럼 쓰면 안 됨. 빠른 조회용 보조 저장소.
- 트랜잭션 보장 ❌
- 영속성 한계
- 장애 시 데이터 유실 가능
📖 예시
KEY: product:123
VALUE: { "name": "운동화", "price": 99000 }
📌 2. Redis는 언제 쓰는가?
✔ Redis 사용이 좋은 경우
- 조회가 매우 잦은 데이터
- DB까지 갈 필요 없는 데이터
- 잠시만 유지하면 되는 데이터 (TTL로 자동 만료)
- 서버 재시작과 무관
📖 예시
- 토큰 / 세션 ( 로그인 세션, Refresh Token)
- 상품 캐시
- 조회수 / 랭킹
- 임시 인증 코드
❌ Redis를 믿으면 안 되는 경우
- 최종 결제 금액
- 재고 차감
- 정합성 100% 필요한 데이터
📌 3. Windows에서 Redis 사용하기 (중요 ⚠️)
Redis는 공식적으로 Windows를 지원하지 않는다
👉 그래서 Memurai를 사용한다. (Memurai = Windows용 Redis 호환 서버)
✅3-1. Memurai 설치 방법 (Windows)
🔹 설치 파일
🔗 https://www.memurai.com/get-memurai
⚠️ 설치 중 오류 발생 시
Memurai Developer Setup Wizard ended prematurely
👉 CMD를 관리자 권한으로 실행하여 명령어 실행
msiexec /i Memurai-Developer-v4.3.2.msi /l*v "install.log"
📌 4. Redis 실행 & CLI 사용
✅ 4-1. Redis 실행
Memurai-cli.exe
👉 실행과 동시에 Redis 서버가 뜸
✅4-2. Redis CLI 접속
redis-cli
✅ 4-3. Redis 정상 동작 확인
PING
응답: PONG
📌 5. Redis 기본 명령어
✅ 5-1. 조회
🔹KEYS: 모든 키 목록 조회 (❌ 주의 - 성능 이슈)
redis-cli KEYS *
⚠️ 운영 환경에서는 절대 금지 (성능 이슈)
🔹 SCAN: 키 패턴으로 검색, 개수 제한 (안전)
redis-cli SCAN 0 MATCH order:* COUNT 100
- COUNT 100 : 한 번에 100개씩 조회
🔹 EXISTS: 키 존재 여부 확인
redis-cli EXISTS your-key
- 1 : 존재
- 0 : 없음
🔹 GET: 특정 키 값 확인
redis-cli GET "your-key"
✅ 5-2. 생성 / 갱신
🔹SET
redis-cli SET your-key "your-value" NX EX 30
*NX + EX {짧은 시간} => 중복 생성 방지, 간단한 락 용도로 쓰인다.
🔹옵션
| 옵션 | 의미 | 사용처 |
| SET | 기본 저장 | 테스트 |
| EX | TTL(초) | 캐시 |
| PX | TTL(ms) | 정밀 |
| NX | 없을 때만 | 락 |
| XX | 있을 때만 | 갱신 |
| KEEPTTL | TTL 유지 | 캐시 수정 |
✅ 5-3. 삭제
🔹DEL (여러 개 가능)
redis-cli DEL your-key key2 key3
✅ 5-4. 만료 시간 설정
🔹TTL: 키 만료 시간 확인
redis-cli TTL your-key
- > 0 : 남은 TTL (초)
- -1 : 만료 없음
- -2 : 키 없음
🔹 EXPIRE: 키 만료 설정 / 변경
redis-cli EXPIRE your-key 600
🔹PERSIST: TTL 제거 (영구 키로 변경)
redis-cli PERSIST your-key
✅ 5-5. 기타
🔹TYPE: 키 타입 확인 (디버깅 필수)
redis-cli TYPE your-key
- string
- hash
- list
- set
- zset
⚠️ 타입 모르고 GET 했다가 nil 나오는 경우 많음
🔹Hash: 구조 조회 (자주 씀)
redis-cli HGETALL your-hash-key
redis-cli HGET your-hash-key field
redis-cli HKEYS your-hash-key
💡 세션, 토큰, 복합 데이터에서 많이 사용
🔹FLUSH: 캐시 강제 초기화 (주의 ⚠️)
redis-cli FLUSHDB #현재 DB만
redis-cli FLUSHALL #전체 Redis 데이터 삭제
🔹 MEMORY: 메모리 사용량 확인
redis-cli MEMORY USAGE your-key #특정 키가 차지하는 메모리 확인
redis-cli INFO MEMORY #Redis 전체 메모리 상태 확인
📌 6. Spring Boot + Redis 연동
✅ 6-1. 의존성 추가 (pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
✅ 6-2. Redis 설정 클래스
// RedisConfig.java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// Key는 사람이 읽을 수 있도록 String
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// Value는 JSON 형태로 직렬화
GenericJackson2JsonRedisSerializer jsonSerializer =
new GenericJackson2JsonRedisSerializer();
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
return template;
}
}
💡 왜 JSON 직렬화?
- Redis CLI에서 내용 확인 가능
- 디버깅 쉬움
- 서비스 간 호환성 좋음
✅ 6-3. Redis 캐시 서비스 구현
// CacheService.java
@Service
public class CacheService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 🔍 캐시 조회
public Object getFromCache(String key) {
return redisTemplate.opsForValue().get(key);
}
// 💾 캐시 저장
public void saveToCache(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
// ⏰ TTL 포함 저장
public void saveToCache(String key, Object value, long ttlSeconds) {
redisTemplate.opsForValue().set(key, value, ttlSeconds, TimeUnit.SECONDS);
}
// ❌ 캐시 삭제
public void deleteFromCache(String key) {
redisTemplate.delete(key);
}
}
📌 7. 캐시 설계
MSA 쇼핑몰에서 상품 정보를 캐싱하는 걸 예제로 함!!
✅7-1. 흐름 예제
🔹 주문목록 조회 시
주문 서비스가 Redis에서 상품 캐시 조회
→ 없으면 상품 서비스 API 호출
→ 결과 Redis 저장
🔹 상품 수정 시
상품 서비스가 수정 이벤트 발행 → 이벤트 수신한 각 서비스가 캐시 처리
✅7-2. MSA에서 Redis 구조
- Redis Cluster 1개 (공용 인프라)
- 서비스별 Key Prefix로 논리적 분리
- 각 서비스는 자기 Prefix만 접근
Redis (공용 인프라)
┌──────────────────┐
│ order:* (주인: Order) │
│ product:* (주인: Product)│
│ auth:* (주인: Auth) │
└──────────────────┘
✅7-3. 키 설계
🎯 원칙
- 의미가 명확해야 함
- 충돌 방지
- 계층 구조
📖 예시
product:{productId}
order:{userId}:{orderId}
refreshToken:{userId}
📖 JAVA 예시
서비스별 Key Prefix + 캐시 분류 + key
private static final String ORDER_PRODUCT_KEY = "order:product:";
String cacheKey = ORDER_PRODUCT_KEY + productId;
✅7-4. TTL 설정 (필수)
일정 시간이 지나면 자동으로 캐시가 만료되도록 설정.
*이유는 17에서 자세히 설명한다!
redisTemplate.opsForValue()
.set(cacheKey, value, 600, TimeUnit.SECONDS); // 10분
✅7-5. 캐시 구조
주문서비스 기준 상품목록 캐싱 예제
🎯 핵심 원칙
“주문 판단에 필요한 최소한의 상품 정보만 캐싱한다”
✔ Redis에 넣어도 좋은 데이터
- 상품ID
- 상품명
- 썸네일
- 기본 가격 (참고용)
- 판매 상태 (ON/OFF)
❌ Redis에 넣지 말 것
- 실결제 금액 계산 로직
- 재고 수량 (특히 실시간 차감)
- 할인 정책 (쿠폰, 프로모션)
📖 구조 예제
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CachedProduct {
private int productId;
private String productName;
private BigDecimal displayPrice; //화면 표시용 가격 결제 시 상품 서비스에서 재검증 필요
private String thumbnailUrl;
private boolean onSale;
/**
* 옵션 정보 (정적 정보만)
*/
private Map<Integer, String> availableColors;
private Map<Integer, String> availableSizes;
/**
* 캐시 정합성 판단용
*/
private long version; // 또는 LocalDateTime lastModifiedAt
}
📌 8. 추천 아키텍처 패턴
🔥 이벤트는 “통보”지 “처리”가 아님
Product Service
└─ "상품이 바뀌었어!" (이벤트)
👉 각자 판단
Order Service → 아, 난 캐시 갱신해야지
Cart Service → 아, 난 캐시 삭제해야지
Search Service → 아, 색인 다시 해야지
🔹Pattern 1. Cache Aside
1️⃣ 주문시스템 → Redis 조회
2️⃣ Miss → 상품서비스 API 호출
3️⃣ 결과 Redis 저장 (TTL 설정)
Order Service
├─ Redis (상품 캐시)
└─ Product Service
🔹Pattern 2. 이벤트 기반 캐시 동기화
상품 변경 시:
Product Service
└─ 상품 변경 이벤트 발행 (Kafka / MQ)
└─ Order Service → Redis 갱신
👉 가격/상태 변경 즉시 반영
📌 9. Redis 심화 개념들
👉 운영 환경, 트래픽 증가, 장애 대응을 고려할 때 도움이 되는 내용이다
TTL + Eviction + Fallback
✅ 9-1. Redis 메모리 구조와 최대치
Redis는 인메모리(In-Memory) 데이터 저장소이므로
저장 가능한 데이터의 양은 서버의 물리적 RAM에 의해 제한된다.
📖 예시
- Redis 서버 RAM: 32GB
- Redis는 최대 32GB 범위 내에서만 데이터 저장 가능
🔹 maxmemory 설정
Redis는 사용할 수 있는 최대 메모리를 제한할 수 있다.
📖 예시: Redis가 최대 4GB까지만 메모리 사용
maxmemory 4gb
- Redis가 서버 메모리를 전부 쓰지 않도록 여유 공간 확보 필수
- 보통 전체 RAM의 50~70% 이내로 설정
🔹 캐시 용량 산정 기본 공식
(캐시 1건 평균 크기) × (최대 캐시 개수) × 여유계수(1.5~2)
📖 예시
- CachedProduct 평균 크기: 1KB
- 상품 수: 200,000개
- 여유계수: 2
1KB × 200,000 × 2 = 약 400MB
⚠️ JSON 직렬화는 생각보다 크다
→ 실측해서 잡는 게 가장 정확
✅ 9-2. 메모리가 가득 차면?
Redis가 설정된 메모리 한도를 초과하면
maxmemory-policy (Eviction Policy) 에 따라 동작한다.
🔹 주요 Eviction 정책 정리
*메모리 예측, 장애 시 복구 위해 TTL은 필수!
*실무 기본값 추천: maxmemory-policy allkeys-lru
| 정책 | 설명 | 추천도 |
| noeviction | 새 쓰기 요청 거부 | ❌ |
| allkeys-lru | 전체 키 중 오래 안 쓴 것 삭제 | ⭐⭐⭐ |
| volatile-lru | TTL 있는 키 중 오래 안 쓴 것 삭제 | ⭐ |
| allkeys-random | 전체 키 무작위 삭제 | ❌ |
| volatile-ttl | TTL 짧은 키부터 삭제 | △ |
✅ 9-3. Redis 장애 처리
Redis는 항상 살아있다고 가정하면 안 된다.
1️⃣ 캐시는 항상 Optional
CachedProduct cached = redis.get(key);
if (cached == null) {
// fallback
productServiceApiCall();
}
👉 Redis 장애 ≠ 서비스 장애
2️⃣ 캐시 미스 = 정상 흐름
- 캐시 미스 로그 ❌
- 에러 취급 ❌
👉 캐시는 최적화일 뿐, 의존 대상 아님
3️⃣ Redis 장애 시 동작 원칙
| 상황 | 동작 |
| Redis 다운 | API 직접 호출 |
| 캐시 읽기 실패 | 무시 후 진행 |
| 캐시 쓰기 실패 | 로그만 남김 |
4️⃣ Order Service 관점 핵심
- 주문 생성 / 결제 판단 ❌ Redis 의존
- 조회 화면만 Redis 활용
📌 10. 이벤트 유실 시 캐시 복구 전략
👉 Kafka/MQ는 “절대 유실 안 난다”는 전제 자체가 위험하다
👉 캐시는 언제든지 “틀릴 수 있다”는 가정으로 설계해야 한다
🔹 주문 조회용 상품 캐시 (추천)
이벤트 수신 + TTL 10분 + Cache Miss API 호출
🔹 가격/재고 민감 영역
캐시 사용 ❌
→ Product Service 실시간 조회
✅ 10-1. 이벤트 기반 캐시의 근본 한계
이벤트 기반 캐시 흐름은 보통 이렇다.
Product 변경
→ Product Service 이벤트 발행
→ Order Service consumer 수신
→ Redis 캐시 갱신
⚠️ 문제
- 이벤트 1번만 놓치면 캐시 영구 불일치
- TTL 없으면 “영원히 틀린 데이터”
👉 이벤트 = 가속 장치,
👉 정합성 보장 수단 ❌
✅ 10-2. 1차 방어선: TTL 기반 자연 복구
이벤트 유실이 나도, TTL 만료 시 자동 복구 (🚀TTL은 복구 메커니즘이다!!)
📖 예시
order:product:{productId}
TTL = 10분
- 이벤트 놓침 → 최대 10분만 틀림
- TTL 만료 → API 호출 → 최신 데이터 재캐싱
✅ 10-3. 2차 방어선: Cache Miss 시 강제 재조회
Order Service 기준 기본 패턴
CachedProduct product = redis.get(key);
if (product == null) {
product = productServiceApiCall(productId);
redis.set(key, product, TTL);
}
✔️ 이벤트 유실, Redis flush, Redis 장애 → 모두 자동 복구
✅ 10-4. 3차 방어선: 정기 캐시 검증/보정 배치
이벤트 + TTL만으로 불안하면 보정 작업 추가
매일 정해진 시간에
Product Service에서 변경된 상품 조회 (updated_at > last_sync_time)
→ Redis 재캐싱
✅ 10-5. 4차 방어선: 버전 기반 캐시 무효화
상품 데이터에 version 또는 updatedAt 포함, 결제/주문 확정 단계에서 API데이터와 비교.
📖 예시
1️⃣ 주문 화면 → 캐시 사용
2️⃣ 결제 버튼 클릭
3️⃣ Product Service 재검증 (가격/상태/version)
4️⃣ 캐시 version < 최신 version → 캐시 갱신 또는 삭제
💡 이벤트 유실 + TTL 만료 전이라도 감지 가능
✅ 10-6. 결론 “완벽한 전략은 없다” 🚀
아래 전략을 겹쳐서 써야 안전하다
| 전략 | 역할 |
| 이벤트 | 빠른 반영 |
| TTL | 자연 복구 |
| API fallback | 즉시 복구 |
| 배치 | 장기 안정성 |
| 버전 체크 | 미세 오차 제거 |
'Backend > spring (Boot)' 카테고리의 다른 글
| Connection Pool과 Size 선정 기준 (with HikariCP) (0) | 2025.09.01 |
|---|---|
| [Spring, JSP] session 생성 차단 (0) | 2025.07.26 |
| [Spring] (프로젝트 외부) 정적 리소스 처리 (0) | 2025.07.26 |
| Spring boot 예외 처리: @ControllerAdvice, @ExceptionHandler, ResponseStatusException (0) | 2025.07.26 |
| [error] java.lang.IllegalArgumentException: Name for argument of type [int] not specified (0) | 2025.02.23 |