728x90
반응형

https://spring.io/projects/spring-data-redis

 

Spring Data Redis

Spring Data Redis, part of the larger Spring Data family, provides easy configuration and access to Redis from Spring applications. It offers both low-level and high-level abstractions for interacting with the store, freeing the user from infrastructural c

spring.io

Spring Data Redis 란 무엇인가?

The Spring Data Redis (SDR) framework makes it easy to write Spring applications that use the Redis key-value store by eliminating the redundant tasks and boilerplate code required for interacting with the store through Spring’s excellent infrastructure support.

Spring Data Redis 는 Spring project 에서 Redis의 데이터를 쉽게 관리할 수 있게 해주는 Framework이다. RDB나 NoSQL의 경우도 각각의 Framework을 가지고 있어서 개발을 편리하게 해준다. 

 

Spring Data Redis Dependency 추가

<dependencies>

  <!-- other dependency elements omitted -->

  <dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.6.0</version>
  </dependency>

</dependencies>

Dependency는 위와 같이 추가하면 되는데, Spring boot framework을 사용중이라면 아래와 같이 추가하면 된다. 

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

 

Spring boot dependency를 추가하면 좋은 점은 많이 사용되고 있는 Redis client인 LettuceJedis가 같이 추가된다. 

 

이 문서에서는 Redis 연결을 위한 작업이 아니라 Redis key를 어떻게 원하는 방식으로 추가할 것인가를 고민해보도록 하겠다. 

 

Spring Data Redis의 사용

Spring Data Redis는 사용하면 JPA 처럼 코드를 통해 Redis의 값을 저장하고 읽어 올 수 있다. 그것이 복잡한 Object 형태라고 하더라도 세분화하여 자체적으로 Key값을 만들어서 저장한다. 

 

Default Key Value

Spring Data Redis에서의 기본 key 값은 Model의 구조에 결정된다. 

@RedisHash("people")
public class Person {

  @Id String id;
  String firstname;
  String lastname;
  Address hometown;
}

유저의 Person을 저장한다고 하였을 때 간단하게 위와 같이 Model을 만들 수 있다. Key 명에 대해서 생각할 때 중요한 부분은 

`@RedisHash` annotation이다. 이 annotation은 이 Model이 Redis의 Entity라는 것을 나타내줄 뿐더러 Key의 Prefix를 결정한다. 위의 예제에서는 @RedisHash("people")이라고 되어 있는데 이럴 경우 jwtToken 이라는 이름으로 Key이름이 시작되게 된다. 

`@RedisHash`만 사용할 경우 `getClass().getName()`의 리턴값이 기본으로 들어가게 된다. 

 

즉 아래와 같은 key 값이 만들어진다. (ex. e2c7dcee-b8cd-4424-883e-736ce564363e 는 생성된 Id 값)

 

SADD people e2c7dcee-b8cd-4424-883e-736ce564363e

 

@Indexed annotation

@RedisHash("people")
public class Person {

  @Id String id;
  @Indexed String firstname;
  String lastname;
  Address hometown;
}

위의 예제의 경우 `@Indexed` annotation이 추가된 것을 볼 수 있다. `@Indexed`을 추가되면 Secondary Index가 추가된다고 생각하면 된다. 이 말은 사용자가 Key 값에 원하는 구분자를 추가하여 검색을 용이하게 하는 역할을 한다. 

 

예를 들어 아래와 같이 Redis에 Data를 저장시킨다. 

repository.save(new Person("rand", "althor"));

이 경우 실제 Redis에서는 아래와 같은 명령들이 수행된다. 

HMSET "people:19315449-cda2-4f5c-b696-9cb8018fa1f9" "_class" "Person" "id" "19315449-cda2-4f5c-b696-9cb8018fa1f9" "firstname" "rand" "lastname" "althor" 
SADD  "people" "19315449-cda2-4f5c-b696-9cb8018fa1f9"                           
SADD  "people:firstname:rand" "19315449-cda2-4f5c-b696-9cb8018fa1f9"            
SADD  "people:19315449-cda2-4f5c-b696-9cb8018fa1f9:idx" "people:firstname:rand"

우선 HMSET 명령어를 통해서 Model에 입력된 전체 정보가 HashMap으로 저장된다. 그때의 key값은 `Prefix:Id` 구조로 저장된다. 

하지만 사용자의 검색을 위해서 SADD "people:firstname:rand" 라는 Set에 Id를 저장해 두고 사용자의 `repository.findByFirstname()` 검색이 가능하도록 저장을 한다. 

마지막 라인의 경우 Secondary Index의 Update 와 Delete를 위해 Set을 저장한다. 이 곳에는 전체 Secondary Index들을 저장한다고 생각하면 된다. 

 

오늘은 간단하게 어떻게 Key가 생성되는지 알아보았다. 

 

사실 이 내용에 대해서 공부하게 된 이유는 내가 개발하고 있는 서비스에서 Redis Key Convention(Key naming rule)을 가져갈 것인지 고민하면서 시작되었다. MSA(Micro Service Architecture)에서 여러 Service에서 Redis에 정보를 저장할 경우 Key 값의 구조를 잘 만들어야지 나중에 어떠한 이유로 인해 key값을 확인해야할 때 또는 서비스에서 값을 가져오기 위해 Key값을 만들 때 쉽게 할 수 있을 것 같기 때문이다. 

 

이 부분에 대한 고민은 다음 포스트로 넘기겠다. 

728x90
반응형
728x90
반응형
$ helm install -f values.yaml my-release bitnami/redis​
$ helm repo add bitnami https://charts.bitnami.com/bitnami

현재 구현하고 있는 Service의 경우 Redis를 사용해야 하기 때문에 Redis는 local에 설치하였다. 

 

요즘 추세가 Kubernetes operator를 사용하여 설치하지만 Local Kubernetes를 이용해야 하고, Service type을 NodePort를 사용하여 IDE에서 테스트를 하고 싶었기 때문에 Helm chart를 이용하고 싶었다. 그리고 Github에 values.yaml를 저장해두면 설정 파일의 버전을 관리할 수 있으니 이 방법을 택했다. 

 

현재 가장 잘 관리되고 있는 redis의 Helm chart는 bitnami에서 관리되는 Chart 이다. 아래 경로를 참조하기 바란다. 

 

https://github.com/bitnami/charts/tree/master/bitnami/redis

 

GitHub - bitnami/charts: Bitnami Helm Charts

Bitnami Helm Charts. Contribute to bitnami/charts development by creating an account on GitHub.

github.com

 

모든 설치방법과 상세한 옵션은 위의 사이트에 자세하게 나와 있지만 간단하게 master 1개와 replica 1개를 설치하는 방법을 공유하고자 한다. 이 또한 나의 기억을 유지하기 위한 방법이므로... ㅎㅎ

 

Helm Repository 등록

bitnami의 chart를 사용하기 위해서는 우선 Helm repository를 등록해야 한다. 

$ helm repo add bitnami https://charts.bitnami.com/bitnami

 

Installation

변경된 values.yaml과 함께 설치를 하기 위해서는 `-f` 옵션을 이용한다. `my-release` 부분은 원하는 배포명을 입력하면 된다. 

$ helm install -f values.yaml my-release bitnami/redis

 

Uninstallation

$ helm delete my-release

 

변경한 Configuration in values.yaml

1. Service 변경

NodePort 30379를 open 하였다. 

service:
    type: NodePort
    port: 6379
    nodePort: 30379
    externalTrafficPolicy: Cluster

2. Replica count 변경

리소스 문제가 있으므로 replica count 는 1로 설정하였다. 

replica:
    replicaCount: 1

3. Persistence Volume 설정

Local 환경의 Volume은 yaml 파일로 우선 생성한 후 연결하였다. 개발용으로 많은 데이터를 저장하지 않을 것이기 때문에 1Gi 로 셋팅하였다. 

persistence:
    existingClaim: "redis-pvc"

 

Persistence Volume chart

아래 저장소의 Helm chart로 volume을 설치하였다. 

 

저장소 Link : https://github.com/coolexplorer/k8s-charts/tree/main/charts/volumes/charts/redis-vol

 

GitHub - coolexplorer/k8s-charts: Kubernetes Helm Chart Repository for the environment for Software Quality via kind and k3d

Kubernetes Helm Chart Repository for the environment for Software Quality via kind and k3d - GitHub - coolexplorer/k8s-charts: Kubernetes Helm Chart Repository for the environment for Software Qual...

github.com

 

728x90
반응형

'Infrastructure > redis' 카테고리의 다른 글

Redis란?  (0) 2022.01.11
728x90
반응형

Server API의 Request 나 Response 의 String이 모두 영어로 되어 있을 경우에는 문제가 없지만, 에러메세지나 Validation 메세지 등을 한글로 보낼 경우에는 `UTP-8` Encoding 을 사용해야 한다. 그럼 언어를 Character Encoding을 설정하는 방법에 대해서 알아보자. 

 

Spring에서 Character Encoding을 설정하기 위해서는 Configuration annotation을 활용하여 Bean으로 Character Encoding Filter를 등록시키면 된다. 

 

내 개인 프로젝트에서는 아래와 같이 간단하게 AppConfig class를 만들어 두었다. 

 

 

 

728x90
반응형
728x90
반응형

Webserver 개발할 때 Database 나 Redis 등은 필수로 사용하게 된다. 이 때 API로 들어오는 데이터(DTO)를 Database에 저장되는 실제 Model로 복사하는 경우가 매번 발생하게 된다. 이때마다 chain이나 별도 function을 만들어서 복사를 할 수 없다. 왜냐하면 반복해서 넣어야 하는 동일한 코드가 너무 많기 때문이다. 

 

이를 해결하기 위해서 ModelMapper를 사용한다. ObjectMapping을 쉽게 해주는 Library라고 보면 된다.

Applications often consist of similar but different object models, where the data in two models may be similar but the structure and concerns of the models are different. Object mapping makes it easy to convert one model to another, allowing separate models to remain segregated.

ModelMapper의 목적은 아래와 같다. 

The goal of ModelMapper is to make object mapping easy, by automatically determining how one object model maps to another, based on conventions, in the same way that a human would - while providing a simple, refactoring-safe API for handling specific use cases.

Object mapping을 자동으로 이름이나 자료형을 가지고 판단하여 수행을 해준다. 반복된 코드를 줄여주기 때문에 효율적이고 휴먼에러는 줄여주는 역할도 한다고 하겠다. 

 

Dependency 추가

ModelMapper를 사용하기 위해서는 우선 Dependecy를 추가한다.  이 글에서는 2.4.4 버전을 사용한다. 

글을 쓰는 시점에서 최신 버전은 3.0.0 이다. 
<properties>
	<modelMapper.version>2.4.4</modelMapper.version>
</properties>

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>${modelMapper.version}</version>
</dependency>

 

ModelMapper Configuration 추가

Default option으로 사용해도 큰 문제는 없지만, 난 MatchStrategies 를 Strict 하게 하도록 하였고, Null value가 Object에 있어도 Mapping이 되도록 설정하였다. 

@Configuration
public class ModelMapperConfig {
    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT).setSkipNullEnabled(true);

        return modelMapper;
    }
}

 

Usage

사용방법은 간단하다. 아래의 예제는 ModelMapper object를 사용하였는데 위 설정으로 Bean에 등록을 하였으니 Dependecy Injection 으로 사용해도 된다. 

 

Order & OrderDTO

class Order {
  Customer customer;
  Address billingAddress;
}

class Customer {
  Name name;
}

class Name {
  String firstName;
  String lastName;
}

class Address {
  String street;
  String city;
}

class OrderDTO {
  String customerFirstName;
  String customerLastName;
  String billingStreet;
  String billingCity;
}
ModelMapper modelMapper = new ModelMapper();
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);

위와 같이 2개의 Model이 있고 Order model로 생성된 order object를 사용하여 OrderDTO object를 생성하는 코드이다. 

놀라운 점은 하위 Object의 variable까지 Mapping 시킨다는 점이다. 

 

앞으로의 코드에서 많이 사용되는 부분이라 우선 정리하였다. 

728x90
반응형

+ Recent posts