Spring - Embeded Redis 사용하기

목차

참고

https://www.baeldung.com/spring-embedded-redis

Embeded Redis 사용하기

보통 Local 에서 테스트를 위해 많이 사용하며, 별도의 Redis 를 설치하지 않고 실행할 수 있게 해줍니다.

보통 Redis를 사용하는 스프링 프로젝트를 Local에서 프로젝트 실행시 Redis를 선행적으로 설치해줘야 한다. 이 문제를 Embedded Redis를 사용해 프로젝트가 Local 환경에 의존적이지 않고 프로젝트 만으로 구동할 수 있도록 한다.

1. Embedded Redis 사용을 위한 의존성 추가

build.gradle 에 다음 Embedded Redis 사용을 위한 의존성을 추가해줍니다.

implementation 'org.springframework.boot:spring-boot-starter-data-redis'
//embedded-redis
compile group: 'it.ozimov', name: 'embedded-redis', version: '0.7.2'

2. Local Redis 접속을 위한 Profile 추가

application.yml 에 local 환경에서 Redis 접속을 위한 설정을 추가해줍니다.

spring:
profiles:
active: local
redis:
host: localhost
port: 6379

3. Embedded Redis 에 대한 설정

Embedded Redis 를 띄우기 위한 설정을 해줍니다. 보통 Embedded Redis 는 테스트 용도로 띄우기 때문에 Port 설정을 이미 설정된 Redis 접속 포트로 실행시켜줍니다.

어플리케이션 종료시 Embedded Redis 를 종료 시켜주기 위한 설정을 잡아줍니다. @PreDestroy 는 어플리케이션 종료 전에 Embedded Redis 가 종료될 수 있게 해줍니다.

Profile 어노테이션을 통해 -Dspring.profiles.active=local 옵션이 주어졌을 때 해당 설정을 사용할 수 있다

@Slf4j
@Profile("local")
@Configuration
public class EmbeddedRedisConfig {
@Value("${spring.redis.port}")
private int redisPort;

private RedisServer redisServer;

@PostConstruct
public void redisServer() throws IOException {
redisServer = new RedisServer(redisPort);
redisServer.start();
}

@PreDestroy
public void stopRedis(){
if(redisServer != null){
redisServer.stop();
}
}
}

Redis 접속 설정하기

Spring Boot 가 Embedded Redis 에 접속하기 위한 설정이나 이미 구축된 Redis 에 대한 접속 설정은 똑같습니다.

@Configuration
@EnableRedisRepositories
public class RedisRepositoryConfig {

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

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

@Bean
public RedisConnectionFactory redisConnectionFactory(){
return new LettuceConnectionFactory(redisHost, redisPort);
}

@Bean
public RedisTemplate<?, ?> redisTemplate(){
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
@SpringBootTest
public class RedisTest {

@Autowired
private PointRedisRepository pointRedisRepository;

@AfterEach
public void tearDown() throws Exception {
pointRedisRepository.deleteAll();
}

@Test
@DisplayName("기본 등록 조회 기능")
public void retrieve(){
String id = "dongwoo";
LocalDateTime refreshTime = LocalDateTime.of(2021,3,16,0,0);

Point point = Point.builder()
.id(id)
.amount(1000L)
.refreshTime(refreshTime)
.build();

pointRedisRepository.save(point);

Point savedPoint = pointRedisRepository.findById(id).get();
assertThat(savedPoint.getAmount()).isEqualTo(1000L);
assertThat(savedPoint.getRefreshTime()).isEqualTo(refreshTime);
}

@Test
@DisplayName("수정 기능")
public void revise(){
String id = "dongwoo";
LocalDateTime refreshTime = LocalDateTime.of(2021,3,16,0,0);

pointRedisRepository.save(Point.builder()
.id(id)
.amount(1000L)
.refreshTime(refreshTime)
.build());

Point savedPoint = pointRedisRepository.findById(id).get();
savedPoint.refresh(2000L, LocalDateTime.of(2021,3,17,0,0));
pointRedisRepository.save(savedPoint);

Point refreshPoint = pointRedisRepository.findById(id).get();
assertThat(refreshPoint.getAmount()).isEqualTo(2000L);
}
}

@Slf4j
@Profile("local")
@Configuration
public class EmbeddedRedisConfig {

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

private RedisServer redisServer;

@PostConstruct
public void redisServer() throws IOException {
int port = isRedisRunning() ? findAvailablePort() : redisPort;

redisServer = new RedisServer(port);
redisServer.start();
}

@PreDestroy
public void stopRedis() {
if (redisServer != null) {
redisServer.stop();
}
}

private boolean isRedisRunning() throws IOException{
return isRedisRunning();
}

public int findAvailablePort() throws IOException{
for(int port = 10000; port <= 65535; port++ ){
Process process = executeGrepProcessCommand(port);

if(!isRunning(process)){
return port;
}
}
throw new IllegalArgumentException("Not Found Available port: 10000 ~ 65535");
}

private Process executeGrepProcessCommand(int port) throws IOException{
String command = String.format("netstat -nat | grep LISTEN|grep %d", port);
String[] shell = {"/bin/sh", "-c", command};
return Runtime.getRuntime().exec(shell);
}

private boolean isRunning(Process process){
String line;

StringBuilder pidInfo = new StringBuilder();

try(BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()))){
while((line = input.readLine()) != null) {
pidInfo.append(line);
}
}catch (Exception e) {

}

return !StringUtils.isEmpty(pidInfo.toString());
}
}
Share