카테고리 없음

레디스(Redis)란?

ddowulli 2023. 10. 8. 08:10

 

 

RDB vs NoSQL

JSP를 공부하면 세트로 따라오는 것이 데이터이다. 웹사이트를 개발하더라도 사이트에서 저장되는 데이터가 있을 것이다. 그 데이터를 어떻게 저장하고 관리할 것이며 조작할 것인지에 대해 알

dawulle.tistory.com

이전 블로그 글 중 NoSQL에 대해 공부하며 포스팅을 한 적이 있다. 그때 NoSQL 중 하나를 사용해보며 공부 후 포스팅 해보기로 했었다. 미뤄두었던 걸 이번에 진행하는 프로젝트 개발에 기능 중 하나인  장바구니 기능에 NoSQL의 종류 중 하나를 적용해보고자 하였다. 그렇다면 각가의 특징에 대해 알아야 한다고 생각하여 첫번째로 Redis에 대해 알아보고 포스팅 해보려고 한다. 

 

 

레디스(Redis)란?

  • Remote Dictionary Server 의 약자로, 오픈소스의 In-Memory 데이터베이스이다.
    키-값(key-value) 데이터 저장소로 사용되며, 메모리 기반 데이터베이스라고도 부른다.
  • 즉, 모든 데이터를 메모리에 저장하고 검색 및 처리할 수 있는 기술을 제공한다.
  • NoSQL 데이터베이스이며 주로 캐싱, 세션관리, 메시지 브로커, 실시간 분석 등 다양한 응용프로그램에 사용된다.
  • 데이터를 메모리에 저장하기때문에 빠른 읽기 및 쓰기 작업을 지원한다.
    하지만, 메모리에 저장하는 이유로 큰 데이터 집합을 다루려면 많은 메모리가 필요할 수 있다. 
  • 다양한 데이터 구조를 지원한다.(ex. 문자열, 리스트, 해시, 셋, 정렬 집합 등) 
    레디스는 다른 In-Memory DB 중 하나인 Memcache와의 가장 큰 차이점이다.
  • 데이터베이스 클러스터링을 지원하며, 단일 쓰레드로 동작한다.
    병렬처리가 필요한 작업에서는 성능 이슈가 발생할 수 있다. (관련하여 자세한 포스팅하겠다.)
  • 레디스는 Java언어를 지원하지 않지만 Redis 클라이언트 라이브러리를 사용하여 통합할 수 있다.

 

레디스 클라이언트

간단히 종류에 대해 알아보았다.

  • 레디스 서버에 연결하여 레디스 데이터 구조를 조작할 수 있게 해준다.
  • Java용 Redis 라이브러리로는 Lettuce, Redisson, Jedis 등이 있다.
    • Lettuce: 동기/비동기 및 논블로킹 I/O를 지원한다. 레디스 클러스터 지원한다.
    • Redisson: 비동기 및 논블로킹 I/O를 지원한다.
    • Jedis: 동기 지원

 

Cache Manager

캐시 추상화에서는 캐시 기술을 지원하는 캐시 매니저를 빈으로 등록해야 한다. 종류는 아래와 같다.

  • ConcurrentMapCacheManager
    • 캐시 기능을 구현하는 간단한 캐시 매니저로, 메모리 상에 캐시를 저장하여 빠른 접근이 가능하다.
    • 하지만, 용량이 제한적으로 큰 데이터를 다루거나 장기간 보관하는 경우에는 지양한다.
    • ConcurrentMap 기반의 캐시 맵을 사용한다. 동시성이 지원되는데 그래서 다중 스레드가 동시에 캐시에 접근하더라도 안전하게 동작 가능하다. 
    • 하지만, 단일 애플리케이션의 메모리 내의 캐시를 다루기 때문에 여러 컴퓨터 또는 장치들이 연결되어 분산하고 처리하는 방식에서의 캐시공유는 적합하지 않다.
  • SimpleCacheManager
    • 기본적으로 제공하는 캐시가 없다.
    • 사용할 캐시를 직접 등록하여 사용하기 위한 캐시 매니저이다.
  • EhCacheCacheManager
    • Spring에서 간단하게 사용할 수 있는 Java 기반 오픈 소스 캐시 라이브러리로,
      데몬을 가지고 있지 않고 Spring 내부적으로 동적하여 캐싱처리를 한다. 
    • 캐시를 캐시저장소에 만료시간과 함께 저장하고, 사용자 요청이 있을 경우 만료 시간 전이라면 해당 저장소에
      있는 데이터를 사용하는 방식이다.
    • 메모리 기반 및 디스크 기반 캐시를 지원하며 분산 환경에서도 사용 가능하다. 
    • 서버 애플리케이션과 라이프사이클을 같이 하므로 사용하기 간편하다.
  • CaffeineCacheManager
    • Caffeine Cache Github에서 Java를 위한 최적의 캐싱 라이브러리라고 소개하고 있다.
    • Google 오픈 소스 Guava Cache와 ConcurrentHashMap을 개선한 ConcurrentLinkedHashMap을 바탕으로 개선되어 성능을 개선하였다고 하여 고성능으로 최근 많이 사용한다. 
    • 또한 properties 나 yml 설정이 쉽다. 
  • CompositeCacheManager
    • 한 개 이상의 캐시 매니저를 사용하도록 지원해주는 혼합 캐시 매니저이다.
  • JCacheCacheManager
    • JSR-107 기반의 캐시를 사용하는 캐시 매니저이다.
    • JSR-107은 Java Community Process(JCP)의 일부로 개발된 자바 스펙의 한 종류로,
      Java Temporary Caching API를 정의하는 스펙이다. 
      이 스펙을 간단히 설명하면, 캐싱을 위한 표준 Java API를 제공하며 Java 애플리케이션에서 캐시를 사용하고 관리한다. 

 

 

의존성 추가

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

 

 

@EnableCaching

Spring에서 @Cacheable과 같은 어노테이션 기반의 캐시기능을 사용하기 위해서는 먼저 별도의 선언이 필요하다.

그래서 해당 어노테이션을 설정 클래스에 추가해주어야한다. 

// 예제 코드
@EnableCaching
@SpringBootApplication
public class FashionCommerceServerApplication {
	public static void main(String[] args) {
		SpringApplication.run(FashionCommerceServerApplication.class, args);
	}
}

 

공통 Optional Element 

Element Description Type
cacheName 캐시 이름(설정 메서드 리턴값이 저장) String[]
value cacheName의 alias String[]
key 동적인 키 값을 사용하는 SpEL표현식
동일한 cacheName을 사용하지만 구분될 필요가 있을 경우 사용되는 값
String
condition SpEL 표현식이 참일 경우에만 캐싱 적용
- or, and 등의 조건식, 논리연산이 가능
String
cacheManager 사용할 CacheManager 지정
(위의 CacheManager 자료 확인)
String

 

 

@Cacheable

적용된 메서드의 리턴값을 기준으로 캐시에 값을 저장한다.

적용할 메소드에 @Cacheable 어노테이션을 붙여주면 캐시에 데이터가 없을 경우에는 기존의 로직을 실행한 후에 캐시에 데이터를 추가하고, 캐시에 데이터가 있으면 캐시의 데이터를 반환한다.

// 예제코드
@Cacheable(cacheNames = "cartList", key = "#userId", sync = false)
    public List<ProductDto> putCartList(int userId, List<ProductDto> orderProductList) {
        List<ProductDto> productDtoList = new ArrayList<>();

Optional Element

Element Description Type
unless 캐싱을 막기 위해 사용되는 SpEL 표현식
condition과 반대로 참일 경우에만 캐싱이 적용되지 않음 
String
sync 여러 스레드가 동일한 키에 대한 값을 로드하려고 할 경우,
기본 메서드의 호출을 동기화한다.
즉, 캐시 구현체가 Thread safe 하지 않는 경우, 캐시에 동기화를 걸 수 있는 속성
boolean

 

 

 

@CacheEvict

Cache를 비우고 싶거나, DB의 데이터 삭제가 있을 때 Redis Cache에 데이터를 삭제한다.

DB에서 DELETE와 같은 삭제에서 사용한다.

// 예제코드
 @CacheEvict(cacheNames = "cartList", key = "#userId", beforeInvocation = false, allEntries = false)
    public void deleteCartList(int userId) {
        //...
    }

Optional Element

Element Description Type
allEntries 캐시 내의 모든 리소스를 삭제할지의 여부 boolean
beforeInvocation true : 메서드 수행 이전 캐시 리소스 삭제
false : 메서드 수행 후 캐시 리소스 삭제
boolean

 

@CachePut

DB의 데이터 업데이트가 있을 때 Redis Cache에 데이터를 업데이트한다.

DB에서 PUT/PATCH와 같은 업데이트에서 사용한다. 

// 예제코드
 @CachePut(cacheNames = "cartList", key = "#userId")
    public void updateCartList(int userId) {
        //...
    }

Optional Element

Element Description Type
unless 캐싱을 막기 위해 사용되는 SpEL 표현식
condition과 반대로 참일 경우에만 캐싱이 적용되지 않음
String

 

 

 

@Caching

하나의 메서드를 호출 할 때 Cacheable, CacheEvict 등 여러 개의 캐싱 동작을 수행해야 할 때 사용한다.

// 예제 코드: @Caching을 사용해 여러개의 @CacheEvict을 묶음.
@Caching(evict = {
	@CacheEvict("addresses"),
    @CacheEvict(value = "directory", key = "#customer.name")
		})
public String getAddress(Customer customer {
	//...
}

Optional Element

Element Description Type
cacheable 적용 될 @Cacheable array를 등록 Cacheable[]
evict 적용 될 @CacheEvict array를 등록 CacheEvict[]
put  적용 될 @Cacheput array를 등록 CachePut[]

 

@CacheConfig

클래스 단위로 캐시 설정을 동일하게 하고 싶을 때 사용한다.

// 예제 코드
@CacheConfig(cacheNames = {"addresses"}, cacheManager = "cacheManager")
public class CustomerDataService {
	// ..
	@Cacheable
	public String getAddress(Customer customer) {
    	//...
    }
}

Optional Element

Element Description Type
cacheNames 해당 클래스 내 정의된 캐시 작업에서의 default 캐시 이름 String[]
cacheManager 사용할 CacheManager 지정 String

 

 

 

간단히 Redis에 대해 알아보며 프로젝트에 활용해 보았다. 자주 조회되는 데이터에 대해 사용하였지만 레디스 설정과 어노테이션을 활용하여 쉽게 사용할 수 있었다. 캐시 기술을 지원하는 캐시 매니저의 다양한 종류로 특징에 맞게 다음 프로젝트 개발 시 활용할 기회를 만들어봐야겠다. 또한 다른 NoSQL 종류를 알아보고 그에 관련하여 포스팅 해보겠다. 

 


[출처 및 참고]

https://zrr.kr/RYTK

https://zrr.kr/d6Gf

https://zrr.kr/h2cy

https://zrr.kr/gmBs