Header Banner
GG Logo

Future Engineering

기술의 최전선을 기록합니다.

기술 자료/Redis/Spring Boot와 Redis 기본 설정과 사용법

Spring Boot와 Redis 기본 설정과 사용법

Redis약 1개월 전

Spring Boot에서 Redia를 쉽게 연동하고 활용할 수 있도록 돕는 spring-boot-starter-data-redis의존성에 대해 사용 방법을 작성해봤습니다.

 

spring-boot-starter-data-redis란?

Spring Boot 환경에서 Redis를 사용하기 위한 의존성입니다. 복잡한 설정 없이 쉽게 연결할 수 있게 도와줍니다.

  • 자동 구성 지원: Redis 서버와의 연결을 관리하는 RedisConnectionFactory, 데이터 조작을 담당하는 RedisTemplate 등 핵심 객체들을 자동으로 스프링 빈(Bean)으로 등록해줍니다.

  • Lettuce 클라이언트 기본 내장: 현재 업계 표준으로 자리 잡은 고성용 비동기 Redis 클라이언트인 Lettuce가 기본으로 포함되어 있어, 별도의 클라이언트 라이브러리 설정이 필요 없습니다.

  • 고수준 추상화 제공: RedisTemplate 같은 템플릿 클래스를 제공하여, Redis의 다양한 데이터 타입(String, List, Hash 등)을 Java에서 객체지향적으로 편리하게 다룰 수 있도록 돕습니다.

결론적으로, 개발자는 Redis와의 연결이나 세부적인 설정에 대한 부담 없이 비즈니스 로직에 더 집중할 수 있습니다.

 

프로젝트 설정

의존성 추가 (Maven pom.xml)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Redis 연결 설정

application.yml 파일에 Redis 서버 접속 정보를 설정

spring:
  data:
    redis:
      host: localhost      # Redis 서버 호스트 (기본값: localhost)
      port: 6379           # Redis 서버 포트 (기본값: 6379)
      password:            # Redis 서버 비밀번호 (설정한 경우)
      database: 0          # 사용할 데이터베이스 인덱스 (0~15, 기본값: 0)

이 설정만으로 Spring Boot 애플리케이션은 시작 시 Redis 서버와의 자동 연결됩니다.

 

RedisTemplate Bean 커스터마이징

Redis 연결만으로 Redis를 사용할 수 있는 건 아닙니다. RedisTemplate을 반드시 설정해야합니다.

일반적으로 config 폴더에 RedisConfig.java를 작성하면 됩니다. 이외 다양한 기능이 존재하지만 기본적으로 제공 받은 Template만 작성해놨습니다.

// src/main/java/com/example/config/RedisConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        // Key 직렬화 방식: String
        template.setKeySerializer(new StringRedisSerializer());

        // Value 직렬화 방식: JSON
        // 객체를 JSON 형태로 저장하여 가독성을 높이고 다른 시스템과의 연동을 용이하게 함
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        // Hash 자료구조의 Key, Value 직렬화 방식 설정
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

        return template;
    }
}

 

위와 같이 설정 후 간단한 캐싱 예시를 확인해보겠습니다. 게시글 조회입니다.

// src/main/java/com/example/service/PostService.java
import com.example.dto.PostDto;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.time.Duration;

@Slf4j
@Service
@RequiredArgsConstructor
public class PostService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final ObjectMapper objectMapper; // Redis에서 가져온 Object를 DTO로 변환하기 위해 사용

    /**
     * 특정 ID의 게시글 조회 (Cache-Aside 패턴 적용)
     */
    public PostDto getPostById(Long postId) {
        final String key = "post::" + postId; // Redis 키 정의: "객체타입::ID"

        // 1. 캐시에서 데이터 조회 시도
        Object cachedPost = redisTemplate.opsForValue().get(key);

        if (cachedPost != null) {
            log.info("Cache Hit: post id {}", postId);
            // 캐시에 데이터가 있으면 DTO로 변환하여 반환
            return objectMapper.convertValue(cachedPost, PostDto.class);
        }

        // 2. 캐시에 데이터가 없으면 DB에서 조회 (Cache Miss)
        log.info("Cache Miss: Fetching from DB for post id {}", postId);
        PostDto postFromDb = findPostInDatabase(postId); // DB 조회 로직

        // 3. DB에서 조회한 데이터를 캐시에 저장 (만료 시간 10분 설정)
        redisTemplate.opsForValue().set(key, postFromDb, Duration.ofMinutes(10));

        return postFromDb;
    }

    /**
     * 게시글 수정 시 캐시 데이터 무효화
     */
    public void updatePost(PostDto postDto) {
        // 1. DB 데이터 업데이트
        log.info("Updating post in DB for id {}", postDto.getId());
        // ... 실제 DB 업데이트 로직 ...

        // 2. 캐시 데이터 삭제 (Cache Invalidation)
        // 수정된 데이터를 캐시에 바로 반영(put)할 수도 있지만,
        // 정합성을 위해 삭제(evict)하는 것이 더 간단하고 안전한 전략입니다.
        final String key = "post::" + postDto.getId();
        redisTemplate.delete(key); // 해당 게시글 캐시 삭제
        log.info("Cache evicted for post id {}", postDto.getId());
    }

    // --- 아래는 데이터베이스 연동을 시뮬레이션하는 더미(dummy) 메서드입니다. ---
    private PostDto findPostInDatabase(Long postId) {
        // 실제로는 DB에서 `SELECT * FROM posts WHERE id = ?` 쿼리를 실행합니다.
        log.info("DB Query for post id {}", postId);
        return new PostDto(postId, "DB에서 가져온 제목 " + postId, "DB에서 가져온 내용입니다.");
    }
}

 

Redis Operations 살펴보기

RedisTemplate이 제공하는 다양한 자료구조입니다. 

  • opsForValue(): Strings. 가장 기본적인 Key-Value 형태. 위의 캐싱 예제에서 사용되었습니다.

  • opsForList(): Lists. 순서가 있는 데이터 목록. 메시지 큐, 타임라인 등에 활용됩니다.

  • opsForSet(): Sets. 순서가 없고 중복을 허용하지 않는 데이터 집합. 태그, 친구 목록 등에 사용됩니다.

  • opsForZSet(): Sorted Sets. Set에 Score가 추가되어 정렬된 상태를 유지. 랭킹보드, 자동완성 등에 매우 유용합니다.

  • opsForHash(): Hashes. 하나의 Key 아래에 여러 필드와 값을 저장하는 구조. 객체 정보를 저장하기에 적합합니다.

키워드

Spring Boot RedisRedisTemplateRedis 캐싱