์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ Spring Data Redis๋กœ ์ดˆ๊ฐ„๋‹จ ์บ์‹œ ์„œ๋ฒ„ ์—ฐ๋™ํ•˜๊ธฐ: ์„ฑ๋Šฅ ํญ๊ฒฉ๊ธฐ ๋งŒ๋“ค๊ธฐ ๐Ÿ’ฃ

๐Ÿš€ Spring Data Redis๋กœ ์ดˆ๊ฐ„๋‹จ ์บ์‹œ ์„œ๋ฒ„ ์—ฐ๋™ํ•˜๊ธฐ: ์„ฑ๋Šฅ ํญ๊ฒฉ๊ธฐ ๋งŒ๋“ค๊ธฐ ๐Ÿ’ฃ

์•ˆ๋…•ํ•˜์„ธ์š” ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ„ฐ๋ณด ์—”์ง„์„ ๋‹ฌ์•„์ค„ Spring Data Redis๋ฅผ ํ™œ์šฉํ•œ ์บ์‹œ ์„œ๋ฒ„ ์—ฐ๋™์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ๊ด€์‹ฌ ์žˆ๋Š” ๋ถ„๋“ค, ํŠนํžˆ Java ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๊ผญ ์•Œ์•„์•ผ ํ•  ๋‚ด์šฉ์ด๋‹ˆ ๋๊นŒ์ง€ ํ•จ๊ป˜ํ•ด์š”! ๐Ÿ˜Ž

๐Ÿ“š ๋ชฉ์ฐจ

  1. Redis์™€ ์บ์‹ฑ์ด ๋ญ๊ธธ๋ž˜? ๐Ÿค”
  2. Spring Data Redis ์‹œ์ž‘ํ•˜๊ธฐ ๐Ÿ’ป
  3. Redis ์—ฐ๊ฒฐ ์„ค์ •ํ•˜๊ธฐ โš™๏ธ
  4. ์บ์‹œ ์ „๋žต ์ˆ˜๋ฆฝํ•˜๊ธฐ ๐Ÿ“
  5. ์‹ค์ „ ์˜ˆ์ œ: ์ƒํ’ˆ ์ •๋ณด ์บ์‹ฑํ•˜๊ธฐ ๐Ÿ›’
  6. ์„ฑ๋Šฅ ์ธก์ • ๋ฐ ์ตœ์ ํ™” ํŒ ๐Ÿ“Š
  7. ์šด์˜ ํ™˜๊ฒฝ์—์„œ์˜ ์ฃผ์˜์‚ฌํ•ญ โš ๏ธ
  8. ๋งˆ๋ฌด๋ฆฌ ๋ฐ ๋‹ค์Œ ๋‹จ๊ณ„ ๐ŸŽฏ

1. Redis์™€ ์บ์‹ฑ์ด ๋ญ๊ธธ๋ž˜? ๐Ÿค”

์—ฌ๋Ÿฌ๋ถ„, ์›น์‚ฌ์ดํŠธ๊ฐ€ ๋А๋ ค์„œ ์‚ฌ์šฉ์ž๋“ค์ด ๋– ๋‚˜๊ฐ„ ๊ฒฝํ—˜ ์žˆ์œผ์‹ ๊ฐ€์š”? ใ… ใ…  ์•„๋‹ˆ๋ฉด DB ์„œ๋ฒ„๊ฐ€ ๊ณผ๋ถ€ํ•˜๋กœ ํ„ฐ์ ธ๋ฒ„๋ฆฐ ์•…๋ชฝ ๊ฐ™์€ ์ˆœ๊ฐ„? ๐Ÿ˜ฑ ์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์˜ ํ•ด๊ฒฐ์‚ฌ๊ฐ€ ๋ฐ”๋กœ Redis(Remote Dictionary Server)์˜ˆ์š”!

Redis๋ž€? ์ธ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ์ €์žฅ์†Œ๋กœ, ํ‚ค-๊ฐ’ ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ดˆ๊ณ ์†์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ์˜คํ”ˆ์†Œ์Šค ์†”๋ฃจ์…˜์ด์—์š”. ์บ์‹œ, ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค, ์‹ค์‹œ๊ฐ„ ๋ถ„์„ ๋“ฑ ๋‹ค์–‘ํ•œ ์šฉ๋„๋กœ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.

๊ทผ๋ฐ ์บ์‹ฑ์ด ๋ญ๋ƒ๊ตฌ์š”? ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ์ €์žฅํ•ด๋‘๊ณ  ๋น ๋ฅด๊ฒŒ ๊บผ๋‚ด ์“ฐ๋Š” ๊ธฐ์ˆ ์ด์—์š”. ๋งˆ์น˜ ์—ฌ๋Ÿฌ๋ถ„์ด ์ž์ฃผ ์“ฐ๋Š” ๋ฌผ๊ฑด์„ ์ฑ…์ƒ ์œ„์— ์˜ฌ๋ ค๋‘๋Š” ๊ฒƒ์ฒ˜๋Ÿผ์š”! ๐Ÿ‘

Spring Data Redis ์บ์‹ฑ ํ๋ฆ„ 1. ์ฒซ ์š”์ฒญ: ์บ์‹œ ๋ฏธ์Šค โ†’ DB ์กฐํšŒ ๊ฒฐ๊ณผ ์บ์‹œ์— ์ €์žฅ 2. ์ดํ›„ ์š”์ฒญ: ์บ์‹œ ํžˆํŠธ โ†’ ์ฆ‰์‹œ ์‘๋‹ต ์‘๋‹ต ๋ฐ˜ํ™˜ Spring ์„œ๋น„์Šค ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง Redis ์บ์‹œ (๋น ๋ฆ„ โšก) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (๋А๋ฆผ ๐Ÿข)

Redis์˜ ์žฅ์ ์€ ์ •๋ง ๋งŽ์€๋ฐ์š”, ๋Œ€ํ‘œ์ ์œผ๋กœ๋Š”:

  1. ์ดˆ๊ณ ์† ์„ฑ๋Šฅ: ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜์ด๋ผ ๋””์Šคํฌ I/O๊ฐ€ ์—†์–ด์„œ ์—„์ฒญ ๋นจ๋ผ์š”! ๐ŸŽ๏ธ
  2. ๋‹ค์–‘ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ: ๋ฌธ์ž์—ด, ํ•ด์‹œ, ๋ฆฌ์ŠคํŠธ, ์…‹, ์ •๋ ฌ๋œ ์…‹ ๋“ฑ ์—ฌ๋Ÿฌ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์ง€์›ํ•ด์š”.
  3. ์›์ž์  ์—ฐ์‚ฐ: ๋ณต์žกํ•œ ์—ฐ์‚ฐ๋„ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.
  4. ์˜์†์„ฑ: ๋ฉ”๋ชจ๋ฆฌ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋””์Šคํฌ์— ์ €์žฅํ•  ์ˆ˜ ์žˆ์–ด์š”.
  5. ํด๋Ÿฌ์Šคํ„ฐ๋ง: ์—ฌ๋Ÿฌ ์„œ๋ฒ„๋กœ ํ™•์žฅ ๊ฐ€๋Šฅํ•ด์„œ ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค์—๋„ ์ ํ•ฉํ•ด์š”.

์š”์ฆ˜ ์žฌ๋Šฅ๋„ท๊ฐ™์€ ํ”Œ๋žซํผ๋„ 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์— ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์ž๋™์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค˜์„œ ์ •๋ง ํŽธ๋ฆฌํ•ด์š”! ๐Ÿ˜

Spring Data Redis ์—ฐ๊ฒฐ ๊ตฌ์กฐ Spring Boot ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ RedisTemplate RedisConnectionFactory Lettuce Client Redis ์„œ๋ฒ„ In-Memory ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ user:1001 {"name":"ํ™๊ธธ๋™",...} product:2002 {"title":"๋…ธํŠธ๋ถ",...} session:xyz123 {"userId":1001,...} TCP ์—ฐ๊ฒฐ 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 ์บ์‹ฑ ๋Œ€์ƒ ์„ ์ •ํ•˜๊ธฐ

๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹ฑํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ์‹ฌํ•ด์š”. ๋‹ค์Œ ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹ฑ ๋Œ€์ƒ์œผ๋กœ ๊ณ ๋ คํ•ด๋ณด์„ธ์š”:

  1. ์ฝ๊ธฐ๊ฐ€ ๋งŽ์€ ๋ฐ์ดํ„ฐ: ์กฐํšŒ๋Š” ์ž์ฃผ ํ•˜์ง€๋งŒ ์ˆ˜์ •์€ ์ ์€ ๋ฐ์ดํ„ฐ
  2. ๊ณ„์‚ฐ ๋น„์šฉ์ด ํฐ ๋ฐ์ดํ„ฐ: DB ์กฐ์ธ์ด ๋งŽ๊ฑฐ๋‚˜ ๊ณ„์‚ฐ์ด ๋ณต์žกํ•œ ๊ฒฐ๊ณผ
  3. ๋ฐ˜๋ณต ์ ‘๊ทผ์ด ๋งŽ์€ ๋ฐ์ดํ„ฐ: ์‚ฌ์šฉ์ž๊ฐ€ ์ž์ฃผ ์ ‘๊ทผํ•˜๋Š” ์ธ๊ธฐ ์ฝ˜ํ…์ธ 
  4. ๋ณ€๊ฒฝ์ด ์ ์€ ๋ฐ์ดํ„ฐ: ์ƒํ’ˆ ์ •๋ณด, ์นดํ…Œ๊ณ ๋ฆฌ ๋“ฑ ์ž์ฃผ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ์ •๋ณด

์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ๋Š” ์ธ๊ธฐ ์žˆ๋Š” ์žฌ๋Šฅ ๋ชฉ๋ก์ด๋‚˜ ์ž์ฃผ ์กฐํšŒ๋˜๋Š” ํ”„๋กœํ•„ ์ •๋ณด ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์ข‹์€ ์บ์‹ฑ ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๋Š” ์ฝ๊ธฐ๊ฐ€ ๋งŽ๊ณ  ๋ณ€๊ฒฝ์€ ์ ์œผ๋‹ˆ๊นŒ์š”! ๐Ÿ‘

4.2 ์บ์‹œ ์ „๋žต ํŒจํ„ด

์บ์‹œ๋ฅผ ์ ์šฉํ•  ๋•Œ๋Š” ๋ช‡ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ด ์žˆ์–ด์š”. ์ƒํ™ฉ์— ๋งž๊ฒŒ ์„ ํƒํ•ด๋ณด์„ธ์š”!

1. Cache-Aside (Lazy Loading) ํŒจํ„ด

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์œผ๋กœ, ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•  ๋•Œ:

  1. ๋จผ์ € ์บ์‹œ๋ฅผ ํ™•์ธ
  2. ์บ์‹œ์— ์—†์œผ๋ฉด(Cache Miss) DB์—์„œ ์กฐํšŒ
  3. DB์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์บ์‹œ์— ์ €์žฅ
  4. ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜

์žฅ์ : ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์บ์‹ฑ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ 

๋‹จ์ : ์ฒซ ์š”์ฒญ์€ ๋А๋ฆผ(Cache Miss)

2. Write-Through ํŒจํ„ด

๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ๋•Œ:

  1. DB์— ๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ
  2. ๋™์‹œ์— ์บ์‹œ๋„ ์—…๋ฐ์ดํŠธ

์žฅ์ : ์บ์‹œ์™€ DB๊ฐ€ ํ•ญ์ƒ ๋™๊ธฐํ™”๋จ

๋‹จ์ : ์“ฐ๊ธฐ ์ž‘์—…์ด ์•ฝ๊ฐ„ ๋А๋ ค์งˆ ์ˆ˜ ์žˆ์Œ

3. Write-Behind (Write-Back) ํŒจํ„ด

๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ๋•Œ:

  1. ์บ์‹œ์—๋งŒ ๋จผ์ € ์“ฐ๊ธฐ
  2. ๋‚˜์ค‘์— ์ผ๊ด„์ ์œผ๋กœ DB์— ๋ฐ˜์˜

์žฅ์ : ์“ฐ๊ธฐ ์„ฑ๋Šฅ์ด ๋งค์šฐ ๋น ๋ฆ„

๋‹จ์ : ์บ์‹œ ์žฅ์•  ์‹œ ๋ฐ์ดํ„ฐ ์œ ์‹ค ์œ„ํ—˜

4. Refresh-Ahead ํŒจํ„ด

๋งŒ๋ฃŒ ์‹œ๊ฐ„์ด ๋‹ค๊ฐ€์˜ค๋Š” ์บ์‹œ ํ•ญ๋ชฉ์„:

  1. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฏธ๋ฆฌ ๊ฐฑ์‹ 
  2. ์‚ฌ์šฉ์ž ์š”์ฒญ ์ „์— ์ค€๋น„

์žฅ์ : ์บ์‹œ ๋ฏธ์Šค๊ฐ€ ๊ฑฐ์˜ ์—†์Œ

๋‹จ์ : ๊ตฌํ˜„์ด ๋ณต์žกํ•˜๊ณ  ๋ถˆํ•„์š”ํ•œ ๊ฐฑ์‹  ๊ฐ€๋Šฅ์„ฑ

Cache-Aside ํŒจํ„ด ๋™์ž‘ ์›๋ฆฌ ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ Redis ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค 1. ๋ฐ์ดํ„ฐ ์š”์ฒญ 2. ์บ์‹œ ํ™•์ธ 3. ์บ์‹œ ๋ฏธ์Šค 4. DB ์กฐํšŒ 5. ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ 6. ์บ์‹œ ์—…๋ฐ์ดํŠธ 7. ๋ฐ์ดํ„ฐ ์‘๋‹ต 8. ๋‘ ๋ฒˆ์งธ ์š”์ฒญ 9. ์บ์‹œ ํ™•์ธ 10. ์บ์‹œ ํžˆํŠธ! 11. ๋น ๋ฅธ ์‘๋‹ต ์ฒซ ์š”์ฒญ: ์บ์‹œ ๋ฏธ์Šค โ†’ DB ์กฐํšŒ โ†’ ์บ์‹œ ์ €์žฅ ์ดํ›„ ์š”์ฒญ: ์บ์‹œ ํžˆํŠธ โ†’ ๋น ๋ฅธ ์‘๋‹ต

4.3 ์บ์‹œ ๋งŒ๋ฃŒ ์ „๋žต

์บ์‹œ ๋ฐ์ดํ„ฐ๋Š” ์˜์›ํžˆ ๋ณด๊ด€ํ•  ์ˆ˜ ์—†์–ด์š”. ์ ์ ˆํ•œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„(TTL, Time-To-Live)์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”!

๋ฐ์ดํ„ฐ ํŠน์„ฑ๋ณ„ ๊ถŒ์žฅ TTL:

  1. ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๋ฐ์ดํ„ฐ: ์งง์€ TTL (๋ช‡ ์ดˆ~๋ช‡ ๋ถ„)
  2. ์ค€-์ •์  ๋ฐ์ดํ„ฐ: ์ค‘๊ฐ„ TTL (๋ช‡ ์‹œ๊ฐ„~ํ•˜๋ฃจ)
  3. ๊ฑฐ์˜ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ: ๊ธด 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๋ฅผ ํ˜ธ์ถœํ•ด๋ณด๋ฉด:

  1. ์ฒซ ๋ฒˆ์งธ ์š”์ฒญ: DB์—์„œ ์กฐํšŒํ•˜๋ฏ€๋กœ ์•ฝ 1์ดˆ ์ •๋„ ์†Œ์š” (์บ์‹œ ๋ฏธ์Šค)
  2. ๋‘ ๋ฒˆ์งธ ์š”์ฒญ: ์บ์‹œ์—์„œ ๋ฐ”๋กœ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ ๋ช‡ ๋ฐ€๋ฆฌ์ดˆ ๋‚ด๋กœ ์‘๋‹ต (์บ์‹œ ํžˆํŠธ)

์ด๋ ‡๊ฒŒ Redis ์บ์‹œ๋ฅผ ์ ์šฉํ•˜๋ฉด ์‘๋‹ต ์‹œ๊ฐ„์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”! ํŠนํžˆ DB ์กฐํšŒ๊ฐ€ ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ๋ถ€ํ•˜๊ฐ€ ํฐ ๊ฒฝ์šฐ์— ํšจ๊ณผ๊ฐ€ ๋” ํฌ๋‹ต๋‹ˆ๋‹ค. ๐Ÿ‘

๐Ÿ’ก ์‹ค๋ฌด ํŒ: ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์œ„ ์ฝ”๋“œ์— ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ๋กœ๊น…, ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋“ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ๋˜ํ•œ ์บ์‹œ ํ‚ค ์ƒ์„ฑ ๋กœ์ง์„ ๋ณ„๋„ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค๋กœ ๋ถ„๋ฆฌํ•˜๋ฉด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋” ์‰ฌ์›Œ์ ธ์š”!

6. ์„ฑ๋Šฅ ์ธก์ • ๋ฐ ์ตœ์ ํ™” ํŒ ๐Ÿ“Š

Redis ์บ์‹œ๋ฅผ ์ ์šฉํ–ˆ๋‹ค๋ฉด ์–ผ๋งˆ๋‚˜ ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋๋Š”์ง€ ์ธก์ •ํ•˜๊ณ , ๋” ์ตœ์ ํ™”ํ•  ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ณผ๊นŒ์š”?

6.1 ์„ฑ๋Šฅ ์ธก์ •ํ•˜๊ธฐ

์บ์‹œ ์ ์šฉ ์ „ํ›„์˜ ์„ฑ๋Šฅ์„ ๋น„๊ตํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์–ด์š”:

  1. ์‘๋‹ต ์‹œ๊ฐ„ ์ธก์ •: ์œ„ ์˜ˆ์ œ์ฒ˜๋Ÿผ API ํ˜ธ์ถœ ์‹œ๊ฐ„์„ ์ธก์ •
  2. ์ฒ˜๋ฆฌ๋Ÿ‰(Throughput) ์ธก์ •: ์ดˆ๋‹น ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ์š”์ฒญ ์ˆ˜ ๋น„๊ต
  3. DB ๋ถ€ํ•˜ ๊ฐ์†Œ ์ธก์ •: DB ์„œ๋ฒ„์˜ CPU, ๋ฉ”๋ชจ๋ฆฌ, I/O ์‚ฌ์šฉ๋Ÿ‰ ๋ณ€ํ™” ๊ด€์ฐฐ
  4. ์บ์‹œ ํžˆํŠธ์œจ ๋ชจ๋‹ˆํ„ฐ๋ง: ์ „์ฒด ์š”์ฒญ ์ค‘ ์บ์‹œ์—์„œ ์ฒ˜๋ฆฌ๋œ ๋น„์œจ

์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋กœ๋Š” 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์„ ์žฌ๊ฒ€ํ† ํ•ด๋ณผ ํ•„์š”๊ฐ€ ์žˆ์–ด์š”!

Redis ์บ์‹ฑ ์ ์šฉ ์ „ํ›„ ์„ฑ๋Šฅ ๋น„๊ต ์š”์ฒญ ์œ ํ˜• ์‘๋‹ต ์‹œ๊ฐ„ (ms) 0 200 400 600 800 1000 ๋‹จ์ผ ์กฐํšŒ ๋ชฉ๋ก ์กฐํšŒ ํ†ต๊ณ„ ์กฐํšŒ ์บ์‹œ ์ ์šฉ ์ „ ์บ์‹œ ์ ์šฉ ํ›„ 850ms 920ms 1000ms 20ms 30ms 40ms

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 ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์€ ํ•ญ์ƒ ์ค‘์š”ํ•œ ์ด์Šˆ์˜ˆ์š”:

  1. ์บ์‹œ ๋ฌดํšจํ™” ์ „๋žต: ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ๊ด€๋ จ ์บ์‹œ๋ฅผ ์ ์ ˆํžˆ ์‚ญ์ œ/๊ฐฑ์‹ 
  2. TTL ๊ด€๋ฆฌ: ๋ฐ์ดํ„ฐ ํŠน์„ฑ์— ๋งž๋Š” ์ ์ ˆํ•œ ๋งŒ๋ฃŒ ์‹œ๊ฐ„ ์„ค์ •
  3. ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์บ์‹œ ๊ฐฑ์‹ : DB ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ์บ์‹œ ์ž๋™ ๊ฐฑ์‹ 

๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ๊ณผ ์„ฑ๋Šฅ์€ ์ข…์ข… ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ๊ด€๊ณ„์— ์žˆ์–ด์š”. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ๊ท ํ˜•์ ์„ ์ฐพ๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”!

7.2 ์žฅ์•  ๋Œ€์‘ ์ „๋žต

Redis ์„œ๋ฒ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ๋Œ€์‘ ๋ฐฉ๋ฒ•์„ ๋ฏธ๋ฆฌ ์ค€๋น„ํ•ด๋‘์„ธ์š”:

  1. Circuit Breaker ํŒจํ„ด: Redis ์—ฐ๊ฒฐ ์‹คํŒจ ์‹œ DB๋กœ ํด๋ฐฑ
  2. Redis Sentinel: ๊ณ ๊ฐ€์šฉ์„ฑ์„ ์œ„ํ•œ ์ž๋™ ์žฅ์•  ์กฐ์น˜
  3. Redis Cluster: ๋ฐ์ดํ„ฐ ๋ถ„์‚ฐ ๋ฐ ๋ณต์ œ๋กœ ์•ˆ์ •์„ฑ ํ™•๋ณด
  4. ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์•Œ๋ฆผ: 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๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ธ์ฆ ์—†์ด ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ๋ณด์•ˆ์— ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”:

  1. ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ •: Redis ์„œ๋ฒ„์— ์ธ์ฆ ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ •
  2. ๋„คํŠธ์›Œํฌ ๊ฒฉ๋ฆฌ: Redis ์„œ๋ฒ„๋ฅผ ์™ธ๋ถ€์— ๋…ธ์ถœํ•˜์ง€ ์•Š๊ธฐ
  3. SSL/TLS ์ ์šฉ: ๋ฐ์ดํ„ฐ ์ „์†ก ์•”ํ˜ธํ™” (Redis 6.0 ์ด์ƒ)
  4. ๋ฏผ๊ฐ ์ •๋ณด ์ œ์™ธ: ๊ฐœ์ธ์ •๋ณด ๋“ฑ ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ๋Š” ์บ์‹ฑํ•˜์ง€ ์•Š๊ธฐ

Redis๋Š” ์„ฑ๋Šฅ์— ์ตœ์ ํ™”๋œ ์†”๋ฃจ์…˜์ด๋ผ ๊ธฐ๋ณธ ์„ค์ •์€ ๋ณด์•ˆ๋ณด๋‹ค ์„ฑ๋Šฅ์„ ์šฐ์„ ์‹œํ•ด์š”. ์šด์˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ณด์•ˆ ์„ค์ •์„ ๊ฐ•ํ™”ํ•ด์•ผ ํ•ด์š”!

7.4 ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์šด์˜

Redis ์บ์‹œ์˜ ๊ฑด๊ฐ• ์ƒํƒœ๋ฅผ ์ง€์†์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์„ธ์š”:

  1. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰: maxmemory ์ œํ•œ์— ๊ทผ์ ‘ํ•˜๋Š”์ง€ ํ™•์ธ
  2. ๋ช…๋ น์–ด ์ฒ˜๋ฆฌ๋Ÿ‰: ์ดˆ๋‹น ์ฒ˜๋ฆฌ๋˜๋Š” ๋ช…๋ น์–ด ์ˆ˜ ๋ชจ๋‹ˆํ„ฐ๋ง
  3. ์‘๋‹ต ์‹œ๊ฐ„: Redis ๋ช…๋ น์–ด ์ง€์—ฐ ์‹œ๊ฐ„ ์ถ”์ 
  4. ์บ์‹œ ํžˆํŠธ์œจ: ์บ์‹œ ํšจ์œจ์„ฑ ์ธก์ •
  5. ์—ฐ๊ฒฐ ์ˆ˜: ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์ƒํƒœ ํ™•์ธ

Prometheus + Grafana, Redis Exporter, Spring Boot Actuator ๋“ฑ์„ ํ™œ์šฉํ•˜๋ฉด ํšจ๊ณผ์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ด์š”!

๐Ÿ’ก ์šด์˜ ํŒ: Redis INFO ๋ช…๋ น์–ด๋กœ ๊ฐ„๋‹จํžˆ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ฃผ๊ธฐ์ ์œผ๋กœ ๋ชจ๋‹ˆํ„ฐ๋ง ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•˜์„ธ์š”!

8. ๋งˆ๋ฌด๋ฆฌ ๋ฐ ๋‹ค์Œ ๋‹จ๊ณ„ ๐ŸŽฏ

์ง€๊ธˆ๊นŒ์ง€ Spring Data Redis๋ฅผ ํ™œ์šฉํ•œ ์บ์‹œ ์„œ๋ฒ„ ์—ฐ๋™์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด์š”! ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ„ฐ๋ณด ์—”์ง„์„ ๋‹ฌ ์ค€๋น„๊ฐ€ ๋๋„ค์š”! ๐Ÿ˜Ž

8.1 ์š”์•ฝ

์ด๋ฒˆ ๊ธ€์—์„œ ๋‹ค๋ฃฌ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณผ๊ฒŒ์š”:

  1. Redis์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ ์บ์‹ฑ์˜ ์ค‘์š”์„ฑ
  2. Spring Data Redis ์„ค์ • ๋ฐฉ๋ฒ•
  3. ํšจ๊ณผ์ ์ธ ์บ์‹œ ์ „๋žต ์ˆ˜๋ฆฝ ๋ฐฉ๋ฒ•
  4. ์‹ค์ „ ์˜ˆ์ œ: ์ƒํ’ˆ ์ •๋ณด ์บ์‹ฑ ๊ตฌํ˜„
  5. ์„ฑ๋Šฅ ์ตœ์ ํ™” ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐฉ๋ฒ•
  6. ์šด์˜ ํ™˜๊ฒฝ์—์„œ์˜ ์ฃผ์˜์‚ฌํ•ญ

Redis ์บ์‹œ๋ฅผ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์š”. ํŠนํžˆ DB ๋ถ€ํ•˜๊ฐ€ ํฐ ์„œ๋น„์Šค๋‚˜ ๋ฐ˜๋ณต์ ์ธ ์กฐํšŒ๊ฐ€ ๋งŽ์€ ์„œ๋น„์Šค์—์„œ ํšจ๊ณผ๊ฐ€ ๋‘๋“œ๋Ÿฌ์ ธ์š”!

8.2 ๋‹ค์Œ ๋‹จ๊ณ„

Redis ์บ์‹ฑ์— ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ ์ฃผ์ œ๋“ค์„ ์‚ดํŽด๋ณด์„ธ์š”:

  1. Redis ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ: Pub/Sub, Stream, Lua ์Šคํฌ๋ฆฝํŠธ ๋“ฑ
  2. ๋ถ„์‚ฐ ์บ์‹ฑ: Redis Cluster๋ฅผ ํ™œ์šฉํ•œ ๋Œ€๊ทœ๋ชจ ์บ์‹ฑ
  3. ์บ์‹œ ์ผ๊ด€์„ฑ ํŒจํ„ด: ๋” ์ •๊ตํ•œ ์บ์‹œ ๋ฌดํšจํ™” ์ „๋žต
  4. ๋กœ์ปฌ ์บ์‹œ + Redis: ๋‹ค์ค‘ ๋ ˆ๋ฒจ ์บ์‹ฑ ๊ตฌ์กฐ
  5. Spring Cache์™€ Redis: ๋” ์„ ์–ธ์ ์ธ ์บ์‹ฑ ๋ฐฉ์‹

์บ์‹ฑ์€ ๋‹จ์ˆœํžˆ ๊ธฐ์ˆ ์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ๋ฐ์ดํ„ฐ ํŠน์„ฑ์„ ์ดํ•ดํ•˜๊ณ  ์ ์ ˆํ•œ ์ „๋žต์„ ์ˆ˜๋ฆฝํ•˜๋Š” ๊ฒƒ์ด ๋” ์ค‘์š”ํ•ด์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ์„œ๋น„์Šค์— ๋งž๋Š” ์ตœ์ ์˜ ์บ์‹ฑ ์ „๋žต์„ ์ฐพ์•„๋ณด์„ธ์š”!

์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์„ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ํ”Œ๋žซํผ๋„ ๋” ๋น ๋ฅด๊ณ  ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ํ–ฅ์ƒ์€ ๋ฌผ๋ก  ์„œ๋ฒ„ ๋น„์šฉ ์ ˆ๊ฐ์—๋„ ๋„์›€์ด ๋  ๊ฑฐ์˜ˆ์š”! ๐Ÿš€

Redis ์บ์‹ฑ์œผ๋กœ ์—ฌ๋Ÿฌ๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋กœ์ผ“ ์—”์ง„์„ ๋‹ฌ์•„๋ณด์„ธ์š”! ๐Ÿš€

์งˆ๋ฌธ์ด๋‚˜ ์˜๊ฒฌ์ด ์žˆ์œผ์‹œ๋ฉด ์–ธ์ œ๋“ ์ง€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์„ธ์š”! ํ•จ๊ป˜ ์„ฑ์žฅํ•ด์š”! ๐Ÿ’ช

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.