목차
참고
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'
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()); } }
|