HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
♥️
2기 최종 프로젝트 팀별 공간
/
[팀 BackFro💯] ArtZip: 세상 모든 전시회를 한 번에
[팀 BackFro💯] ArtZip: 세상 모든 전시회를 한 번에
/
☠️
백엔드 기술 문서
/
🧪
테스트를 위한 Embedded Redis
🧪

테스트를 위한 Embedded Redis

CI/CD를 공부하고 해당 방법을 사용해보며 한가지 느끼게된 점이 있습니다. 지금까지 테스트 코드를 작성하면 로컬에서만 사용하였기 때문에 필요한 외부 의존성(ex. DB)을 직접 실행시켜 사용하였습니다. 하지만 CI 툴에서는 해당 방법이 불가능하기에 다른 방법을 생각해봐야했습니다. DB의 경우 Embedded h2를 사용하면 된다는 것을 알았지만 Redis는 어떻게 해야하는지 몰랐고 방법을 찾아보았습니다. 그 결과 아래와 같은 글들을 보고 기존 프로젝트에 Embedded Redis를 적용해보았습니다.
 
[Redis] SpringBoot Data Redis 로컬/통합 테스트 환경 구축하기
안녕하세요? 이번 시간엔 SpringBoot Data Redis 로컬 테스트 예제를 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 Github와 세미나+책 후기를 정리하는 Github, 이 모든 내용을 담고 있는 블로그가 있습니다. ) 회사 신규 프로젝트로 Redis 를 사용하게 되었습니다. 로컬에서 개발하고 테스트 할 수 있는 환경구성이 필요했는데요.
[Redis] SpringBoot Data Redis 로컬/통합 테스트 환경 구축하기
https://jojoldu.tistory.com/297
[Redis] SpringBoot Data Redis 로컬/통합 테스트 환경 구축하기
내장 Redis 설정기
안녕하세요 :) 마크입니다! 토큰과 캐싱 개발 초기엔 내장 Redis가 존재하는지 모르고, RedisRepository 역할을 하는 객체를 직접 자바 코드로 구현하여 테스트를 진행했다. 즉, Fake 객체를 만들어서 테스트하는 방법을 택했다. 이렇게 테스트 하는 것의 가장 큰 문제는 실제 Redis 환경이 아니란 점이다..
내장 Redis 설정기
http://tech.pick-git.com/embedded-redis-server/
내장 Redis 설정기
 
실습은 이전 클론 코딩 프로젝트인 coretime을 기준으로 작성하였습니다.
 

의존성 추가

build.gradle에 Embedded Redis를 위한 의존성을 추가합니다.
testImplementation 'it.ozimov:embedded-redis:0.7.2'
spring-data-radis는 이미 의존성이 추가 되어 있기에 따로 명시하지 않았습니다.
 

EmbeddedRedisConfig

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import redis.embedded.RedisServer; @Configuration public class EmbeddedRedisConfig { @Value("${spring.redis.port}") private int port; private RedisServer redisServer; @PostConstruct public void redisServer() throws IOException { System.out.println("시발 이게 왜 저기서 되는데"); redisServer = new RedisServer(isRedisRunning()? findAvailablePort() : port); redisServer.start(); } @PreDestroy public void stopRedis() { if (redisServer != null) { redisServer.stop(); } } /** * Embedded Redis가 현재 실행중인지 확인 */ private boolean isRedisRunning() throws IOException { return isRunning(executeGrepProcessCommand(port)); } /** * 현재 PC/서버에서 사용가능한 포트 조회 */ 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"); } /** * 해당 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 e) { } return StringUtils.hasText(pidInfo.toString()); } }
위는 Embedded Redis를 테스트에 적용하는 코드입니다. (여러 스프링 테스트 컨텍스트가 실행되면 Embedded Redis에서 포트충돌이 발생하기 때문에 사용 가능한 포트를 확인하고 설정하는 코드가 포함되어 있습니다.)
 
하면서 신기했던 점이 있었는데 redis.embedded.RedisServer 는 test디렉토리에서만 사용이 가능하다는 것이었습니다.
 

나머지

 
Embedded Redis에 연결하는 코드의 경우 실제 Redis에 연결하는 기존 코드를 그대로 사용하면 됩니다.
import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @ConfigurationProperties(prefix = "spring.redis") @Getter @Setter public class RedisConfig { private final Logger log = LoggerFactory.getLogger(getClass()); private String host; private int port; @Bean public RedisConnectionFactory redisConnectionFactory() { log.info("host: {}, port: {}", host, port); return new LettuceConnectionFactory(host, port); } @Bean public RedisTemplate<String, String> redisTemplate() { RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(redisConnectionFactory()); return redisTemplate; } }