Home
Backend Engineering
SpringBoot-Redis 로 만든 디저트가게 예제
울이
울이
May 07, 2022
1 min

Table Of Contents

01
목차
02
스택
03
레디스서버 띄우기
04
Configuration 작성하기
05
CRUD API 작성하기
  • SpringBoot 와 Redis를 이용한 디저트가게 예제
  • Redis를 사용하기위해서 디저트가게 예제를 만들어보자

목차

스택

  • SpringBoot
    • Lombok
    • Spring Reactive Web
    • Spring Data Reactive Redis
    • Validation
  • Gradle
  • Java 11 +
  • Redis

레디스서버 띄우기

  • 레디스 서버를 실행시켜야 함
  • 로컬에서 임베드로 생성하거나, 로컬에 Docker로 생성하거나, 클라우드에 설치 된 redis 사용
  • docker-compose를 사용해서 설치 함
    • docker-compose.redis.yml
      version: "3"
      services:
          redis-docker:
              image: redis:latest
              command: redis-server --requirepass qwerqwer123 --port 6379
              container_name: "docker-redis"
              labels:
              - "name=redis"
              - "mode=standalone"
              volumes:
              - /Users/wool/Database-docker/data/redis:/data
              ports:
              - 6379:6379
      
    • redis에 비밀번호를 적용하지 않는다면 --requirepass 옵션을 빼고 작성
    • redis서버 실행
      $ docker-compose -f docker-compose.redis.yml up -d
      

Configuration 작성하기

  • ReactiveRedisConfiguration.java

  • Redis와 Spring을 연결하기 위해 설정 파일을 작성

  • reactRedisConnectionFactory 빈을 생성하여 레디스 연결 팩토리를 생성

    @Bean
    public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
        return new LettuceConnectionFactory(
            Objects.requireNonNull(env.getProperty("spring.redis.host")),
            Integer.parseInt(Objects.requireNonNull((env.getProperty("spring.redis.port"))))
        );
    }
    

    혹은 @Value어노테이션을 사용해서 아래와 같이 데이터를 깔끔하게 정리 할 수 있음

        @Value("${spring.redis.host}")
        private String redisHost;
    
        @Value("${spring.redis.port}")
        private int redisPort;
    
        @Bean
        public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
            return new LettuceConnectionFactory(redisHost, redisPort);
        }
    
  • Redis의 데이터를 주고받아야 하기 때문에 JSON형식을 지원하는 Jackson 라이브러리를 사용한 Operation Bean을 세팅한다.

    @Bean
    public ReactiveRedisOperations<String, Object> redisOperations(ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
    
        RedisSerializationContext.RedisSerializationContextBuilder<String, Object> builder =
                RedisSerializationContext.newSerializationContext(new StringRedisSerializer());
    
        RedisSerializationContext<String, Object> context = builder.value(serializer).hashValue(serializer)
                .hashKey(serializer).build();
    
        return new ReactiveRedisTemplate<>(reactiveRedisConnectionFactory, context);
    }
    

CRUD API 작성하기

  • CRUD를 작성하기 위해 우선 모델 클래스가 필요

Domain 모델 작성

  • 도메인 객체 생성하기
    • pk, 제품명, 카테고리, 설명, 가격, 출시일 을 가진 Dessert 도메인객체 생성

Database에 접근하는 Repository 작성

  • Redis 데이터베이스와 연결 할 Repository를 작성한다

  • Interface를 사용해서 CRUD 기능을 명시하고, 구현체를 사용해 각 내부 로직을 구현

  • JSON 파싱을 위해서 ObjectMapperUtils 클래스 생성

  • Redis와 연결을 위해서 ReactiveRedisComponent 클래스 생성

  • DessertRepository

    public interface DessertRepository {
    
        Mono<Dessert> save(Dessert dessert);
    
        Mono<Dessert> get(String key);
    
        Flux<Dessert> getAll();
    
        Mono<Long> delete(String id);
    }
    
  • RedisDessertRepository

    public class RedisDessertRepository implements DessertRepository {
    
        private ReactiveRedisOperations<String, Object> redisOperations;
    
        public RedisDessertRepository(ReactiveRedisOperations<String, Object> redisOperations) {
            this.redisOperations = redisOperations;
        }
    
        @Override
        public Mono<Dessert> save(Dessert dessert) {
            return redisOperations.opsForValue().set(dessert.getId(), dessert);
        }
    
        @Override
        public Mono<Dessert> get(String key) {
            return redisOperations.opsForValue().get(key);
        }
    
        @Override
        public Flux<Dessert> getAll() {
            return redisOperations.keys("*")
                    .flatMap(redisOperations::opsForValue::get)
                    .cast(Dessert.class);
        }
    
        @Override
        public Mono<Long> delete(String id) {
            return redisOperations.delete(id);
        }
    }
    

Service 작성

  • Interface를 먼저 명시 해 준 후에 구현체로 구현

  • DessertService

    • DessertService

      public interface DessertService {
      
          Mono<Dessert> create(Dessert dessert);
      
          Flux<Dessert> getAll();
      
          Mono<Dessert> getOne(String id);
      
          Mono<Long> deleteById(String id);
      
      }
      
    • DessertServiceImpl

      @RequiredArgsConstructor
      @Service
      public class DessertServiceImpl implements DessertService {
      
          private final RedisDessertRepository redisDessertRepository;
      
          @Override
          public Mono<Dessert> create(Dessert dessert) {
              return redisDessertRepository.save(dessert);
          }
      
          @Override
          public Flux<Dessert> getAll() {
              return redisDessertRepository.getAll();
          }
      
          @Override
          public Mono<Dessert> getOne(String id) {
              return redisDessertRepository.get(id);
          }
      
          @Override
          public Mono<Long> deleteById(String id) {
              return redisDessertRepository.delete(id);
          }
      }
      

Contoller 생성

  • DessertController를 생성하여 API Call을 Response 할 수 있도록 작성

    @RestController
    @RequestMapping("/v1")
    @RequiredArgsConstructor
    public class DessertController {
    
        private final DessertServiceImpl dessertService;
    
        @PostMapping("/dessert")
        @ResponseStatus(HttpStatus.CREATED)
        public Mono<Dessert> addDessert(@RequestBody @Valid Dessert dessert) {
            return dessertService.create(dessert);
        }
    
        @GetMapping("/dessert")
        public Flux<Dessert> getAllDessert() {
            return dessertService.getAll();
        }
    
        @GetMapping("/dessert/{id}")
        public Mono<Dessert> getDessert(@PathVariable String id) {
            return dessertService.getOne(id);
        }
    
        @DeleteMapping("/dessert/{id}")
        public Mono<Long> deleteDessert(@PathVariable String id) {
            return dessertService.deleteById(id);
        }
    
    }
    
    

Tags

#Spring#Java#SpringBoot#redis#docker-compose#redis-crud
Previous Article
SpringBoot에서 스케쥴링 사용하기
울이

울이

개발자 울이

경험하고 사용하고 개선하는 것, 그리고 소통하면서 성장하는 것을 좋아합니다.

Expertise

Backend
Frontend
Data Engineering

Social Media

githublinkedinwebsiteinstagram

Related Posts

ActiveMQ와 JMS를 사용한 SpringBoot 메시지
ActiveMQ와 JMS를 사용한 SpringBoot 메시지
December 24, 2022
1 min
© 2023, All Rights Reserved.

Quick Links

Home

Social Media