잘못된 내용이나 의견 있다면 편하게 말씀해주세요.🙏🏻
개발/테스트 목적의 단일 노드 Redis(Remote Dictionary Server)를 구축하는 5가지 방법을 소개합니다.
(1. 로컬, 2. docker-compose, 3. Embedded Redis, 4. Testcontainers, 5. AWS ElastiCache, Terraform)
운영 목적의 아키텍처(Replication, Sentinel, Cluster)는 아닙니다.
글 목록
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : 로컬, docker-compose
현재글 : [Redis] 레디스를 5가지 방법으로 설치/구축하기 : Embedded Redis, Testcontainers
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : AWS ElastiCache + AWS Console
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : Terraform + AWS ElastiCache
이번 글에서는
Embedded Redis와 Testcontainers를 활용하고자 합니다.
전체 소스 코드는 이곳을 참고해주세요.
3. Embedded Redis (Java/Spring)
Embedded Redis는 내장 Redis입니다. 주로 Java/Spring 프로젝트에서 개발/테스트 환경에서 사용 목적으로 사용됩니다.
로컬/Docker-compose 구축 방법과 다르게 별도로 Redis 실행 없이 Java/Spring 프로젝트 실행 시 자동으로 실행되고 종료됩니다.
구축 방법은 아래와 같습니다. (Java/Spring + Gradle)
3.1. 의존성 추가
3.2. embedded redis 설정
3.3. Redis Client - Lettuce 사용
3.1. 의존성 추가
Embedde Redis DB는 it.ozimov 라이브러리를 사용합니다.
Redis Client는 Lettuce를 사용합니다. (Why is Lettuce the default Redis client used in Spring Session Redis?)
# build.gradle
dependencies {
// ...
// Embedded Redis DB : it.ozimov
testImplementation 'it.ozimov:embedded-redis:0.7.3' exclude group: 'org.slf4j', module: 'slf4j-simple'
// Spring Data Redis (Lettuce Client 포함)
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}
application.yml 설정
// application.yml
spring:
redis:
host: localhost
port: 6379
3.2. embedded redis 설정
전체 작동 방식은 RedisServer() 객체를 생성 -> 실행 -> 종료 합니다.
특이한 점은 통합 테스트 환경에서 Embedded Redis를 두 개 이상 띄울 경우 포트가 겹치는 문제가 발생하기 때문에 지정한 Redis port 사용 중이라면 RandomPort를 생성하여 Embedded Redis를 생성합니다. (ref : jojoldu - SpringBoot Data Redis 로컬/통합 테스트 환경 구축하기)
// https://github.com/ku-kim/springboot-redis-example/blob/main/src/test/java/kim/ku/redis/config/EmbeddedRedisConfig.java
@Configuration
// @TestConfiguration // 테스트에서만 사용할 때
public class EmbeddedRedisConfig {
@Value("${spring.redis.port}")
private int redisPort;
private RedisServer redisServer;
@PostConstruct
public void redisServer() throws IOException {
int port = isRedisRunning() ? getRandomPort() : redisPort; // 겹치지 않는 랜덤 포트 생성
redisServer = new RedisServer(port); // 레디스 서버 생성
redisServer.start(); // 레디스 서버 실행
}
@PreDestroy
public void stopRedis() {
redisServer.stop(); // 레디스 서버 종료
}
private boolean isRedisRunning() throws IOException {
return isRunning(executeGrepProcessCommand(redisPort));
}
/**
* 해당 port를 사용중인 프로세스 확인하는 sh 실행
*/
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);
}
/**
* 해당 Process가 현재 실행중인지 확인
*/
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 ignored) {
}
return StringUtils.hasLength(pidInfo.toString());
}
/**
* 랜덤 포트를 할당받아서 리턴
* ref : <a href="https://github.com/apache/curator/blob/7a148288603ae5db0c232142f7dc07d43e01bea3/curator-test/src/main/java/org/apache/curator/test/InstanceSpec.java#L86">...</a>
*/
private int getRandomPort() {
ServerSocket server = null;
try {
server = new ServerSocket(0);
server.setReuseAddress(true);
return server.getLocalPort();
} catch (IOException e) {
throw new Error(e);
} finally {
if (server != null) {
try {
server.close();
} catch (IOException ignore) {
// ignore
}
}
}
}
}
위와 같이 Configuration을 설정하면 실행될 때마다 Embedded Redis 가 실행됩니다. 이제 Redis Client를 사용하여 해당 Redis에 연결하여 사용하면 됩니다.
3.3. Redis Client - Lettuce 사용
Java/Spring을 사용하는 Redis Client 라이브러리로 Redis에 접근하는 방법은 크게 두 가지입니다.
RedisTemplate와 RedisRepository입니다.
아쉽게도 이 글의 취지는 Redis Server를 구축하는 방법이기에 해당 사용 방법은 다른 글에서 소개드리고자 합니다.
아래 코드는 RedisTemplate를 생성하고 있습니다.
@Configuration
public class RedisRepositoryConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int port;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisHost, port); // Redis Client 객체 생성
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory()); // RedisTempaltes에 Redis Client 연결
return redisTemplate;
}
}
4. Testcontainers 라이브러리를 활용 (Java/Spring)
Testcontainers 라이브러리를 사용하여 Docker-compose 구축 과정을 Java 코드로 사용할 수 있습니다. 자동으로 Docker 컨테이너가 실행되고 종료됩니다. 이는 CI 테스트 환경에서 유리하게 작동할 수 있습니다. (ref : [의사결정] Testcontainers 사용하기까지)
4.1. 의존성 추가
# build.gradle
dependencies {
// ...
// TestContainers
testImplementation 'org.testcontainers:junit-jupiter:1.17.4'
// Spring Data Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
}
4.2. Testcontainers컨테이너 설정
class TestContainersRedis {
static {
GenericContainer redis = new GenericContainer("redis:7.0.5")
.withExposedPorts(6379);
redis.start();
// 테스트 환경에서 host, port가 랜덤으로 생성되기 때문에 property를 추가 설정해준다.
System.setProperty("spring.redis.host", redis.getHost());
System.setProperty("spring.redis.port", redis.getMappedPort(6379).toString());
}
}
위와 같이 Testcontainers 라이브러리를 사용하여 Redis 도커를 띄울 수 있다. 이를 테스트에서 활용할 수 있다.
4.3. Redis Client - Lettuce 사용
3.3과 동일하여 넘어가고자 합니다.
마치며
이번 글을 통해 Java/Spring 프로젝트에서 Embedded Redis와 Testcontainers를 사용하여 Redis를 구축하였습니다.
다음 글에서는 AWS ElastiCache 서비스를 사용하여 Redis를 구축해보고자 합니다.
글 목록
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : 로컬, docker-compose
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : Embedded Redis, Testcontainers
다음글 : [Redis] 레디스를 5가지 방법으로 설치/구축하기 : AWS ElastiCache + AWS Console
[Redis] 레디스를 5가지 방법으로 설치/구축하기 : Terraform + AWS ElastiCache
Reference
Embedded Redis
- https://jojoldu.tistory.com/297
- https://github.com/ozimov/embedded-redis
- https://github.com/kstyrc/embedded-redis
- https://www.baeldung.com/spring-embedded-redis
Testcontainers Redis
- https://www.baeldung.com/spring-boot-redis-testcontainers
- https://github.com/testcontainers/testcontainers-java/tree/main/examples/redis-backed-cache
'🏢 DB > 1️⃣ Redis' 카테고리의 다른 글
[간단 장애 회고] Redis + @Transactional (트랜잭션에서 Redis Get은 항상 null을 리턴한다. 트랜잭션 없는 상위 메서드에서 트랜잭션 있는 하위 메서드 호출은 에러다.) (2) | 2022.12.18 |
---|---|
레디스를 5가지 방법으로 설치/구축하기 : AWS ElastiCache (0) | 2022.12.09 |
레디스를 5가지 방법으로 설치/구축하기 : 로컬, docker-compose (2) | 2022.12.08 |
레디스를 학습하며 도움 받았던 레퍼런스 링크 모음 (0) | 2022.12.08 |
댓글