๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Redis

[Redis] Redis CacheAside ์ „๋žต ๊ฐ„๋‹จํžˆ ์ ์šฉํ•ด๋ณด๊ธฐ @Cachable ์–ด๋…ธํ…Œ์ด์…˜

by ์šฐ์ฃผ๋ฌผ๊ณ ๊ธฐ 2025. 11. 28.
๋ฐ˜์‘ํ˜•

(๊ฒŒ์‹œํŒ ํ† ์ดํ”„๋กœ์ ํŠธ)

 

์ผ๋‹จ ํ˜„์žฌ ๋‚ด service์ฝ”๋“œ๋Š”

๋‹จ์ˆœํžˆ DB์ฐ”๋Ÿฌ์„œ ๊ฐ–๊ณ  ์˜ค๋Š” ์ฝ”๋“œ์ž„.

@Service
public class BoardService {

    private BoardRepository boardRepository;

    public BoardService(BoardRepository boardRepository) {
        this.boardRepository = boardRepository;
    }

    public List<Board> getBoards(int page, int size) {
        Pageable pageable = PageRequest.of(page -1, size);
        Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable);
        return pageOfBoards.getContent();
    }
}

 

 

 

์ด์ œ ํ”„๋กœ์ ํŠธ์— configํด๋” ๋งŒ๋“ค๊ณ , ์„ธํŒ…ํ•ด์ค€๋‹ค์Œ์—

Service์ชฝ ์ฝ”๋“œ ๊ฐ„๋‹จํžˆ ์ˆ˜์ •ํ•ด์„œ

 

Redis๋จผ์ € ์ฐ”๋Ÿฌ๋ณด๊ณ , CacheMiss๋ฉด DB ์ฐŒ๋ฅด๊ณ  DB์— ์ €์žฅ๊นŒ์ง€ ํ•˜๋Š” ๋กœ์ง์œผ๋กœ ํ•ด๋ณด๊ฒ ์Œ.

 

ํŒŒ์ผ๊ตฌ์กฐ๋Š” ์ด๋ ‡๊ฒŒ 

configํด๋” ๋งŒ๋“ค๊ณ , ๊ทธ ํ•˜์œ„์— redis ์„ค์ •ํ•˜๋Š” ํŒŒ์ผ ๋‘๊ฐœ ๋งŒ๋“ค๊ฒ ์Œ.

 

 

RedisCacheConfig ํŒŒ์ผ

@Configuration
@EnableCaching // Spring Boot์˜ ์บ์‹ฑ ์„ค์ •์„ ํ™œ์„ฑํ™”
public class RedisCacheConfig {
    @Bean
    public CacheManager boardCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
                .defaultCacheConfig()
                // Redis์— Key๋ฅผ ์ €์žฅํ•  ๋•Œ String์œผ๋กœ ์ง๋ ฌํ™”(๋ณ€ํ™˜)ํ•ด์„œ ์ €์žฅ
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new StringRedisSerializer()))
                // Redis์— Value๋ฅผ ์ €์žฅํ•  ๋•Œ Json์œผ๋กœ ์ง๋ ฌํ™”(๋ณ€ํ™˜)ํ•ด์„œ ์ €์žฅ
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(
                                new Jackson2JsonRedisSerializer<Object>(Object.class)
                        )
                )
                // ๋ฐ์ดํ„ฐ์˜ ๋งŒ๋ฃŒ๊ธฐ๊ฐ„(TTL) ์„ค์ • - 1๋ถ„๋งˆ๋‹ค ๋ฐ์ดํ„ฐ ๊ฐฑ์‹ ๋์œผ๋ฉด ์ข‹๊ฒ ๋‹ค!
                .entryTtl(Duration.ofMinutes(1L));

        return RedisCacheManager
                .RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory)
                .cacheDefaults(redisCacheConfiguration)
                .build();
    }
}

 

 

 

RedisConfigํŒŒ์ผ

@Configuration
public class RedisConfig {

    @Value("${spring.data.redis.host}")
    private String host;

    @Value("${spring.data.redis.port}")
    private int port;


    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        //Lettuce ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด์šฉํ•ด์„œ Redis ์—ฐ๊ฒฐ ๊ด€๋ฆฌํ•˜๋Š” ๊ฐ์ฒด ์ƒ์„ฑ
        // Redis ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ •๋ณด(host, port)๋ฅผ ์„ค์ •
        return  new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port));
    }

}

 

 

Redis ์„ค์ •์€ ํ•ด๋†จ๊ณ ,

์ด์ œ Service์ชฝ ์ฝ”๋“œ ์ˆ˜์ •

@Service
public class BoardService {

    private BoardRepository boardRepository;

    public BoardService(BoardRepository boardRepository) {
        this.boardRepository = boardRepository;
    }

    // @Cacheable : CacheAside ์ „๋žต ์“ฐ๊ฒ ๋‹ค.
    // CacheAside ์ „๋žต : ์ผ๋‹จ redis ์บ์‹œ ๋จผ์ € ๋’ค์ง€๊ณ , ์—†์œผ๋ฉด ๋‚ด๋ถ€ ๋กœ์ง ์ง„ํ–‰, return ๊ฐ’์„ redis์— ์ €์žฅ.
    // ํ‚ค๊ฐ’ - boards:pages:2:size:10 - boards ์—์„œ page๊ฐ€ 2์ด๊ณ , size๊ฐ€ 10๊ฐœ์ธ ๋ฐ์ดํ„ฐ
    @Cacheable(cacheNames = "getBoards", key = "'boards:pages:' + #page + ':size' + #size", cacheManager = "boardCacheManager")
    public List<Board> getBoards(int page, int size) {
        // Cache Miss ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ง„ํ–‰๋˜๋Š” ๋กœ์ง
        // redis์— ์—†์œผ๋‹ˆ๊นŒ boardRepository(DB) ๋’ค์ง€๋Š”๊ฑฐ์ž„
        Pageable pageable = PageRequest.of(page -1, size);
        Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable);
        return pageOfBoards.getContent();
    }
}

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”์ฃผ๊ฒ ์Œ.

 

@Cachable์–ด๋…ธํ…Œ์ด์…˜:

- cacheNames : ์บ์‹œ ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋”” ์ €์žฅ๋ ์ง€ ์ง€์ •.

์ฒจ์— ์–ด๋…ธํ…Œ์ด์…˜ ๋ดค์„ ๋•Œ ๋ ˆ๋””์Šค ์ €์žฅ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ธด์ง€ ๋ชฐ๋ผ์„œ

์ด ์†์„ฑ์ด ์™œ ํ•„์š”ํ•œ๊ฐ€ ํ–ˆ์Œ.

 

์–ด์ฐจํ”ผ key-value๋กœ ์ €์žฅ๋˜๋Š” ๋ ˆ๋””์Šค์—์„œ key๋Š” ์•ˆ๊ฒน์ณ์•ผํ•˜๊ณ .. ๊ตณ์ด ์™œ ํ•„์š”ํ•œ๊ฐ€ ํ–ˆ๋Š”๋ฐ

์•ฝ๊ฐ„ RDBMS์—์„œ table๊ฐ™์€ ์—ญํ• ๋กœ ์ดํ•ดํ•˜๋ฉด ์‰ฌ์šธ๊ฑฐ๊ฐ™์Œ.

 

์ง€๊ธˆ ๋‚ด๊ฐ€ ์ง  ์ฝ”๋“œ ์ฒ˜๋Ÿผ ํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด 

๋‚ด๋ถ€์—

getBoards {
    boards:pages:2:size:10 ->  [ Board ๋ฐ์ดํ„ฐ ... ]
    boards:pages:3:size:10 ->  [ Board ๋ฐ์ดํ„ฐ ... ]
}

์ด๋Ÿฐ ๋А๋‚Œ์œผ๋กœ ์ €์žฅ๋œ๋‹ค๊ณ  ๋ณด๋ฉด๋จ.

 

์–ด์ฐจํ”ผ key๊ฐ’์€ uniqueํ•ด์•ผํ•˜๋‹ˆ๊นŒ ๊ฒน์น ์ผ์€ ์—†๊ฒ ์ง€๋งŒ,

์บ์‹œ ๊ตฌ์กฐ ๊ด€๋ฆฌ๋‚˜ ์ œ์–ด ํŽธ๋ฆฌ์„ฑ๋•Œ๋ฌธ์— ๊ผญ ํ•„์š”ํ•จ.

 

์˜ˆ๋ฅผ ๋“ค์–ด ๋‚ด๊ฐ€ boards ์บ์‹œ๋งŒ ์ง€์šฐ๊ณ ์‹ถ๋‹ค๋ฉด?

๊ตฌ์กฐ์ ์œผ๋กœ ๋ถ„๋ฆฌ๊ฐ€ ์•ˆ๋˜์–ด์žˆ์œผ๋ฉด ๊นŒ๋‹ค๋กœ์›Œ์ง.

์•„๋ฌดํŠผ ์ด๋Ÿฐ ์ด์œ ๋กœ ์ €์žฅ์†Œ ์ด๋ฆ„ ๋ถ™์ด๊ธฐ๋Š” ํ•„์ˆ˜์ .

 

- key : key๊ฐ’ ์ด๋ฆ„ ์ง€์ •

๋‚ด๊ฐ€ ์“ด ์ฝ”๋“œ์ฒ˜๋Ÿผ ํ•˜๊ฒŒ ๋˜๋ฉด ํ‚ค๊ฐ’์ด

boards:pages:2:size:10 

์ด๋Ÿฐ์‹์œผ๋กœ ์ €์žฅ๋จ.

์˜ˆ์ „์— ํฌ์ŠคํŒ…ํ–ˆ๋˜, ๊ณ„์ธต์  ๊ตฌ์กฐ๋ฅผ ์ž˜ ๋”ฐ๋ฅด๊ฒŒ ์ง€์Œ

 

 

- cacheManager : ์–ด๋–ค cacheManagerํ•œํ…Œ ๋งก๊ธธ๊ฑด์ง€ ์ง€์ •

์ง€์ • ์•ˆํ•ด์ฃผ๋ฉด defaultCacheManager์“ด๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์œ„์—์„œ config ๋””๋ ‰ํ† ๋ฆฌ ํ•˜์œ„์—

boardCacheManager ๋งŒ๋“ค์–ด๋‘”๊ฒŒ ์žˆ๋Š”๋ฐ, ๊ทธ๊ฑธ ๊ฐ–๋‹ค ์“ฐ๋Š”๊ฑฐ์ž„.

 

 


์ด์ œ ์‹คํ–‰ํ•˜๊ณ  api ํ˜ธ์ถœํ•ด๋ณด๋ฉด

 

๋กœ๊ทธ์— ์ด๋ ‡๊ฒŒ ์ฐํž˜.

 

์ฒ˜์Œ์— ์บ์‹œ ์กฐํšŒํ•ด ๋ดค๋Š”๋ฐ ์—†์–ด์„œ

No cache entry๋ผ๊ณ  ๋œจ๊ณ ,

DB๋ฅผ ์กฐํšŒํ•จ.

๊ทธ๋ฆฌ๊ณ  return๊ฐ’์„ redis์— ์ €์žฅํ•˜๋Š” ๋กœ๊ทธ.

 

 

redis-cli ์ผœ์„œ ํ™•์ธํ•ด๋ณด๋ฉด

์ž˜ ๋“ค์–ด๊ฐ€ ์žˆ์Œ!!!

 

ํ•˜๋‚˜ํ•˜๋‚˜ ํ™•์ธํ•ด๋ณด๋ฉด

๋‚ด๊ฐ€ ์ €๋ฒˆ์— ๋งŒ๊ฐœ์ธ๊ฐ€ ์‹ญ๋งŒ๊ฐœ์ธ๊ฐ€ ๋žœ๋ค ์ƒ์„ฑํ•ด๋†“์€ ๋ฐ์ดํ„ฐ์ค‘์—์„œ ๋ถˆ๋Ÿฌ์™€์ง.

 

1๋ถ„์ด ์ง€๋‚˜๊ธฐ ์ „์— ๋‹ค์‹œ apiํ˜ธ์ถœํ•ด๋ณด๋ฉด

์•„๊นŒ๋ž‘ ๋‹ฌ๋ฆฌ ๋ฐ”๋กœ ์กฐํšŒ.

 

 

 

 

 

ttlํ™•์ธํ•ด๋ณด๋ฉด

5์ดˆ ๋‚จ๊ธฐ๊ณ  ์บก์ณ

ใ…‹ใ…‹ใ…‹

 

 

 

~~~์‹œ๊ฐ„์ด ํ๋ฅด๊ณ  1๋ถ„์ด ์ง€๋‚จ~~~

 

๋‹ค์‹œ apiํ˜ธ์ถœํ•ด๋ณด๋ฉด

๋‹ค์‹œ ์บ์‹œ ์—†๋‹ค๋ฉด์„œ DB์กฐํšŒํ•˜๊ณ  ์บ์‹œ์— ์ €์žฅํ•จ.

 

 

๋ฐ˜์‘ํ˜•