๐ถ ์์ฆ์ docker๋ก ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ตฌ์ฑํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค.๐ถ
๊ทธ๋ฐ๋ฐ docker๋ก ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ตฌ์ฑํ๋๊ฒ ์ณ์ ๊ฐ์ ๋ํด ๊ณ ๋ฏผ์ ํด๋ณด์๋ค.
๋ฐฐํฌ๋ docker๋ก ํ๊ณ ๊ฐ๋ฐ ํ๊ฒฝ์ docker๋ก ํ์ง ์๋๊ฒ ๋ง๋ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ง์ด ๋ ๋ค.
๊ฐ๋ฐ ํ๊ฒฝ์์๋ ๋จ์ ํ ์คํธ๋ฅผ ์์ฃผ ํ๊ธฐ๋ ํ๋ฉฐ , ๊ฐ๊ฐ์ ๊ธฐ๋ฅ์ด ์๋ก ๋ ๋ฆฝ์ ์ผ๋ก
์๋ํด์ผ ํ๋๊ฒฝ์ฐ๊ฐ ๋ง๋ค. docker ๋ก ๊ฐ๋ฐ ํ๊ฒฝ์ ๋์ฐ๋ฉด ์ฌ์ค ์ข ๋ฌด๊ฒ๋ค๊ณ ์๊ฐ ๋๋ค.
๋จ ์ก์ด๋จน๋ ๊ท์ ๊ทธ ์์ฒด docker
๋ค์ ๋์์์, ๋ฌด๊ฑฐ์ด ๋งํผ , ๋ ์ ์ก์๋จน๋ ๋งํผ , ๋น๋ ์๋์ ๋์ฐ๋ ์๋๋ ๋๋ฆฌ๋ค.
๋ํ, docker ๊ฐ ์ค์น ๋์ง ์์ ๊ฐ๋ฐ์๋ค์ docker-compose ๊น์ง ์ค์ ํ๊ณ ๋ญํ๊ณ ...
์๋ก ๊ฐ๋ฐํ๊ฒฝ์ ๋ง์ถฐ์ฃผ๋ ๊ฑด ์ข์ง๋ง ๋๋ ค...
๋ ์ธ๋ถ ํ๊ฒฝ์ ์ข ์ ๋๋ค. ์ด๊ฒ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์๋๊ฐ?
์์ฆ์ ์ด๊ฑธ ๊ฐ์ฅ ํฌ๊ฒ ๋๋๋ค. ํ์ ์ ํ๋ฉด์ ์ค๊ฐ์ ์ฐธ์ฌํ๋ ๊ฒ๋ ๊ทธ๋ ๊ณ
์ฌ์ค ์๋ก์ ํ๊ฒฝ์ด ๋ง์ง ์์ผ๋ฉด ๊ฐ๋ฐ์ด ๋ถ๊ฐ๋ฅ ํ๋ค. ๋๋ ๋๋๋ฐ ๋ ์ ์๋ผ?
์ธ๋ถ ํ๊ฒฝ์ ์ข ์๋๋ ๊ฐ๋ฐ์ ์ข์ง ์๋ค. ๊ทธ๋ฐ ๋ง์ ๊ฐ์ง์ผ๋ก ์ฌ๋ฌ embeded ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฐพ์๋ณด์๋ค.
๋ํ์ ์ผ๋ก๋ h2
, hsql
, derby
, redis
, mongo
๋ฑ์ด ์๋ค.
์ฌ๊ธฐ์ kafka
, zookeeper
๋ฑ๋ฑ๋ ์๋ค.
embeded redis ๋ฅผ ์ฌ์ฉํ๋ฉด redis ๋ฅผ ์ค์นํ์ง ์๊ณ ๋ ๊ฐ๋ฐ ํ๊ฒฝ์์ redis ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
@Configuration
public class RedisConfig {
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory("localhost", 6379);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
์์ฒ๋ผ ๋ญ... ๋ก์ปฌ์์๋ง ํ ๊ฑฐ๋ฉด ์ ๋ ๊ฒ ํ๊ณ
package com.yata.backend.global.config.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisConnectionFactory;
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.repository.configuration.EnableRedisRepositories;
import java.util.Arrays;
@Configuration
@EnableRedisRepositories
public class RedisRepositoryConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Value(value = "${spring.redis.password}")
private String redisPassword;
@Autowired
private Environment environment;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisHost);
redisStandaloneConfiguration.setPort(redisPort);
// redis password ์ค์
Arrays.stream(environment.getActiveProfiles()).forEach(profile -> {
if (profile.equals("prod")) {
redisStandaloneConfiguration.setPassword(redisPassword);
}
});
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
}
์ด ์ฒ๋ผ ํ๋กํ ๋ณ๋ก ์ค์ ์ ํด์ฃผ๋ฉด ๋๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ embeded redis๋ฅผ ์ค์ ์ผ๋ก ๋ดค๊ณ
์ฌ๊ธฐ์ ์ถ๊ฐ์ ์ผ๋ก ๋ฌธ์ ์ ์ด ํ๋์๋ค.
๋ฌธ์ ์ ์ test ํ๊ฒฝ์์ redis ํ ์คํธ ํ ๋ ๋ฌธ์ ๊ฐ ๋๋ค.
config Bean ๋ฑ์ ์ฌ์ฉ ํ ๋๋ ์ผ๋ฐ์ ์ผ๋ก spiringBootTest ๊ฐ์ด ์ ์ญ ํ ์คํธ๋ฅผ ํ ๋
์ฌ์ฉํ๊ฒ ๋๋๋ฐ ์ด๋ ๋งค ๊ฐ๊ฐ์ ํ ์คํธ ํด๋์ค ๋ง๋ค redis๋ฅผ ๋์ฐ๊ฒ ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ด์ redis ์๋ฒ๊ฐ ์ฃฝ๊ธฐ์ ์ ๋ค์ ํ ์คํธ ํด๋์ค๊ฐ ๋์์ง๊ฒ ๋๋ฉด
์ด์ ์ ๋์์ง redis ์๋ฒ๊ฐ ์์ง ์ด์์๊ธฐ ๋๋ฌธ์ port ์ถฉ๋๋ก ์ธํด ํ ์คํธ๊ฐ ์คํจํ๊ฒ ๋๋ค.
redis๊ฐ ์ ๋์์ง๊ธฐ ๋๋ฌธ์ ํ ์คํธ๊ฐ ์คํจํ๊ฒ ๋๋ค.
์ด ๋ฌธ์ ๋ jojodu ๋์ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ๋ค.
https://jojoldu.tistory.com/297 ์ ๋ง ์ ์ฐฌ ๋ด์ฉ!
๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ํฌํธ ์ถฉ๋ ๋๋ฌธ์ ํ ์คํธ๊ฐ ์คํจํ๋ค๋ ๊ฒ์ด๋ค.
ํด๊ฒฐ flow idea๋ ๋ค์๊ณผ ๊ฐ๋ค.
๊ทธ๋์ redis ์๋ฒ๋ฅผ ๋์ฐ๊ธฐ ์ ์ ํฌํธ ๋ฒํธ๊ฐ ์ ํจํ์ง ํ์ธํ๋ ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ค.
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 org.springframework.util.StringUtils;
import redis.embedded.RedisServer;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Slf4j
@Profile("!prod")
@Configuration
public class LocalRedisConfig {
@Value("${spring.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();
}
}
/**
* Embedded Redis๊ฐ ํ์ฌ ์คํ์ค์ธ์ง ํ์ธ
*/
private boolean isRedisRunning() throws IOException {
return isRunning(executeGrepProcessCommand(redisPort));
}
/**
* ํ์ฌ 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 OS = System.getProperty("os.name").toLowerCase();
if (OS.contains("win")) {
log.info("OS is " + 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);
}
/**
* ํด๋น 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.isEmpty(pidInfo.toString());
}
}
jojodu ๋์ ์ฝ๋์ ์ถ๊ฐ์ ์ผ๋ก OS๋ณ๋ก ํฌํธ๋ฅผ ํ์ธํ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ค.
์ ์ฒ๋ผ embeded redis testcode ๊ฐ ์ถฉ๋์ด ๋๋ ๊ฒฝ์ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด๋ค. ํ์ดํ !