✏️ 환경설정
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'it.ozimov:embedded-redis:0.7.2'
spring:
data:
redis:
port: 6379
host: localhost
password:
✏️ Redis 적용
📍 Embedded redis 적용
- Embedded redis 는 개발 및 테스트를 위해 사용되는 인메모리 형태의 Redis DB 를 뜻한다.
- 별도의 Redis DB 를 실행시키지 않아도 되기 때문에 어떤 환경에서든 Redis 와 상호작용 할 수 있다.
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import redis.embedded.RedisServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Slf4j
@Profile("!prod")
@Configuration
public class EmbeddedRedisConfig {
@Value("${spring.data.redis.port}")
private int redisPort;
private RedisServer redisServer;
@PostConstruct
public void redisServer() throws IOException {
int port = isRedisRunning() ? findAvailablePort() : redisPort;
redisServer = RedisServer.builder()
.port(port)
.setting("maxmemory 128M")
.build();
redisServer.start();
}
@PreDestroy
public void stopRedis() {
if (redisServer != null)
redisServer.stop();
}
private boolean isRedisRunning() throws IOException {
return isRunning(executeGrepProcessCommand(redisPort));
}
private int findAvailablePort() throws IOException {
for (int port = 10000; port <= 65535; port++) {
Process process = executeGrepProcessCommand(port);
if (!isRunning(process))
return port;
}
throw new IllegalArgumentException("Redis 가 실행할 수 있는 port 가 없음 : 10000 ~ 65535");
}
private Process executeGrepProcessCommand(int port) throws IOException {
String OS = System.getProperty("os.name").toLowerCase();
if (OS.contains("win")) {
log.info("OS os {} {}", OS, port);
String command = String.format("netstat -nao | find \"LISTEN\" | find \"%d\"", port);
String[] shell = {"cmd.exe", "/y", "/c", command};
return Runtime.getRuntime().exec(shell);
}
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());
}
}
📍 Redis 적용
- 위 방법은 인메모리 방식으로 Redis 를 실행하는 방법으로 배포 후 실제 운영에서 쓰기엔 무리가 있기 때문에 Redis DB 를 별도로 띄우고 연결하는 방식도 필요하다.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String host;
@Value("${spring.data.redis.port}")
private int port;
@Value("${spring.data.redis.password}")
private String password;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(host, port);
config.setPassword(RedisPassword.of(password));
return new LettuceConnectionFactory(config);
}
@Bean
@Primary
public RedisTemplate<String, String> redisTemplate() {
RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
✏️ Redis util 생성
- 위와 같은 방식으로 Config 객체를 생성하면 Redis 와 연결이 된다.
- Redis 를 조작하기 위해서 Redis Template 을 사용해 메서드를 만들어주면된다.
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
@Service
@RequiredArgsConstructor
public class RedisUtil {
private final RedisTemplate<String, String> redisTemplate;
public void setData(String key, String value, long timeout) {
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
valueOperations.set(key, value, timeout, MILLISECONDS);
}
public String getValue(String key) {
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
return valueOperations.get(key);
}
public void deleteData(String key) {
redisTemplate.delete(key);
}
}