[Redis] localhost SpringBoot + Redis

Turtle·2024년 8월 17일
0

TIL(Today I Learned)

목록 보기
6/7
post-thumbnail

🏷️Redis 도입

  • build.gradle 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
  • application.yml 작성
spring:
  profiles:
    default: local
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: 사용자 이름
    password: 패스워드
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  data:
    redis:
      port: 6379
      host: localhost

logging:
  level:
    org.springframework.cache: trace
  • RedisConfig 레디스 Configuration 코드 작성
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

	@Value("${spring.data.redis.host}")
	private String host;

	@Value("${spring.data.redis.port}")
	private int port;

	// ⭐Lettuce 라이브러리를 활용해 Redis 연결을 관리하는 객체를 생성하고
    // ⭐Redis 서버에 대한 정보(host, port)를 설정한다.
	@Bean
	public LettuceConnectionFactory lettuceConnectionFactory() {
		return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port));
	}
}
  • RedisCacheConfig 스프링 부트 캐시 Configuration 코드 작성
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
@EnableCaching
public class RedisCacheConfig {

	@Bean
	public CacheManager boardCacheManager(RedisConnectionFactory redisConnectionFactory) {
		RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
				.defaultCacheConfig()
				// ⭐Redis에 Key를 저장할 때 String으로 직렬화
				.serializeKeysWith(
						RedisSerializationContext.SerializationPair.fromSerializer(
								new StringRedisSerializer()
						)
				)
				// ⭐Redis에 Value를 저장할 때 Json으로 직렬화
				.serializeValuesWith(
						RedisSerializationContext.SerializationPair.fromSerializer(
								new GenericJackson2JsonRedisSerializer()
						)
				)
				// ⭐인메모리 데이터베이스는 저장량이 한정되어있으므로 TTL을 설정
				.entryTtl(Duration.ofMinutes(1L));
		return RedisCacheManager
				.RedisCacheManagerBuilder
				.fromConnectionFactory(redisConnectionFactory)
				.cacheDefaults(redisCacheConfiguration)
				.build();
	}
}
  • Service 측에서 레디스 캐싱을 직접적으로 활용할 수 있게끔 추가
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import spring.spirngbootredis.repository.BoardRepository;
import spring.spirngbootredis.domain.Board;

import java.util.List;

@Service
public class BoardService {

	private final BoardRepository boardRepository;

	@Autowired
	public BoardService(BoardRepository boardRepository) {
		this.boardRepository = boardRepository;
	}

	// ⭐@Cacheable : 메서드 결과를 캐싱하고 동일한 메서드가 동일한 인자로 호출될 경우 데이터베이스로부터 조회하는 것이 아니라 캐시된 결과를 반환한다.
    // ⭐@Cacheable 어노테이션은 Cache Aside 전략을 기반으로 작동한다.
    // ⭐cacheNames : 캐시 이름, key : Redis에 저장할 키, cacheManager : 사용할 cacheManager의 Bean이름 지정
	@Cacheable(cacheNames = "getBoards", key= "'board:page:' + #page + ':size' + #size", cacheManager = "boardCacheManager")
	public List<Board> getBoards(int page, int size) {
		Pageable pageable = PageRequest.of(page - 1, size);
		Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable);
		return pageOfBoards.getContent();
	}
}

🏷️Redis 적용 후 조회 성능 테스트 결과(PostMan)

🏷️정리

개인 프로젝트에 Redis를 도입하려던 차에 Redis에 대한 이해가 부족하여, 성능 개선에 대한 궁금증을 해결하기 위해 공부를 시작했다. 새로운 기술을 도입하는 것은 문제를 해결하기 위한 첫걸음에 불과하다고 생각한다. 기술 자체의 강력한 기능이나 장점도 중요하지만, 그 기술이 실제로 무엇을 해결하려는 것인지, 어떤 상황에 적합한지를 고려하는 것이 더 중요하다. 단순히 "안 써본 기술이니 한 번 도입해보자"는 접근보다는, 기술의 적합성과 문제 해결 목표에 맞게 신중하게 활용할 수 있도록 많은 공부를 해야 한다는 것을 깨달았다.

0개의 댓글