Backend/spring (Boot)

Redis란? (Spring 연동)

dddzr 2026. 1. 7. 21:22

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 즉시 복구
배치 장기 안정성
버전 체크 미세 오차 제거