Framework/Spring

[Spring Boot]Redis 사용법

SHXL2 2023. 2. 17. 15:34
반응형

오늘은 Redis를 데이터 저장소로 사용하는 과정을 포스팅하려고 합니다.

Redis는 설치되었다는 가정하에 진행되니 참고해주세요. (Redis 설치 방법)

※테스트 환경
  • Spring Boot
  • Maven
  • CentOS 7

1) Maven 추가

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

 

Spring 설정에 들어가기전에 Redis에 데이터를 저장하는 방법은 2가지가 있습니다. RedisTemplate을 이용한 방법과 RedisRepository를 이용한 방법입니다.

RedisTemplate을 이용한 방법은 직렬화,역직렬화 설정 후 데이터를 저장,조회하는 방법입니다.(생성자 주입 후 사용)

RedisRepository를 이용한 방법은 CrudRepository를 상속받아 JPA 처럼 사용하는 방법입니다.

 

본 포스팅에서는 두 가지 방법을 소개합니다.

 

2) Redis 접속 정보 설정

# Redis 설정
spring.redis.host=127.0.0.1
spring.redis.port=6379

 

3) 데이터 저장

3-1) RedisRepository 사용 방식 설정

3-1-1) Configuration 등록

package com.study.app.config;

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.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

	@Value("${spring.redis.host}")
	private String host;
	
	@Value("${spring.redis.port}")
	private int port;
	
	@Bean
	public LettuceConnectionFactory redisConnectionFactory() {
		return new LettuceConnectionFactory(host, port);
	}
}

 

3-1-2) Entity 등록

package com.study.app.common.redis;

import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@RedisHash(value = "companyUser")
public class CompanyUser {
	
	@Id
	private String userId;
	private String userName;
	
	public CompanyUser(String userId, String userName) {
		this.userId   = userId;
		this.userName = userName;
	}
}

@RedisHash로 데이터의 prefix가 설정됩니다.

@Id 어노테이션 사용시 javax.persistence.Id가 아닌 org.springframework.data.annotation.Id를 임포트해야합니다.

import org.springframework.data.annotation.Id;

 

3-1-3) Repository 등록

package com.study.app.common.redis;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface CompanyRepository extends CrudRepository<CompanyUser, String>{
	
	List<CompanyUser> findAll();

}

 

3-1-4) Test Component 등록

package com.study.app.common.component;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import com.wwl.app.common.redis.CompanyRepository;
import com.wwl.app.common.redis.CompanyUser;

@Component
public class RedisCompany {	
	
	private final CompanyRepository companyRepository;
		
	public RedisCompany(CompanyRepository companyRepository) {		
		this.companyRepository = companyRepository;
	}	
	
	@PostConstruct
	public void init() {
		companyRepository.save(new CompanyUser("lsh", "홍길동"));
	}
}

서버를 실행하게 되면 @PostConstruct 에 의해 최초 1회 Redis 에 저장됩니다.

이제 Redis에 저장된 값을 조회해보겠습니다.

 

3-1-5) 전체 리스트 조회

결과를 리턴할 MsgEntity 클래스와 Enum 타입 생성

package com.study.app.common.entity;

import lombok.Data;

@Data
public class MsgEntity {

	private StatusEnum status;
    private String message;
    private Object result;
       
    public MsgEntity(StatusEnum status, String message) {
    	this.status	 = status;
    	this.message = message;    	
    }   
    public MsgEntity(StatusEnum status, Object result) {
    	this.status	 = status;
    	this.result	 = result;    	
    }
}
package com.study.app.common.entity;

public enum StatusEnum {

	OK(200, "OK"),
	BAD_REQUEST(400, "BAD_REQUEST"),
	NOT_FOUND(404, "NOT_FOUND"),
	INTERNAL_SERVER_ERROR(500, "INTERNAL_SERVER_ERROR");
	
	int code;
	String message;
	
	StatusEnum(int code, String message) {
		this.code = code;
		this.message = message;
	}	
}

 

데이터 조회를 위한 컨트롤러를 만들고 테스트해보겠습니다.

package com.study.app.common.redis;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.wwl.app.common.entity.MsgEntity;
import com.wwl.app.common.entity.StatusEnum;

import lombok.AllArgsConstructor;

@RestController
@RequiredArgsConstructor
public class CompanyController {

	private final CompanyRepository companyRepository;	
	
	@GetMapping(value="/company/list")
    public ResponseEntity<MsgEntity> companyList() throws Exception {														
		return ResponseEntity.ok()
				.body(new MsgEntity(StatusEnum.OK, companyRepository.findAll()));
	}
}

 

@Id로 지정된 lsh를 키값으로 홍길동의 값을 조회할 수 있습니다.

2개의 키(companyUser, companyUser:lsh)가 생성된 것을 확인할 수 있습니다.

여기서 companyUser는 companyUser와 관련된 모든 키를 관리하며 companyUser의 Id와 매핑된 정보는 companyUser:Id와 같은 형태로 저장됩니다.

각각의 타입을 확인해보면 companyUser는 Set의 형태를 하고 실제 정보가 있는 companyUser:lsh는 Hash 타입임을 알 수 있습니다.

 

Redis에서는 각각의 자료구조별로 조회하는 명령어가 존재합니다.

Set 타입 조회시에는 SMEMBERS라는 명령어로 조회를 할 수 있습니다.

Hash 타입 조회시에는 hkeys로 키 리스트를 볼 수 있고, hvals로 값을 볼 수 있습니다.

입력된 값은 인코딩 과정에서 한글이 깨지는 문제로 redis-cli --raw 옵션을 붙이게 되면 확인할 수 있습니다.

 

[Postman 호출 테스트]

 

3-2) RedisTemplate 사용 방식

3-2-1) Configuration 등록

RedisTemplate은 Redis 서버에 커맨드를 수행하기 위한 메소드를 제공합니다. 자료구조에 따라 각기 다른 메소드가 사용되는데 각 메소드는 *Operations 인터페이스를 반환하기에 타입에 맞는 Operations을 선언해 사용합니다.

  • opsForValue() :  String -> ValueOperations
  • opsForSet() : Set -> SetOperations
  • opsForList() : List -> ListOperations
  • opsForZSet() : Sorted Set -> ZSetOperations
  • opsForHash() : Hash -> HashOperations
package com.study.app.config;

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.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

	@Value("${spring.redis.host}")
	private String host;
	
	@Value("${spring.redis.port}")
	private int port;
	
	@Bean
	public LettuceConnectionFactory redisConnectionFactory() {
		return new LettuceConnectionFactory(host, port);
	}
    
    @Bean
	public RedisTemplate<String, CompanyUserDTO> companyTemplate() {
		RedisTemplate<String, CompanyUserDTO> accessTemplate = new RedisTemplate<>();
		accessTemplate.setConnectionFactory(redisConnectionFactory());
		accessTemplate.setKeySerializer(new StringRedisSerializer());
		accessTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(CompanyUserDTO.class));

		return accessTemplate;
	}
}

 

3-2-2) DTO 등록

package com.study.app.common.redis;

import lombok.Data;

@Data
public class CompanyUserDTO {

	private String userId;
	private String userName;

}

 

3-2-3) Controller 등록

  • [GET] "/company/list" : 사용자 조회
  • [POST] "/company/user" : 사용자 등록
package com.study.app.common.redis;

import com.wwl.app.common.entity.MsgEntity;
import com.wwl.app.common.entity.StatusEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Set;

@RestController
@RequiredArgsConstructor
public class CompanyController {

	private final RedisTemplate<String, CompanyUserDTO> companyTemplate;

	@GetMapping(value="/company/list")
    public ResponseEntity<MsgEntity> companyList() throws Exception {
        SetOperations<String, CompanyUserDTO> setOpertaions = companyTemplate.opsForSet();
        Set<CompanyUserDTO> companyUserList = setOpertaions.members("companyUser");

		return ResponseEntity.ok()
				.body(new MsgEntity(StatusEnum.OK, companyUserList));
	}

    @PostMapping(value="/company/user")
    public ResponseEntity<MsgEntity> insertCompanyUser(@RequestBody CompanyUserDTO companyUserDTO) throws Exception {
        SetOperations<String, CompanyUserDTO> setOpertaions = companyTemplate.opsForSet();
        setOpertaions.add("companyUser", companyUserDTO);

		return ResponseEntity.ok()
				.body(new MsgEntity(StatusEnum.OK, "Success"));
	}
}

RedisRepository를 이용한 방식과 동일하게 SET 타입으로 사용자를 등록하도록 했습니다.

먼저 redis-cli 명령어를 통해 접속 후 키 리스트를 조회해보면 아래와 같이 아무것도 조회되지 않는 것을 확인할 수 있습니다.

사용자를 등록하고 다시 조회해보겠습니다.

 

[Postman 호출 테스트]

 

다시 redis-cli 후 키를 조회해보면 companyUser가 추가된 것을 확인할 수 있고, SMEMBERS 명령어로 등록된 값을 확인할 수 있습니다.

깨진 한글은 위에서와 마찬가지로 redis-cli --raw 옵션 설정 후 재조회하면 해결됩니다.


+ 피드백은 언제나 환영입니다 :)

반응형