diff --git a/build.gradle.kts b/build.gradle.kts index 8029184d..7b0f4824 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -63,6 +63,10 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.security:spring-security-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + // Redis + implementation("org.springframework.boot:spring-boot-starter-data-redis") + implementation("com.github.codemonstur:embedded-redis:1.4.3") } tasks.withType { diff --git a/src/main/java/com/back/global/config/EmbeddedRedisConfig.java b/src/main/java/com/back/global/config/EmbeddedRedisConfig.java new file mode 100644 index 00000000..c569a4b8 --- /dev/null +++ b/src/main/java/com/back/global/config/EmbeddedRedisConfig.java @@ -0,0 +1,56 @@ +package com.back.global.config; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import redis.embedded.RedisServer; + +import java.io.IOException; +import java.net.ServerSocket; + +/** + * Embedded Redis 설정 클래스 + * - 개발 및 테스트 환경에서만 활성화 (dev, test 프로파일) + * - 애플리케이션 시작 시 내장 Redis 서버 시작 + * - 애플리케이션 종료 시 내장 Redis 서버 중지 + */ +@Configuration +@Profile({"dev", "test"}) +public class EmbeddedRedisConfig { + + private RedisServer redisServer; + private int port; + + @PostConstruct + public void startRedis() { + try { + this.port = findAvailablePort(); + this.redisServer = new RedisServer(port); + this.redisServer.start(); + System.setProperty("spring.data.redis.port", String.valueOf(port)); + } catch (IOException e) { + throw new IllegalStateException("Failed to start embedded Redis", e); + } + } + + @PreDestroy + public void stopRedis() { + try { + if (redisServer != null && redisServer.isActive()) { + redisServer.stop(); + } + } catch (IOException e) { + throw new IllegalStateException("Failed to stop embedded Redis", e); + } + } + + private int findAvailablePort() { + try (ServerSocket socket = new ServerSocket(0)) { + socket.setReuseAddress(true); + return socket.getLocalPort(); + } catch (IOException e) { + throw new IllegalStateException("No available port found", e); + } + } +} diff --git a/src/main/java/com/back/global/config/RedisConfig.java b/src/main/java/com/back/global/config/RedisConfig.java new file mode 100644 index 00000000..6f8ea292 --- /dev/null +++ b/src/main/java/com/back/global/config/RedisConfig.java @@ -0,0 +1,36 @@ +package com.back.global.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * Redis 설정 클래스 + */ +@Configuration +public class RedisConfig { + + /** + * RedisTemplate 설정 + * - Key: String + * - Value: JSON (Jackson) + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + // Key: String + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + // Value: JSON + template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); + + return template; + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index f79524c8..34da7aa3 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -5,6 +5,11 @@ spring: username: sa password: + data: + redis: + host: localhost + port: 6379 + config: import: optional:file:.env[.properties] diff --git a/src/test/java/com/back/RedisConnectionTest.java b/src/test/java/com/back/RedisConnectionTest.java new file mode 100644 index 00000000..94d05e50 --- /dev/null +++ b/src/test/java/com/back/RedisConnectionTest.java @@ -0,0 +1,31 @@ +package com.back; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.test.context.ActiveProfiles; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@ActiveProfiles("test") +class RedisConnectionTest { + + @Autowired + private StringRedisTemplate redisTemplate; + + @Test + void redisShouldStoreAndGetValue() { + // given + String key = "test:key"; + String value = "hello"; + + // when + redisTemplate.opsForValue().set(key, value); + String result = redisTemplate.opsForValue().get(key); + + // then + assertThat(result).isEqualTo(value); + } +}