리액티브 레디스 — 기본 개념·Spring Boot 연동

2026-05-03확률과 통계 마스터 노트

리액티브 레디스 마스터 노트 시리즈 1편. Redis가 단순 캐시가 아닌 인메모리 데이터 구조 서버인 이유, WebFlux + Reactive Redis가 표준이 된 흐름, Lettuce 드라이버의 Netty 기반 논블로킹 구조, Spring Boot 3.x + Spring Data Redis Reactive 의존성 + 설정, ReactiveRedisConnectionFactory 자동 구성, Docker로 Redis 띄우기, redis-cli 기본 사용까지.

이 글은 리액티브 레디스 마스터 노트 시리즈의 첫 번째 편입니다. WebFlux 마이크로서비스 + Redis 통합은 더 이상 옵션이 아닙니다. 다만 전통 RedisTemplate은 블로킹 — WebFlux 흐름과 안 맞습니다. ReactiveRedisTemplate이 그 자리.

이 시리즈 7편은 Redis 기초·ReactiveRedisTemplate·자료구조·WebFlux 캐싱·성능·Pub/Sub·고급 주제까지. 1편의 목표 — 왜 리액티브 Redis인지, Spring Boot에 어떻게 연동하는지 손에 잡히게.

📚 학습 노트

이 시리즈는 Redis 공식 문서, Spring Data Redis 가이드, Lettuce 클라이언트 문서, Project Reactor 학습 자료 등 공개 자료를 참고해 한국어 학습 노트로 풀어쓴 자료입니다.

로컬에 Docker로 Redis를 띄우고 Spring Boot WebFlux 프로젝트에서 ReactiveRedisTemplate으로 GET/SET 한 번 해 보면 흐름이 한 번에 잡혀요.

처음 리액티브 레디스가 어렵게 느껴지는 이유

처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, **"왜 Reactive Redis인가"**가 막연합니다. 그냥 RedisTemplate 쓰면 안 되나? 둘째, Lettuce·Jedis·Redisson 클라이언트가 한 번에 등장합니다. 셋이 어떻게 다른가?

해결법은 한 가지예요. WebFlux = 논블로킹 = 블로킹 라이브러리 X. Lettuce = Netty 기반 = 자연스러운 논블로킹. 이 한 줄이 핵심. 클라이언트 비교는 5편에서 깊게.

Redis — 단순 캐시 아닌 인메모리 데이터 구조 서버

일반 사람 인식: "Redis = 캐시"
실제: "Redis = 인메모리 데이터 구조 서버"

Redis가 다루는 자료구조:

  • String — 단순 키-값
  • Hash — 객체 (필드-값 쌍)
  • List — 큐·스택
  • Set — 중복 없는 집합
  • Sorted Set (ZSet) — 점수 기반 정렬 집합
  • Stream — 로그·이벤트
  • GeoSpatial — 지리 좌표
  • HyperLogLog — 카디널리티 추정
  • Bitmap — 비트 단위

여기서 정말 중요한 시험 함정 — Redis = "키-값 캐시"는 빙산의 일각. ZSet으로 실시간 랭킹, GeoSpatial로 위치 검색, Stream으로 이벤트 큐, Pub/Sub으로 실시간 통신. 거의 모든 인메모리 데이터 패턴을 커버.

왜 인메모리?

디스크 SSD: ~100us 지연
디스크 HDD: ~10ms 지연
메모리 RAM: ~100ns 지연 (1000~100000배 빠름)

대신 휘발성 → AOF·RDB로 디스크 백업 (7편).

WebFlux + Reactive Redis 흐름

전통 RedisTemplate — 블로킹

@Autowired
private RedisTemplate<String, String> redisTemplate;

public String getUser(String id) {
    return redisTemplate.opsForValue().get("user:" + id);  // 블로킹!
}

WebFlux의 핵심 = 논블로킹 이벤트 루프. 블로킹 호출이 들어오면 이벤트 루프가 멈춤 → 처리량 폭락.

ReactiveRedisTemplate — 논블로킹

@Autowired
private ReactiveRedisTemplate<String, String> redisTemplate;

public Mono<String> getUser(String id) {
    return redisTemplate.opsForValue().get("user:" + id);  // 논블로킹
}

Mono/Flux 반환. WebFlux 흐름과 자연스럽게.

여기서 정말 중요한 시험 함정 — WebFlux + RedisTemplate(블로킹) = 안티패턴. 한 줄의 블로킹 호출이 전체 처리량 망가뜨림. 항상 ReactiveRedisTemplate.

Redis 클라이언트 3종

클라이언트 특징 Reactive
Jedis 단순·전통, 동기 X (블로킹)
Lettuce Netty 기반, 비동기 O (Reactive 표준)
Redisson 고수준 API + 분산 락 O (ReactiveRedissonClient)

여기서 시험 함정이 하나 있어요. Spring Boot 2.0+ 기본 = Lettuce. Jedis는 옛날 표준. 새 프로젝트는 Lettuce 또는 Redisson.

Spring Boot 의존성

// build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation 'org.springframework.boot:spring-boot-starter-data-redis-reactive'

    // Redisson (선택)
    implementation 'org.redisson:redisson-spring-boot-starter:3.x'
}

spring-boot-starter-data-redis-reactive = Reactive Redis Template + Lettuce 자동 포함.

설정 (application.yml)

spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: ${REDIS_PASSWORD:}
      timeout: 5s
      lettuce:
        pool:
          max-active: 8
          max-idle: 8
          min-idle: 0

Spring Boot 자동 구성:

  • ReactiveRedisConnectionFactory (Lettuce 기반)
  • ReactiveRedisTemplate<String, String>
  • ReactiveStringRedisTemplate

Docker로 Redis 띄우기

# 기본 — 인증 X
docker run -d -p 6379:6379 --name redis redis:7-alpine

# 영속화 + 인증
docker run -d -p 6379:6379 --name redis \
  -v redis-data:/data \
  redis:7-alpine \
  redis-server --appendonly yes --requirepass "secret"

docker-compose

version: '3.8'
services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s

volumes:
  redis-data:

redis-cli 기본 명령

# 컨테이너 진입
docker exec -it redis redis-cli

# 기본
> SET name "Alice"
OK
> GET name
"Alice"

> KEYS *
1) "name"

> DEL name
(integer) 1

> PING
PONG

여기서 시험 함정이 하나 있어요. KEYS * 운영 환경 절대 X. O(N) 동기 명령 = Redis 전체 멈춤. 운영은 SCAN을 점진적으로.

> SCAN 0 MATCH user:* COUNT 100
1) "256"
2) 1) "user:1"
   2) "user:2"

첫 ReactiveRedisTemplate 코드

@Service
public class UserCacheService {

    @Autowired
    private ReactiveRedisTemplate<String, String> redisTemplate;

    public Mono<Void> set(String id, String value) {
        return redisTemplate.opsForValue()
            .set("user:" + id, value, Duration.ofMinutes(5))
            .then();
    }

    public Mono<String> get(String id) {
        return redisTemplate.opsForValue().get("user:" + id);
    }

    public Mono<Boolean> delete(String id) {
        return redisTemplate.delete("user:" + id).map(n -> n > 0);
    }
}

WebFlux Controller에서:

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserCacheService cache;

    @GetMapping("/{id}")
    public Mono<ResponseEntity<String>> get(@PathVariable String id) {
        return cache.get(id)
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());
    }
}

TTL — Time To Live

자동 만료 — 캐시의 핵심.

redisTemplate.opsForValue().set("key", "value", Duration.ofMinutes(5));
> SET key value EX 300       # 300초 후 만료
> TTL key                    # 남은 시간
(integer) 295
> PERSIST key                # TTL 제거 (영구)

여기서 정말 중요한 시험 함정 — TTL 없는 캐시 = 메모리 누수. 모든 캐시 키에 TTL 필수. 운영 환경 표준.

Database 분리

Redis 16개 데이터베이스 (0~15):

spring:
  data:
    redis:
      database: 0    # 기본
> SELECT 1
> KEYS *   # database 1만 보임

여기서 시험 함정이 하나 있어요. Redis Cluster는 database 1개만 (0). 단일 인스턴스에서만 다중 DB 가능. Cluster 환경에선 키 prefix로 분리.

환경 비교

환경 권장
개발 Docker (단일 노드)
스테이징 Docker Compose
운영 Redis Sentinel(HA) 또는 Redis Cluster

운영 — 6편(Cluster·HA)에서 다룸.

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 1편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • Redis = 인메모리 데이터 구조 서버 (단순 캐시 X)
  • 자료구조 — String·Hash·List·Set·ZSet·Stream·GeoSpatial·HLL·Bitmap
  • 인메모리 = 100ns (디스크 1000100000배 빠름)
  • 휘발성 → AOF·RDB 백업 (7편)
  • WebFlux + RedisTemplate = 안티패턴
  • WebFlux = 논블로킹, RedisTemplate = 블로킹
  • ReactiveRedisTemplate이 답
  • Mono/Flux 반환, WebFlux 흐름 자연스러움
  • 클라이언트 3종 — Jedis(블로킹) / Lettuce(Netty, 표준) / Redisson(고수준+분산락)
  • Spring Boot 2.0+ 기본 = Lettuce
  • 의존성 — spring-boot-starter-data-redis-reactive
  • 자동 구성 — ReactiveRedisConnectionFactory + ReactiveRedisTemplate
  • 설정 — host/port/password/timeout/pool
  • Docker 띄우기 — docker run -d -p 6379:6379 redis:7-alpine
  • 영속화 — --appendonly yes
  • redis-cli — SET·GET·DEL·KEYS·SCAN·PING
  • KEYS * 운영 X (O(N) 멈춤) → SCAN 사용
  • TTL 없는 캐시 = 메모리 누수
  • 모든 캐시 키 TTL 필수
  • Database 16개 (0~15) — 단일 인스턴스만
  • Redis Cluster = DB 1개 (0)
  • 운영 환경 — Sentinel(HA) 또는 Cluster

시리즈 다른 편

공식 문서: Redis Documentation / Spring Data Redis Reference 에서 더 깊이.

다음 글(2편)에서는 ReactiveRedisTemplate의 5가지 Operations·Redisson과의 차이·Serializer 설정까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!