Ver2.0 ๐ Spring Data Redis๋ก ์ด๊ฐ๋จ ์บ์ ์๋ฒ ์ฐ๋ํ๊ธฐ: ์ฑ๋ฅ ํญ๊ฒฉ๊ธฐ ๋ง๋ค๊ธฐ ๐ฃ

๐ Spring Data Redis๋ก ์ด๊ฐ๋จ ์บ์ ์๋ฒ ์ฐ๋ํ๊ธฐ: ์ฑ๋ฅ ํญ๊ฒฉ๊ธฐ ๋ง๋ค๊ธฐ ๐ฃ
์๋ ํ์ธ์ ๊ฐ๋ฐ์ ์ฌ๋ฌ๋ถ! ์ค๋์ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํฐ๋ณด ์์ง์ ๋ฌ์์ค Spring Data Redis๋ฅผ ํ์ฉํ ์บ์ ์๋ฒ ์ฐ๋์ ๋ํด ์์๋ณผ๊ฒ์. ์ฑ๋ฅ ์ต์ ํ์ ๊ด์ฌ ์๋ ๋ถ๋ค, ํนํ Java ๊ฐ๋ฐ์๋ผ๋ฉด ๊ผญ ์์์ผ ํ ๋ด์ฉ์ด๋ ๋๊น์ง ํจ๊ปํด์! ๐
๐ ๋ชฉ์ฐจ
- Redis์ ์บ์ฑ์ด ๋ญ๊ธธ๋? ๐ค
- Spring Data Redis ์์ํ๊ธฐ ๐ป
- Redis ์ฐ๊ฒฐ ์ค์ ํ๊ธฐ โ๏ธ
- ์บ์ ์ ๋ต ์๋ฆฝํ๊ธฐ ๐
- ์ค์ ์์ : ์ํ ์ ๋ณด ์บ์ฑํ๊ธฐ ๐
- ์ฑ๋ฅ ์ธก์ ๋ฐ ์ต์ ํ ํ ๐
- ์ด์ ํ๊ฒฝ์์์ ์ฃผ์์ฌํญ โ ๏ธ
- ๋ง๋ฌด๋ฆฌ ๋ฐ ๋ค์ ๋จ๊ณ ๐ฏ
1. Redis์ ์บ์ฑ์ด ๋ญ๊ธธ๋? ๐ค
์ฌ๋ฌ๋ถ, ์น์ฌ์ดํธ๊ฐ ๋๋ ค์ ์ฌ์ฉ์๋ค์ด ๋ ๋๊ฐ ๊ฒฝํ ์์ผ์ ๊ฐ์? ใ ใ ์๋๋ฉด DB ์๋ฒ๊ฐ ๊ณผ๋ถํ๋ก ํฐ์ ธ๋ฒ๋ฆฐ ์ ๋ชฝ ๊ฐ์ ์๊ฐ? ๐ฑ ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐ์ฌ๊ฐ ๋ฐ๋ก Redis(Remote Dictionary Server)์์!
Redis๋? ์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ์ฅ์๋ก, ํค-๊ฐ ํํ๋ก ๋ฐ์ดํฐ๋ฅผ ์ด๊ณ ์์ผ๋ก ์ ์ฅํ๊ณ ๊ฒ์ํ ์ ์๋ ์คํ์์ค ์๋ฃจ์ ์ด์์. ์บ์, ๋ฉ์์ง ๋ธ๋ก์ปค, ์ค์๊ฐ ๋ถ์ ๋ฑ ๋ค์ํ ์ฉ๋๋ก ํ์ฉ๋ฉ๋๋ค.
๊ทผ๋ฐ ์บ์ฑ์ด ๋ญ๋๊ตฌ์? ๊ฐ๋จํ ๋งํด์ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅํด๋๊ณ ๋น ๋ฅด๊ฒ ๊บผ๋ด ์ฐ๋ ๊ธฐ์ ์ด์์. ๋ง์น ์ฌ๋ฌ๋ถ์ด ์์ฃผ ์ฐ๋ ๋ฌผ๊ฑด์ ์ฑ ์ ์์ ์ฌ๋ ค๋๋ ๊ฒ์ฒ๋ผ์! ๐
Redis์ ์ฅ์ ์ ์ ๋ง ๋ง์๋ฐ์, ๋ํ์ ์ผ๋ก๋:
- ์ด๊ณ ์ ์ฑ๋ฅ: ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฐ์ด๋ผ ๋์คํฌ I/O๊ฐ ์์ด์ ์์ฒญ ๋นจ๋ผ์! ๐๏ธ
- ๋ค์ํ ์๋ฃ๊ตฌ์กฐ: ๋ฌธ์์ด, ํด์, ๋ฆฌ์คํธ, ์ , ์ ๋ ฌ๋ ์ ๋ฑ ์ฌ๋ฌ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ง์ํด์.
- ์์์ ์ฐ์ฐ: ๋ณต์กํ ์ฐ์ฐ๋ ํ ๋ฒ์ ์ฒ๋ฆฌํ ์ ์์ด์.
- ์์์ฑ: ๋ฉ๋ชจ๋ฆฌ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋์คํฌ์ ์ ์ฅํ ์ ์์ด์.
- ํด๋ฌ์คํฐ๋ง: ์ฌ๋ฌ ์๋ฒ๋ก ํ์ฅ ๊ฐ๋ฅํด์ ๋๊ท๋ชจ ์๋น์ค์๋ ์ ํฉํด์.
์์ฆ ์ฌ๋ฅ๋ท๊ฐ์ ํ๋ซํผ๋ Redis๋ฅผ ํ์ฉํด์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๊ณ ์๋ค๊ณ ํด์. ํนํ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ ์ ๋ณด๋ ์ฌ์ฉ์ ํ๋กํ ๊ฐ์ ์์ฃผ ์กฐํ๋๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ๋ฉด ์๋น์ค ์๋ต ์๋๊ฐ ํ ๋นจ๋ผ์ง๋์! ๐
2. Spring Data Redis ์์ํ๊ธฐ ๐ป
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก Spring Boot ํ๋ก์ ํธ์ Redis๋ฅผ ์ฐ๋ํด๋ณผ๊น์? ์ง์ง ์ฌ์์ ๋๋๊ฑธ์? ใ ใ ใ
2.1 ์์กด์ฑ ์ถ๊ฐํ๊ธฐ
๋จผ์ Maven์ด๋ Gradle์ ์์กด์ฑ์ ์ถ๊ฐํด์ผ ํด์. ์ฌ๋ฌ๋ถ์ ๋น๋ ๋๊ตฌ์ ๋ฐ๋ผ ์ ํํ์ธ์!
Maven (pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Gradle (build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
์ด ์์กด์ฑ ํ๋๋ก Redis ํด๋ผ์ด์ธํธ์ธ Lettuce๊ฐ ์๋์ผ๋ก ํฌํจ๋์ด ๋ณ๋ ์ค์น ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์์ด์. ์ง์ง Spring Boot๋ ๊ฐ๋ฐ์ ํธ์์ฑ ๊ฐ์ด๋ค์! ๐
2.2 Redis ์ค์นํ๊ธฐ
๋ก์ปฌ์์ ๊ฐ๋ฐํ ๋๋ Redis ์๋ฒ๊ฐ ํ์ํด์. ์ด์์ฒด์ ๋ณ๋ก ์ค์น ๋ฐฉ๋ฒ์ด ๋ค๋ฅด๋ ์ฐธ๊ณ ํ์ธ์!
Windows
Windows๋ ๊ณต์์ ์ผ๋ก ์ง์ํ์ง ์์ง๋ง, Microsoft์์ ์ ๊ณตํ๋ ํฌํธ ๋ฒ์ ์ด ์์ด์:
1. https://github.com/microsoftarchive/redis/releases์์ ๋ค์ด๋ก๋
2. ์ค์น ํ Redis ์๋ฒ ์คํ: redis-server.exe
Mac
Homebrew๋ฅผ ์ด์ฉํ๋ฉด ์ ๋ง ๊ฐ๋จํด์:
brew install redis
brew services start redis
Linux (Ubuntu)
apt๋ฅผ ์ด์ฉํด ์ค์นํ ์ ์์ด์:
sudo apt update
sudo apt install redis-server
sudo systemctl start redis-server
Docker (๋ชจ๋ OS)
Docker๋ฅผ ์ฌ์ฉํ๋ฉด OS ์๊ด์์ด ์ฝ๊ฒ ์ค์นํ ์ ์์ด์:
docker run --name my-redis -p 6379:6379 -d redis
์ค์น๊ฐ ๋๋ฌ์ผ๋ฉด Redis๊ฐ ์ ๋๋ก ์คํ ์ค์ธ์ง ํ์ธํด๋ณผ๊น์?
redis-cli ping
"PONG"์ด๋ผ๊ณ ์๋ต์ด ์ค๋ฉด ์ฑ๊ณต์ด์์! ๐
๐ก ๊ฐ๋ฐ ํ: ๋ก์ปฌ ๊ฐ๋ฐ ํ๊ฒฝ์์๋ Docker๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฅ ํธ๋ฆฌํด์. ํ๋ก์ ํธ๋ง๋ค ๋ค๋ฅธ ๋ฒ์ ์ Redis๋ฅผ ์ฌ์ฉํด์ผ ํ ๋๋ ์ปจํ ์ด๋๋ง ๋ฐ๊ฟ์ฃผ๋ฉด ๋๋๊น์!
3. Redis ์ฐ๊ฒฐ ์ค์ ํ๊ธฐ โ๏ธ
์ด์ Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ์์ Redis์ ์ฐ๊ฒฐํ ์ฐจ๋ก์์. Spring Data Redis๋ ์ ๋ง ๊ฐ๋จํ๊ฒ ์ค์ ํ ์ ์์ด์!
3.1 ๊ธฐ๋ณธ ์ค์
application.properties ๋๋ application.yml ํ์ผ์ Redis ์ฐ๊ฒฐ ์ ๋ณด๋ฅผ ์ถ๊ฐํด์ฃผ์ธ์.
application.properties
# Redis ์๋ฒ ์ฐ๊ฒฐ ์ค์
spring.redis.host=localhost
spring.redis.port=6379
# ๋น๋ฐ๋ฒํธ๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ์๋ง ์ถ๊ฐ
# spring.redis.password=mypassword
# ์ฐ๊ฒฐ ํ ์ค์
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
application.yml
spring:
redis:
host: localhost
port: 6379
# password: mypassword # ํ์ํ ๊ฒฝ์ฐ๋ง
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
์ด ์ค์ ๋ง์ผ๋ก Spring Boot๋ ์๋์ผ๋ก RedisConnectionFactory์ RedisTemplate ๋น์ ์์ฑํด์ค์. ์ง์ง Spring Boot๋ ๊ฐ๋ฐ์๋ฅผ ์ฌ๋ํ๋ ๋ด์! ใ ใ ใ
3.2 Redis ์ค์ ํด๋์ค ๋ง๋ค๊ธฐ
๊ธฐ๋ณธ ์ค์ ์ผ๋ก๋ ์ถฉ๋ถํ์ง๋ง, ์ข ๋ ์ธ๋ฐํ ์ ์ด๊ฐ ํ์ํ๋ค๋ฉด ์ค์ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
// ํค๋ ๋ฌธ์์ด๋ก ์ง๋ ฌํ
template.setKeySerializer(new StringRedisSerializer());
// ๊ฐ์ JSON์ผ๋ก ์ง๋ ฌํ (๊ฐ์ฒด๋ฅผ ์ ์ฅํ ๋ ์ ์ฉ)
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// Hash ์์
์ ์ํ ์ง๋ ฌํ ์ค์
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
์ด ์ค์ ํด๋์ค๋ RedisTemplate์ ์ปค์คํฐ๋ง์ด์งํด์ ํค๋ ๋ฌธ์์ด๋ก, ๊ฐ์ JSON์ผ๋ก ์ง๋ ฌํํ๋๋ก ์ค์ ํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด Java ๊ฐ์ฒด๋ฅผ Redis์ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ฌ ๋ ์๋์ผ๋ก ๋ณํํด์ค์ ์ ๋ง ํธ๋ฆฌํด์! ๐
3.3 Redis ์ฐ๊ฒฐ ํ ์คํธํ๊ธฐ
์ค์ ์ด ์ ๋๋ก ๋๋์ง ๊ฐ๋จํ ํ ์คํธ๋ฅผ ํด๋ณผ๊น์? ์๋ ์ฝ๋๋ฅผ ์ฌ์ฉํด์ Redis์ ๊ฐ์ ์ ์ฅํ๊ณ ๊ฐ์ ธ์ ๋ณผ ์ ์์ด์.
@SpringBootApplication
public class RedisTestApplication implements CommandLineRunner {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public static void main(String[] args) {
SpringApplication.run(RedisTestApplication.class, args);
}
@Override
public void run(String... args) {
// ๊ฐ ์ ์ฅํ๊ธฐ
redisTemplate.opsForValue().set("test:key", "์๋
ํ์ธ์ Redis!");
// ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
String value = (String) redisTemplate.opsForValue().get("test:key");
System.out.println("Redis์์ ๊ฐ์ ธ์จ ๊ฐ: " + value);
// ๋ง๋ฃ ์๊ฐ ์ค์ (10์ด)
redisTemplate.opsForValue().set("test:expire", "10์ด ํ์ ์ฌ๋ผ์ ธ์!", 10, TimeUnit.SECONDS);
}
}
์ด ์ฝ๋๋ฅผ ์คํํ๋ฉด Redis์ ๊ฐ์ ์ ์ฅํ๊ณ ๋ฐ๋ก ๊ฐ์ ธ์์ ์ถ๋ ฅํด์. ์ฝ์์ "Redis์์ ๊ฐ์ ธ์จ ๊ฐ: ์๋ ํ์ธ์ Redis!"๊ฐ ์ถ๋ ฅ๋๋ฉด ์ฑ๊ณต์ ๋๋ค! ๐
๐ ์์๋์ธ์: Redis ํค๋ ๋ณดํต namespace:id ํํ๋ก ์์ฑํ๋ ๊ฒ์ด ๊ด๋ก์์. ์๋ฅผ ๋ค์ด user:1001, product:2002 ๊ฐ์ ํ์์ด์ฃ . ์ด๋ ๊ฒ ํ๋ฉด ํค ๊ด๋ฆฌ๊ฐ ํจ์ฌ ์ฌ์์ ธ์!
4. ์บ์ ์ ๋ต ์๋ฆฝํ๊ธฐ ๐
Redis๋ฅผ ์ฐ๊ฒฐํ์ผ๋ ์ด์ ์ด๋ป๊ฒ ํจ๊ณผ์ ์ผ๋ก ์บ์ฑํ ์ง ์ ๋ต์ ์ธ์๋ณผ๊น์? ์บ์ฑ์ ๋ฌด์กฐ๊ฑด ๋ง์ด ํ๋ค๊ณ ์ข์ ๊ฒ ์๋๋ผ, ์ ์ฌ์ ์์ ํ์ฉํด์ผ ์ง์ง ํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ด์!
4.1 ์บ์ฑ ๋์ ์ ์ ํ๊ธฐ
๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น๊ฐ ์ฌํด์. ๋ค์ ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ฑ ๋์์ผ๋ก ๊ณ ๋ คํด๋ณด์ธ์:
- ์ฝ๊ธฐ๊ฐ ๋ง์ ๋ฐ์ดํฐ: ์กฐํ๋ ์์ฃผ ํ์ง๋ง ์์ ์ ์ ์ ๋ฐ์ดํฐ
- ๊ณ์ฐ ๋น์ฉ์ด ํฐ ๋ฐ์ดํฐ: DB ์กฐ์ธ์ด ๋ง๊ฑฐ๋ ๊ณ์ฐ์ด ๋ณต์กํ ๊ฒฐ๊ณผ
- ๋ฐ๋ณต ์ ๊ทผ์ด ๋ง์ ๋ฐ์ดํฐ: ์ฌ์ฉ์๊ฐ ์์ฃผ ์ ๊ทผํ๋ ์ธ๊ธฐ ์ฝํ ์ธ
- ๋ณ๊ฒฝ์ด ์ ์ ๋ฐ์ดํฐ: ์ํ ์ ๋ณด, ์นดํ ๊ณ ๋ฆฌ ๋ฑ ์์ฃผ ๋ฐ๋์ง ์๋ ์ ๋ณด
์๋ฅผ ๋ค์ด, ์ฌ๋ฅ๋ท์์๋ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ ๋ชฉ๋ก์ด๋ ์์ฃผ ์กฐํ๋๋ ํ๋กํ ์ ๋ณด ๊ฐ์ ๊ฒ๋ค์ด ์ข์ ์บ์ฑ ๋์์ด ๋ ์ ์์ด์. ์ด๋ฐ ๋ฐ์ดํฐ๋ ์ฝ๊ธฐ๊ฐ ๋ง๊ณ ๋ณ๊ฒฝ์ ์ ์ผ๋๊น์! ๐
4.2 ์บ์ ์ ๋ต ํจํด
์บ์๋ฅผ ์ ์ฉํ ๋๋ ๋ช ๊ฐ์ง ์ผ๋ฐ์ ์ธ ํจํด์ด ์์ด์. ์ํฉ์ ๋ง๊ฒ ์ ํํด๋ณด์ธ์!
1. Cache-Aside (Lazy Loading) ํจํด
๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํจํด์ผ๋ก, ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ ๋:
- ๋จผ์ ์บ์๋ฅผ ํ์ธ
- ์บ์์ ์์ผ๋ฉด(Cache Miss) DB์์ ์กฐํ
- DB์์ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ฅผ ์บ์์ ์ ์ฅ
- ๋ฐ์ดํฐ ๋ฐํ
์ฅ์ : ํ์ํ ๋ฐ์ดํฐ๋ง ์บ์ฑ๋์ด ๋ฉ๋ชจ๋ฆฌ ํจ์จ์
๋จ์ : ์ฒซ ์์ฒญ์ ๋๋ฆผ(Cache Miss)
2. Write-Through ํจํด
๋ฐ์ดํฐ๋ฅผ ์ธ ๋:
- DB์ ๋ฐ์ดํฐ ์ฐ๊ธฐ
- ๋์์ ์บ์๋ ์ ๋ฐ์ดํธ
์ฅ์ : ์บ์์ DB๊ฐ ํญ์ ๋๊ธฐํ๋จ
๋จ์ : ์ฐ๊ธฐ ์์ ์ด ์ฝ๊ฐ ๋๋ ค์ง ์ ์์
3. Write-Behind (Write-Back) ํจํด
๋ฐ์ดํฐ๋ฅผ ์ธ ๋:
- ์บ์์๋ง ๋จผ์ ์ฐ๊ธฐ
- ๋์ค์ ์ผ๊ด์ ์ผ๋ก DB์ ๋ฐ์
์ฅ์ : ์ฐ๊ธฐ ์ฑ๋ฅ์ด ๋งค์ฐ ๋น ๋ฆ
๋จ์ : ์บ์ ์ฅ์ ์ ๋ฐ์ดํฐ ์ ์ค ์ํ
4. Refresh-Ahead ํจํด
๋ง๋ฃ ์๊ฐ์ด ๋ค๊ฐ์ค๋ ์บ์ ํญ๋ชฉ์:
- ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฏธ๋ฆฌ ๊ฐฑ์
- ์ฌ์ฉ์ ์์ฒญ ์ ์ ์ค๋น
์ฅ์ : ์บ์ ๋ฏธ์ค๊ฐ ๊ฑฐ์ ์์
๋จ์ : ๊ตฌํ์ด ๋ณต์กํ๊ณ ๋ถํ์ํ ๊ฐฑ์ ๊ฐ๋ฅ์ฑ
4.3 ์บ์ ๋ง๋ฃ ์ ๋ต
์บ์ ๋ฐ์ดํฐ๋ ์์ํ ๋ณด๊ดํ ์ ์์ด์. ์ ์ ํ ๋ง๋ฃ ์๊ฐ(TTL, Time-To-Live)์ ์ค์ ํ๋ ๊ฒ์ด ์ค์ํด์!
๋ฐ์ดํฐ ํน์ฑ๋ณ ๊ถ์ฅ TTL:
- ์์ฃผ ๋ณ๊ฒฝ๋๋ ๋ฐ์ดํฐ: ์งง์ TTL (๋ช ์ด~๋ช ๋ถ)
- ์ค-์ ์ ๋ฐ์ดํฐ: ์ค๊ฐ TTL (๋ช ์๊ฐ~ํ๋ฃจ)
- ๊ฑฐ์ ๋ณ๊ฒฝ๋์ง ์๋ ๋ฐ์ดํฐ: ๊ธด TTL (๋ฉฐ์น ~๋ช ์ฃผ)
TTL์ ๋๋ฌด ์งง๊ฒ ์ค์ ํ๋ฉด ์บ์ ํจ๊ณผ๊ฐ ๋จ์ด์ง๊ณ , ๋๋ฌด ๊ธธ๊ฒ ์ค์ ํ๋ฉด ๋ฐ์ดํฐ ์ผ๊ด์ฑ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ด์. ๋ฐ์ดํฐ ํน์ฑ์ ๋ง๊ฒ ์ ์ ํ ์ค์ ํ๋ ๊ฒ์ด ์ค์ํด์!
๐ก ์ค์ฉ์ ์ธ ํ: ์บ์ ๋ง๋ฃ ์๊ฐ์ ์ ํํ ์์ธกํ๊ธฐ ์ด๋ ต๋ค๋ฉด, ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ํด๋น ์บ์๋ฅผ ๋ช ์์ ์ผ๋ก ์ญ์ (์บ์ ๋ฌดํจํ)ํ๋ ๋ฐฉ์๋ ์ข์ ์ ๋ต์ด์์!
5. ์ค์ ์์ : ์ํ ์ ๋ณด ์บ์ฑํ๊ธฐ ๐
์ด์ ์ค์ ๋ก Spring Data Redis๋ฅผ ์ฌ์ฉํด์ ์ํ ์ ๋ณด๋ฅผ ์บ์ฑํ๋ ์์ ๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์! ์ด ์์ ๋ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ์์ ์ธ๊ธฐ ์๋ ์ฌ๋ฅ ์ํ ์ ๋ณด๋ฅผ ์บ์ฑํ๋ ๊ฒ๊ณผ ๋น์ทํ ์๋ฆฌ์์.
5.1 ๋๋ฉ์ธ ๋ชจ๋ธ ๋ง๋ค๊ธฐ
๋จผ์ ์ํ ์ ๋ณด๋ฅผ ๋ด์ Product ํด๋์ค๋ฅผ ๋ง๋ค์ด์:
import java.io.Serializable;
import java.math.BigDecimal;
public class Product implements Serializable {
private Long id;
private String name;
private String description;
private BigDecimal price;
private int stockQuantity;
// ์์ฑ์, getter, setter, toString ๋ฑ ์๋ต
// ์ง๋ ฌํ๋ฅผ ์ํ serialVersionUID
private static final long serialVersionUID = 1L;
}
Serializable์ ๊ตฌํํ ์ด์ ๋ Redis์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ ๋ ์ง๋ ฌํ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ด์์. ํ์ง๋ง ์์ ์ค์ ํ JSON ์ง๋ ฌํ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ด ์ธํฐํ์ด์ค๋ ํ์๋ ์๋์์.
5.2 ๋ ํฌ์งํ ๋ฆฌ ๊ณ์ธต ๊ตฌํํ๊ธฐ
์ด์ ์ํ ์ ๋ณด๋ฅผ DB์์ ๊ฐ์ ธ์ค๋ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ๋ง๋ค์ด์:
@Repository
public class ProductRepository {
// ์ค์ ๋ก๋ DB์์ ์กฐํํ๋ ๋ก์ง์ด ๋ค์ด๊ฐ ๋ถ๋ถ
// ์์ ๋ฅผ ์ํด ๊ฐ๋จํ ๊ตฌํ
public Product findById(Long id) {
// DB ์กฐํ๋ฅผ ์๋ฎฌ๋ ์ด์
(์ค์ ๋ก๋ ๋๋ฆฐ ์์
)
try {
Thread.sleep(1000); // 1์ด ์ง์ฐ (DB ์กฐํ ์๊ฐ ๊ฐ์ )
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Product product = new Product();
product.setId(id);
product.setName("๋ฉ์ง ์ํ " + id);
product.setDescription("์ด ์ํ์ ์ ๋ง ๋ฉ์ ธ์!");
product.setPrice(new BigDecimal("15000"));
product.setStockQuantity(100);
return product;
}
}
5.3 Redis ์บ์ ์๋น์ค ๊ตฌํํ๊ธฐ
์ด์ Redis๋ฅผ ์ฌ์ฉํด ์ํ ์ ๋ณด๋ฅผ ์บ์ฑํ๋ ์๋น์ค๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ์:
@Service
public class ProductService {
private final ProductRepository productRepository;
private final RedisTemplate<String, Object> redisTemplate;
// ์บ์ ํค ์ ๋์ฌ์ ๋ง๋ฃ ์๊ฐ ์ค์
private static final String CACHE_KEY_PREFIX = "product:";
private static final long CACHE_TTL_SECONDS = 3600; // 1์๊ฐ
@Autowired
public ProductService(ProductRepository productRepository, RedisTemplate<String, Object> redisTemplate) {
this.productRepository = productRepository;
this.redisTemplate = redisTemplate;
}
public Product getProductById(Long id) {
String cacheKey = CACHE_KEY_PREFIX + id;
// 1. ์บ์์์ ์กฐํ ์๋
Product cachedProduct = (Product) redisTemplate.opsForValue().get(cacheKey);
// 2. ์บ์์ ์์ผ๋ฉด ๋ฐ๋ก ๋ฐํ
if (cachedProduct != null) {
System.out.println("์บ์ ํํธ! Redis์์ ์ํ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ต๋๋ค.");
return cachedProduct;
}
// 3. ์บ์์ ์์ผ๋ฉด DB์์ ์กฐํ
System.out.println("์บ์ ๋ฏธ์ค! DB์์ ์ํ ์ ๋ณด๋ฅผ ์กฐํํฉ๋๋ค...");
Product product = productRepository.findById(id);
// 4. DB์์ ์กฐํํ ๋ฐ์ดํฐ๋ฅผ ์บ์์ ์ ์ฅ
redisTemplate.opsForValue().set(cacheKey, product, CACHE_TTL_SECONDS, TimeUnit.SECONDS);
System.out.println("์ํ ์ ๋ณด๋ฅผ Redis์ ์บ์ฑํ์ต๋๋ค. TTL: " + CACHE_TTL_SECONDS + "์ด");
return product;
}
// ์ํ ์ ๋ณด๊ฐ ์
๋ฐ์ดํธ๋๋ฉด ์บ์๋ ๊ฐฑ์ ํ๋ ๋ฉ์๋
public void updateProduct(Product product) {
// DB ์
๋ฐ์ดํธ ๋ก์ง (์๋ต)
// ์บ์ ๊ฐฑ์ (Write-Through ํจํด)
String cacheKey = CACHE_KEY_PREFIX + product.getId();
redisTemplate.opsForValue().set(cacheKey, product, CACHE_TTL_SECONDS, TimeUnit.SECONDS);
}
// ์ํ์ด ์ญ์ ๋๋ฉด ์บ์์์๋ ์ ๊ฑฐํ๋ ๋ฉ์๋
public void deleteProduct(Long id) {
// DB ์ญ์ ๋ก์ง (์๋ต)
// ์บ์์์๋ ์ญ์
String cacheKey = CACHE_KEY_PREFIX + id;
redisTemplate.delete(cacheKey);
}
}
์ด ์๋น์ค๋ Cache-Aside ํจํด๊ณผ Write-Through ํจํด์ ํจ๊ป ์ฌ์ฉํ์ด์. ์กฐํํ ๋๋ ์บ์๋ฅผ ๋จผ์ ํ์ธํ๊ณ , ์ ๋ฐ์ดํธํ ๋๋ DB์ ์บ์๋ฅผ ํจ๊ป ๊ฐฑ์ ํ์ฃ !
5.4 ์ปจํธ๋กค๋ฌ ๊ตฌํํ๊ธฐ
๋ง์ง๋ง์ผ๋ก API ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์ด ํ ์คํธํด๋ณผ๊ฒ์:
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
@Autowired
public ProductController(ProductService productService) {
this.productService = productService;
}
@GetMapping("/{id}")
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
long startTime = System.currentTimeMillis();
Product product = productService.getProductById(id);
long endTime = System.currentTimeMillis();
System.out.println("์๋ต ์๊ฐ: " + (endTime - startTime) + "ms");
return ResponseEntity.ok(product);
}
@PutMapping("/{id}")
public ResponseEntity<Product> updateProduct(@PathVariable Long id, @RequestBody Product product) {
product.setId(id);
productService.updateProduct(product);
return ResponseEntity.ok(product);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}
}
์ด์ ์ด API๋ฅผ ํธ์ถํด๋ณด๋ฉด:
- ์ฒซ ๋ฒ์งธ ์์ฒญ: DB์์ ์กฐํํ๋ฏ๋ก ์ฝ 1์ด ์ ๋ ์์ (์บ์ ๋ฏธ์ค)
- ๋ ๋ฒ์งธ ์์ฒญ: ์บ์์์ ๋ฐ๋ก ๊ฐ์ ธ์ค๋ฏ๋ก ๋ช ๋ฐ๋ฆฌ์ด ๋ด๋ก ์๋ต (์บ์ ํํธ)
์ด๋ ๊ฒ Redis ์บ์๋ฅผ ์ ์ฉํ๋ฉด ์๋ต ์๊ฐ์ด ํฌ๊ฒ ํฅ์๋๋ ๊ฑธ ํ์ธํ ์ ์์ด์! ํนํ DB ์กฐํ๊ฐ ๋ณต์กํ๊ฑฐ๋ ๋ถํ๊ฐ ํฐ ๊ฒฝ์ฐ์ ํจ๊ณผ๊ฐ ๋ ํฌ๋ต๋๋ค. ๐
๐ก ์ค๋ฌด ํ: ์ค์ ํ๋ก์ ํธ์์๋ ์ ์ฝ๋์ ์์ธ ์ฒ๋ฆฌ, ๋ก๊น , ํธ๋์ญ์ ๊ด๋ฆฌ ๋ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์์. ๋ํ ์บ์ ํค ์์ฑ ๋ก์ง์ ๋ณ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ก ๋ถ๋ฆฌํ๋ฉด ์ ์ง๋ณด์๊ฐ ๋ ์ฌ์์ ธ์!
6. ์ฑ๋ฅ ์ธก์ ๋ฐ ์ต์ ํ ํ ๐
Redis ์บ์๋ฅผ ์ ์ฉํ๋ค๋ฉด ์ผ๋ง๋ ์ฑ๋ฅ์ด ํฅ์๋๋์ง ์ธก์ ํ๊ณ , ๋ ์ต์ ํํ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณผ๊น์?
6.1 ์ฑ๋ฅ ์ธก์ ํ๊ธฐ
์บ์ ์ ์ฉ ์ ํ์ ์ฑ๋ฅ์ ๋น๊ตํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ด์:
- ์๋ต ์๊ฐ ์ธก์ : ์ ์์ ์ฒ๋ผ API ํธ์ถ ์๊ฐ์ ์ธก์
- ์ฒ๋ฆฌ๋(Throughput) ์ธก์ : ์ด๋น ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์์ฒญ ์ ๋น๊ต
- DB ๋ถํ ๊ฐ์ ์ธก์ : DB ์๋ฒ์ CPU, ๋ฉ๋ชจ๋ฆฌ, I/O ์ฌ์ฉ๋ ๋ณํ ๊ด์ฐฐ
- ์บ์ ํํธ์จ ๋ชจ๋ํฐ๋ง: ์ ์ฒด ์์ฒญ ์ค ์บ์์์ ์ฒ๋ฆฌ๋ ๋น์จ
์ฑ๋ฅ ํ ์คํธ ๋๊ตฌ๋ก๋ JMeter, Gatling, k6 ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํ๋ฉด ์ข์์!
6.2 Redis ์ต์ ํ ํ
Redis ์บ์๋ฅผ ๋ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ ํ์ ์์๋ณผ๊น์?
1. ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ
- ์ ์ ํ maxmemory ์ค์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ ํ
- eviction ์ ์ฑ ์ค์ (์: allkeys-lru, volatile-lru)
- ํ์ํ ๋ฐ์ดํฐ๋ง ์บ์ฑํ๊ณ ๋ถํ์ํ ํ๋๋ ์ ์ธ
2. ํค ์ค๊ณ
- ์๋ฏธ ์๋ ํค ๋ค์ด๋ฐ ๊ท์น ์ฌ์ฉ (namespace:entity:id)
- ๋๋ฌด ๊ธด ํค ์ด๋ฆ ํผํ๊ธฐ (๋ฉ๋ชจ๋ฆฌ ๋ญ๋น)
- ๋ง๋ฃ ์๊ฐ์ด ๋น์ทํ ๋ฐ์ดํฐ๋ผ๋ฆฌ ๊ทธ๋ฃนํ
3. ์ง๋ ฌํ ์ต์ ํ
- JSON๋ณด๋ค MessagePack, Protocol Buffers ๊ฐ์ ๋ฐ์ด๋๋ฆฌ ์ง๋ ฌํ ๊ณ ๋ ค
- ํ์ํ ํ๋๋ง ์ ํ์ ์ผ๋ก ์ง๋ ฌํ
4. ๋ฐฐ์น ์ฒ๋ฆฌ
- mget, mset ๊ฐ์ ๋ฐฐ์น ๋ช ๋ น์ด ํ์ฉ
- ํ์ดํ๋ผ์ด๋(pipelining)์ผ๋ก ์ฌ๋ฌ ๋ช ๋ น์ด ํ ๋ฒ์ ์ ์ก
5. ๋คํธ์ํฌ ์ต์ ํ
- Redis ์๋ฒ์ ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ๋ฅผ ๊ฐ๊น์ด ๋ฐฐ์น
- ์ฐ๊ฒฐ ํ ํฌ๊ธฐ ์ต์ ํ
์บ์ ํํธ์จ(Cache Hit Ratio)์ ์บ์ ์ฑ๋ฅ์ ํต์ฌ ์งํ์์. ํํธ์จ์ด ๋ฎ๋ค๋ฉด ์บ์ฑ ์ ๋ต์ด๋ TTL์ ์ฌ๊ฒํ ํด๋ณผ ํ์๊ฐ ์์ด์!
6.3 Spring Boot ์บ์ ์ถ์ํ ํ์ฉํ๊ธฐ
์ง๊ธ๊น์ง๋ RedisTemplate์ ์ง์ ์ฌ์ฉํ์ง๋ง, Spring์ ์บ์ ์ถ์ํ(Cache Abstraction)๋ฅผ ํ์ฉํ๋ฉด ๋ ๊ฐํธํ๊ฒ ์บ์ฑ์ ์ ์ฉํ ์ ์์ด์!
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(60)) // ๊ธฐ๋ณธ TTL 60๋ถ
.disableCachingNullValues()
.serializeKeysWith(
RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())
)
.serializeValuesWith(
RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())
);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(cacheConfiguration)
.withCacheConfiguration("products", // ํน์ ์บ์์ ๋ํ ์ค์
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10)) // ์ํ ์บ์๋ 10๋ถ
)
.transactionAware()
.build();
}
}
@Service
public class ProductServiceWithCacheAnnotations {
private final ProductRepository productRepository;
@Autowired
public ProductServiceWithCacheAnnotations(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@Cacheable(value = "products", key = "#id")
public Product getProductById(Long id) {
// ์บ์์ ์์ ๋๋ง ์คํ๋จ
return productRepository.findById(id);
}
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
// DB ์
๋ฐ์ดํธ ๋ก์ง (์๋ต)
return product; // ๋ฐํ๊ฐ์ด ์บ์์ ์ ์ฅ๋จ
}
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) {
// DB ์ญ์ ๋ก์ง (์๋ต)
}
}
์ด๋ ๊ฒ @Cacheable, @CachePut, @CacheEvict ๊ฐ์ ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ฉด ์บ์ฑ ๋ก์ง์ ๋น์ฆ๋์ค ๋ก์ง๊ณผ ๋ถ๋ฆฌํ ์ ์์ด ์ฝ๋๊ฐ ๋ ๊น๋ํด์ ธ์! ๐
7. ์ด์ ํ๊ฒฝ์์์ ์ฃผ์์ฌํญ โ ๏ธ
Redis ์บ์๋ฅผ ์ค์ ์ด์ ํ๊ฒฝ์ ์ ์ฉํ ๋๋ ๋ช ๊ฐ์ง ์ค์ํ ๊ณ ๋ ค์ฌํญ์ด ์์ด์!
7.1 ๋ฐ์ดํฐ ์ผ๊ด์ฑ ๊ด๋ฆฌ
์บ์์ DB ๊ฐ์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ํญ์ ์ค์ํ ์ด์์์:
- ์บ์ ๋ฌดํจํ ์ ๋ต: ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋ ๊ด๋ จ ์บ์๋ฅผ ์ ์ ํ ์ญ์ /๊ฐฑ์
- TTL ๊ด๋ฆฌ: ๋ฐ์ดํฐ ํน์ฑ์ ๋ง๋ ์ ์ ํ ๋ง๋ฃ ์๊ฐ ์ค์
- ์ด๋ฒคํธ ๊ธฐ๋ฐ ์บ์ ๊ฐฑ์ : DB ๋ณ๊ฒฝ ์ด๋ฒคํธ๋ฅผ ๊ตฌ๋ ํ์ฌ ์บ์ ์๋ ๊ฐฑ์
๋ฐ์ดํฐ ์ผ๊ด์ฑ๊ณผ ์ฑ๋ฅ์ ์ข ์ข ํธ๋ ์ด๋์คํ ๊ด๊ณ์ ์์ด์. ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ์ ์ ํ ๊ท ํ์ ์ ์ฐพ๋ ๊ฒ์ด ์ค์ํด์!
7.2 ์ฅ์ ๋์ ์ ๋ต
Redis ์๋ฒ์ ๋ฌธ์ ๊ฐ ์๊ฒผ์ ๋ ๋์ ๋ฐฉ๋ฒ์ ๋ฏธ๋ฆฌ ์ค๋นํด๋์ธ์:
- Circuit Breaker ํจํด: Redis ์ฐ๊ฒฐ ์คํจ ์ DB๋ก ํด๋ฐฑ
- Redis Sentinel: ๊ณ ๊ฐ์ฉ์ฑ์ ์ํ ์๋ ์ฅ์ ์กฐ์น
- Redis Cluster: ๋ฐ์ดํฐ ๋ถ์ฐ ๋ฐ ๋ณต์ ๋ก ์์ ์ฑ ํ๋ณด
- ๋ชจ๋ํฐ๋ง ๋ฐ ์๋ฆผ: Redis ์ํ๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋ง
Circuit Breaker ์์ (Resilience4j ์ฌ์ฉ)
@Service
public class ResilientProductService {
private final ProductRepository productRepository;
private final RedisTemplate<String, Object> redisTemplate;
private final CircuitBreaker circuitBreaker;
@Autowired
public ResilientProductService(ProductRepository productRepository,
RedisTemplate<String, Object> redisTemplate,
CircuitBreakerRegistry circuitBreakerRegistry) {
this.productRepository = productRepository;
this.redisTemplate = redisTemplate;
this.circuitBreaker = circuitBreakerRegistry.circuitBreaker("redisCircuitBreaker");
}
public Product getProductById(Long id) {
String cacheKey = "product:" + id;
// Circuit Breaker๋ก Redis ํธ์ถ ๋ํ
Supplier<Product> redisCall = CircuitBreaker.decorateSupplier(circuitBreaker,
() -> (Product) redisTemplate.opsForValue().get(cacheKey));
try {
// Redis์์ ์กฐํ ์๋
Product cachedProduct = redisCall.get();
if (cachedProduct != null) {
return cachedProduct;
}
} catch (Exception e) {
// Redis ์๋ฌ ๋ก๊น
System.err.println("Redis ์กฐํ ์คํจ: " + e.getMessage());
}
// Redis์์ ์กฐํ ์คํจํ๋ฉด DB์์ ์กฐํ
Product product = productRepository.findById(id);
try {
// Redis์ ์บ์ฑ ์๋ (์๋ฌ๊ฐ ๋ฐ์ํด๋ ๋ฉ์ธ ๋ก์ง์ ๊ณ์ ์งํ)
redisTemplate.opsForValue().set(cacheKey, product, 1, TimeUnit.HOURS);
} catch (Exception e) {
System.err.println("Redis ์บ์ฑ ์คํจ: " + e.getMessage());
}
return product;
}
}
7.3 ๋ณด์ ๊ณ ๋ ค์ฌํญ
Redis๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ์ฆ ์์ด ์ ๊ทผ ๊ฐ๋ฅํ๋ฏ๋ก ๋ณด์์ ์ ๊ฒฝ ์จ์ผ ํด์:
- ๋น๋ฐ๋ฒํธ ์ค์ : Redis ์๋ฒ์ ์ธ์ฆ ๋น๋ฐ๋ฒํธ ์ค์
- ๋คํธ์ํฌ ๊ฒฉ๋ฆฌ: Redis ์๋ฒ๋ฅผ ์ธ๋ถ์ ๋ ธ์ถํ์ง ์๊ธฐ
- SSL/TLS ์ ์ฉ: ๋ฐ์ดํฐ ์ ์ก ์ํธํ (Redis 6.0 ์ด์)
- ๋ฏผ๊ฐ ์ ๋ณด ์ ์ธ: ๊ฐ์ธ์ ๋ณด ๋ฑ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ ์บ์ฑํ์ง ์๊ธฐ
Redis๋ ์ฑ๋ฅ์ ์ต์ ํ๋ ์๋ฃจ์ ์ด๋ผ ๊ธฐ๋ณธ ์ค์ ์ ๋ณด์๋ณด๋ค ์ฑ๋ฅ์ ์ฐ์ ์ํด์. ์ด์ ํ๊ฒฝ์์๋ ๋ฐ๋์ ๋ณด์ ์ค์ ์ ๊ฐํํด์ผ ํด์!
7.4 ๋ชจ๋ํฐ๋ง ๋ฐ ์ด์
Redis ์บ์์ ๊ฑด๊ฐ ์ํ๋ฅผ ์ง์์ ์ผ๋ก ๋ชจ๋ํฐ๋งํ์ธ์:
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋: maxmemory ์ ํ์ ๊ทผ์ ํ๋์ง ํ์ธ
- ๋ช ๋ น์ด ์ฒ๋ฆฌ๋: ์ด๋น ์ฒ๋ฆฌ๋๋ ๋ช ๋ น์ด ์ ๋ชจ๋ํฐ๋ง
- ์๋ต ์๊ฐ: Redis ๋ช ๋ น์ด ์ง์ฐ ์๊ฐ ์ถ์
- ์บ์ ํํธ์จ: ์บ์ ํจ์จ์ฑ ์ธก์
- ์ฐ๊ฒฐ ์: ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ์ํ ํ์ธ
Prometheus + Grafana, Redis Exporter, Spring Boot Actuator ๋ฑ์ ํ์ฉํ๋ฉด ํจ๊ณผ์ ์ธ ๋ชจ๋ํฐ๋ง์ด ๊ฐ๋ฅํด์!
๐ก ์ด์ ํ: Redis INFO ๋ช ๋ น์ด๋ก ๊ฐ๋จํ ์ํ๋ฅผ ํ์ธํ ์ ์์ด์. ์ฃผ๊ธฐ์ ์ผ๋ก ๋ชจ๋ํฐ๋ง ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ฌ ๋ฌธ์ ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ์ธ์!
8. ๋ง๋ฌด๋ฆฌ ๋ฐ ๋ค์ ๋จ๊ณ ๐ฏ
์ง๊ธ๊น์ง Spring Data Redis๋ฅผ ํ์ฉํ ์บ์ ์๋ฒ ์ฐ๋์ ๋ํด ์์๋ดค์ด์! ์ด์ ์ฌ๋ฌ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ํฐ๋ณด ์์ง์ ๋ฌ ์ค๋น๊ฐ ๋๋ค์! ๐
8.1 ์์ฝ
์ด๋ฒ ๊ธ์์ ๋ค๋ฃฌ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณผ๊ฒ์:
- Redis์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ ์บ์ฑ์ ์ค์์ฑ
- Spring Data Redis ์ค์ ๋ฐฉ๋ฒ
- ํจ๊ณผ์ ์ธ ์บ์ ์ ๋ต ์๋ฆฝ ๋ฐฉ๋ฒ
- ์ค์ ์์ : ์ํ ์ ๋ณด ์บ์ฑ ๊ตฌํ
- ์ฑ๋ฅ ์ต์ ํ ๋ฐ ๋ชจ๋ํฐ๋ง ๋ฐฉ๋ฒ
- ์ด์ ํ๊ฒฝ์์์ ์ฃผ์์ฌํญ
Redis ์บ์๋ฅผ ์ ์ ํ ํ์ฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ด์. ํนํ DB ๋ถํ๊ฐ ํฐ ์๋น์ค๋ ๋ฐ๋ณต์ ์ธ ์กฐํ๊ฐ ๋ง์ ์๋น์ค์์ ํจ๊ณผ๊ฐ ๋๋๋ฌ์ ธ์!
8.2 ๋ค์ ๋จ๊ณ
Redis ์บ์ฑ์ ๋ ๊น์ด ๋ค์ด๊ฐ๊ณ ์ถ๋ค๋ฉด ๋ค์ ์ฃผ์ ๋ค์ ์ดํด๋ณด์ธ์:
- Redis ๊ณ ๊ธ ๊ธฐ๋ฅ: Pub/Sub, Stream, Lua ์คํฌ๋ฆฝํธ ๋ฑ
- ๋ถ์ฐ ์บ์ฑ: Redis Cluster๋ฅผ ํ์ฉํ ๋๊ท๋ชจ ์บ์ฑ
- ์บ์ ์ผ๊ด์ฑ ํจํด: ๋ ์ ๊ตํ ์บ์ ๋ฌดํจํ ์ ๋ต
- ๋ก์ปฌ ์บ์ + Redis: ๋ค์ค ๋ ๋ฒจ ์บ์ฑ ๊ตฌ์กฐ
- Spring Cache์ Redis: ๋ ์ ์ธ์ ์ธ ์บ์ฑ ๋ฐฉ์
์บ์ฑ์ ๋จ์ํ ๊ธฐ์ ์ ์ ์ฉํ๋ ๊ฒ๋ณด๋ค ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ๊ณผ ๋ฐ์ดํฐ ํน์ฑ์ ์ดํดํ๊ณ ์ ์ ํ ์ ๋ต์ ์๋ฆฝํ๋ ๊ฒ์ด ๋ ์ค์ํด์. ์ฌ๋ฌ๋ถ์ ์๋น์ค์ ๋ง๋ ์ต์ ์ ์บ์ฑ ์ ๋ต์ ์ฐพ์๋ณด์ธ์!
์ค๋ ๋ฐฐ์ด ๋ด์ฉ์ ํ์ฉํ๋ฉด ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ํ๋ซํผ๋ ๋ ๋น ๋ฅด๊ณ ์์ ์ ์ธ ์๋น์ค๋ฅผ ์ ๊ณตํ ์ ์์ ๊ฑฐ์์. ์ฌ์ฉ์ ๊ฒฝํ ํฅ์์ ๋ฌผ๋ก ์๋ฒ ๋น์ฉ ์ ๊ฐ์๋ ๋์์ด ๋ ๊ฑฐ์์! ๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.