[Redis] 스프링에서 레디스 사용하기 — Lettuce 편

y001·2025년 4월 19일
0
post-thumbnail

Spring Boot에서 Redis를 사용하는 가장 기본적인 방법은 Lettuce 클라이언트를 활용하는 것이다. 별도의 의존성 추가 없이도 Spring Boot Starter를 사용하면 Lettuce 기반의 Redis 설정이 자동으로 구성되며, 복잡하지 않은 데이터 캐싱, 세션 저장, 공유 상태 관리 등에 널리 사용된다.

이번 글에서는 Lettuce의 기본 개념부터 실제 사용 방법, 그리고 단점까지를 정리해보며, 왜 다음 편에서 Redisson과 Lua를 도입하게 되는지를 자연스럽게 연결해보려 한다.


Lettuce란?

Lettuce는 Java로 개발된 Redis 클라이언트로, 다음과 같은 특징을 갖는다:

  • Netty 기반의 비동기/넌블로킹 I/O 처리: 높은 성능과 효율적인 리소스 사용이 가능
  • 스레드 세이프(Thread-safe): 하나의 커넥션을 여러 스레드에서 안전하게 공유할 수 있음
  • Reactive 프로그래밍 지원: 비동기 흐름 제어에 적합한 구조 제공 (Future, Reactive API 등)
  • Redis Sentinel, Cluster 등 고급 기능 지원
  • Spring Boot의 기본 클라이언트: 별도 설정 없이 기본적으로 Lettuce를 사용하게 된다

공식 문서: https://lettuce.io/
GitHub 저장소: https://github.com/lettuce-io/lettuce-core

간단히 말해, 단일 명령어 중심의 Redis 사용에 적합한 고성능 클라이언트라고 할 수 있다.


Lettuce 기본 설정 방법

Spring Boot에서는 application.yml에 다음과 같이 설정하면 자동으로 Lettuce가 적용된다:

spring:
  redis:
    host: localhost
    port: 6379

Spring Data Redis와 통합되어, 개발자는 RedisTemplate 혹은 StringRedisTemplate만 주입 받아 사용하면 된다.


RedisTemplate 실습 예제

Lettuce를 사용하는 대표적인 방법은 StringRedisTemplate을 통해 Redis 명령어를 실행하는 것이다.

1. 문자열 저장 및 조회

@Autowired
private StringRedisTemplate stringRedisTemplate;

stringRedisTemplate.opsForValue().set("key", "value");
String value = stringRedisTemplate.opsForValue().get("key");
System.out.println("Redis value: " + value);

2. 카운터 증가 (INCR)

stringRedisTemplate.opsForValue().increment("counter");

3. TTL 설정과 만료 키 저장

stringRedisTemplate.opsForValue().set("tempKey", "123", Duration.ofMinutes(5));

이렇게 기본적인 set, get, incr, expire 명령어는 매우 직관적이며, 로컬 캐시처럼 간편하게 Redis를 사용할 수 있다.


Lettuce의 한계와 실무 적용 시 주의점

Lettuce는 간단한 key-value 저장이나 TTL 기반의 캐싱에는 매우 적합하지만, 다음과 같은 실무 시나리오에서는 확실한 한계를 가진다:

1. 원자성 보장 어려움

Lettuce는 기본적으로 Redis 명령어 단위의 요청을 처리한다. 여러 명령어를 조합해서 사용할 경우, 네트워크를 오가면서 중간에 다른 클라이언트가 같은 키에 접근할 수 있다. 이로 인해 Race Condition이 발생할 수 있으며, 원자성이 깨질 수 있다.

예를 들어, 다음과 같은 흐름은 Java 코드 수준에서는 안전하지 않다:

redis.zadd(key, now, now);
redis.zremrangebyscore(key, 0, now - 60000);
Long count = redis.zcard(key);
if (count > limit) { redis.set(blockKey, "1"); }

이런 복잡한 흐름은 하나의 명령으로 처리되어야 안정적인데, Lettuce는 이를 지원하지 않는다.

2. 조건문, 흐름 제어 부족

트랜잭션(MULTI/EXEC)을 사용하더라도 내부에서 조건문(IF, ELSE) 같은 흐름 제어는 불가능하다. Redis는 기본적으로 단순한 명령 실행기이기 때문에 분기 로직이나 조건 기반 처리에는 적합하지 않다.

3. RateLimit, 동시성 제어 구현 난이도

초당 요청 수 제한(RateLimit), 좌석 중복 예약 방지 등의 고급 기능은 명령어 조합만으로는 구현하기 어렵다. 결국 Lua 스크립트나 락 처리 도구의 도움을 받아야 한다.


정리하며: Lettuce는 Redis 입문의 좋은 출발점

Lettuce는 다음과 같은 환경에서 유용하다:

  • 단일 명령 중심의 캐시 처리
  • 세션 저장소로서의 Redis 활용
  • TTL 기반 데이터 만료 처리

하지만, 실무에서는 단일 명령어 이상으로 복잡한 흐름을 요구하는 경우가 많다.
대표적인 예로는 API 요청 제한, 동시성 제어, 락 기반 자원 보호 같은 것들이 있다.

0개의 댓글