Spring

[Spring] Spring Cache์„ ์ ์šฉํ•œ ์กฐํšŒ ์„ฑ๋Šฅ ๊ฐœ์„  (with. Redis)

DAHLIA CHOI 2024. 3. 19. 00:48

 
 
 
ํ”„๋กœ์ ํŠธ๋ฅผ ๋ฆฌํŒฉํ„ฐ๋ง ํ•˜๋ฉด์„œ ์กฐํšŒํ•˜๋Š” ๋ถ€๋ถ„์— ์บ์‹ฑ์„ ์ ์šฉํ•˜๋ ค๊ณ  ํ•œ๋‹ค! 
 
์™œ ์บ์‹ฑ์„ ์ ์šฉํ•˜๋ ค๊ณ  ํ•˜๋ƒ? ! 
ํ•ด๋‹น ์„œ๋น„์Šค๋Š” ํ™ˆ ํ™”๋ฉด์—์„œ ์ง€๋„์œ„์— ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€ ์œ„์น˜๋ฅผ ํ‘œํ˜„ํ•ด ์ค€๋‹ค. 
์‹ค์งˆ์ ์œผ๋กœ ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก, ์‚ญ์ œ๋ณด๋‹ค ์กฐํšŒ์ˆ˜๊ฐ€ ํ›จ์”ฌ ๋งŽ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ณ , ๊ฐ€์žฅ ๋งŽ์ด ๋…ธ์ถœ๋˜๋Š” ํ™ˆ ํ™”๋ฉด์—์„œ ๊ณ„์† ์œ„์น˜ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜จ๋‹ค๋ฉด ์„ฑ๋Šฅ์ ์œผ๋กœ ์ข‹์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.! 
 
 
์Šคํ”„๋ง ์บ์‹œ๊ฐ€ ๋ฌด์—‡์ธ์ง€๋Š” ์•„๋ž˜ ๊ธ€์— ์ •๋ฆฌํ•ด๋†“์•˜๋‹ค๐Ÿ˜Š

[Spring] Spring Cache(์Šคํ”„๋ง ์บ์‹œ)๋ž€?

๐Ÿ”Ž Spring Cache๋ž€? ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋งค๋ฒˆ ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ์ƒ์„ฑํ•˜์—ฌ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” ์ƒ์„ฑ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด ๋†“๊ณ  ๋˜‘๊ฐ™์€ ์š”์ฒญ์ด ์™”์„ ๋•Œ ๋กœ์ง์„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•ด ์ฃผ์–ด ๋น ๋ฅธ

dahliachoi.tistory.com

 
 

๐Ÿ”Ž ์บ์‹ฑ ์ „๋žต์— ๋Œ€ํ•ด์„œ

๋กœ์ปฌ ์บ์‹ฑ

์„œ๋ฒ„ ๋‚ด๋ถ€ ์ €์žฅ์†Œ์— ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 
์†๋„๋Š” ๋น ๋ฅด์ง€๋งŒ ์„œ๋ฒ„ ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ณต์œ ๊ฐ€ ์•ˆ๋œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค. 

 

๊ธ€๋กœ๋ฒŒ ์บ์‹ฑ

์„œ๋ฒ„ ๋‚ด๋ถ€ ์ €์žฅ์†Œ๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ ์บ์‹œ ์„œ๋ฒ„๋ฅผ ๋‘์–ด ๊ฐ ์„œ๋ฒ„์—์„œ ์บ์‹œ ์„œ๋ฒ„๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 
์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์œผ๋ ค๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค ์บ์‹œ ์„œ๋ฒ„๋กœ์˜ ๋„คํŠธ์›Œํฌ ํŠธ๋ž˜ํ”ฝ์ด ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋กœ์ปฌ ์บ์‹ฑ๋ณด๋‹ค ์†๋„๋Š” ๋Š๋ฆฌ๋‹ค. 
ํ•˜์ง€๋งŒ, ์„œ๋ฒ„ ๊ฐ„ ์บ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋กœ์ปฌ ์บ์‹ฑ์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 
๋‚˜๋Š” ํ˜ผ์ž ๋ฆฌํŒฉํ† ๋ง ์ค‘์ด๋ผ์„œ ๊ตณ์ด ๊ธ€๋กœ๋ฒŒ ์บ์‹ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ, ์ถ”ํ›„ ํ™•์žฅ์„ฑ์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ ๊ธ€๋กœ๋ฒŒ ์บ์‹ฑ์„ ์ ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ Redis๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ–ˆ๋‹ค.!
 
 

โš™๏ธ ์ฝ”๋“œ

 

build.gradle

    implementation 'org.springframework.boot:spring-boot-starter-data-redis'
    implementation 'org.springframework.boot:spring-boot-starter-cache'

  
spring cache์™€ redis๋ฅผ ์˜์กด์„ฑ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
 
 

application

@EnableCaching
@EnableJpaAuditing
@SpringBootApplication
public class FootprintApplication {
    public static void main(String[] args) {
        SpringApplication.run(FootprintApplication.class, args);
    }

}

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํด๋ž˜์Šค ์œ„์— @EnableCaching์„ ์ถ”๊ฐ€ํ•œ๋‹ค. 
์บ์‹ฑ์„ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.
 
 

RedisConfig

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class RedisConfig {

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

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

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory(host, port);
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate() {
        // redisTemplate๋ฅผ ๋ฐ›์•„์™€์„œ set, get, delete๋ฅผ ์‚ฌ์šฉ
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        // setKeySerializer, setValueSerializer ์„ค์ •
        // redis-cli์„ ํ†ตํ•ด ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ ์‹œ ์•Œ์•„๋ณผ ์ˆ˜ ์—†๋Š” ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory());

        return redisTemplate;
    }

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
        redisCacheConfigurationMap.put("all_place", redisCacheConfiguration.entryTtl(Duration.ofHours(1)));

        return RedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(connectionFactory)
                .cacheDefaults(redisCacheConfiguration)
                .withInitialCacheConfigurations(redisCacheConfigurationMap)
                .build();
    }

}
host์™€ port๋Š” yml ํŒŒ์ผ์— ์ •์˜ํ•ด๋†“์œผ๋ฉด ๋œ๋‹ค.

 

  • redisConnectionFactory()
    • redis ์„œ๋ฒ„์™€ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” CommectionFactory๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • redis ํด๋ผ์ด์–ธํŠธ๋Š” Jedis์™€ Lettuce๊ฐ€ ์žˆ๋Š”๋ฐ ์Šคํ”„๋ง์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Lettuce๊ฐ€ ์„ค์ •๋ผ ์žˆ๋‹ค.
      • Jedis : ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ unsafe ํ•˜๋‹ค. Connection pool์„ ์ด์šฉํ•ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•˜๊ณ , Jedis์ธ์Šคํ„ด์Šค๋ž‘ ์—ฐ๊ฒฐํ•  ๋•Œ๋งˆ๋‹ค Connection pool์„ ๋ถˆ๋Ÿฌ์™€ ๋ฌผ๋ฆฌ์ ์ธ ๋น„์šฉ์ด ์ฆ๊ฐ€ํ•œ๋‹ค.
      • Lettuce : ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ safe ํ•˜๋‹ค. netty๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์œ„์— ๊ตฌ์ถ•๋œ๋‹ค. ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ์š”์ฒญํ•˜๋ฉฐ TPS/CPU/Connection ๊ฐœ์ˆ˜์™€ ์‘๋‹ต ์†๋„ ๋“ฑ jedis๋ณด๋‹ค ๋›ฐ์–ด๋‚˜๋‹ค.
  • RedisTemplate()
    • Spring Data Redis๋Š” RedisTemplate, RedisRepository ๋‘ ๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ์ ‘๊ทผํ•œ๋‹ค. 
      • RedisTemplate
        • Redis ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์„ค์ •์„ ๊ตฌ์„ฑํ•œ๋‹ค.
        • Redis์— ๋ฌธ์ž์—ด ํ‚ค์™€ JSON ํ˜•์‹์˜ ๊ฐ’์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค. 
        • ์ผ๋ฐ˜์ ์œผ๋กœ Redis์˜ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์œ ํ˜•์ธ ๋ฌธ์ž์—ด, ํ•ด์‹œ, ๋ชฉ๋ก, ์ง‘ํ•ฉ, ์ •๋ ฌ๋œ ์ง‘ํ•ฉ ๋“ฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. 
        • ๊ฐ์ฒด๋“ค์„ ์ž๋™์ ์œผ๋กœ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ํ•˜๋ฉฐ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ๋ฅผ Redis์— ์ €์žฅํ•œ๋‹ค. 
        • ๊ฐ ๋ฐ์ดํ„ฐ ์œ ํ˜•์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์ธ CRUD ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 
        • ์ €์ˆ˜์ค€์˜ API๋กœ ์ง์ ‘์ ์ธ Redis ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
      • RedisRepository
        • ๋” ์ถ”์ƒํ™”๋œ ๋ ˆ๋ฒจ์˜ ์ปดํฌ๋„ŒํŠธ๋กœ, Redis ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๊ณตํ†ต ์ž‘์—…์„ ๋” ํŽธ๋ฆฌํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ์ˆ˜์ค€์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. 
        • Spring Data JPA์˜ JpaRepository์™€ ์œ ์‚ฌํ•œ ํ˜•ํƒœ๋กœ ์ž‘์„ฑ๋˜๋ฉฐ, ์—”ํ‹ฐํ‹ฐ CRUD์™€ ๊ฐ™์€ ๊ณ ์ˆ˜์ค€์˜ ์ž‘์—…์„ ์ง€์›ํ•œ๋‹ค. 
        • ๊ฐœ๋ฐœ์ž๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” Redis ์ €์žฅ์†Œ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ, ์ง์ ‘ Redis ์ž‘์—…์„ ๊ตฌํ˜„ํ•  ํ•„์š” ์—†์ด Spring Data Redis์˜ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
    • redisCacheManager
      • Redis Cache ์ ์šฉ์„ ์œ„ํ•ด RedisCacheManager๋ฅผ ์„ค์ •ํ•œ๋‹ค. ๊ธฐ๋ณธ RedisCacheConfiguration์„ ๊ฐ€์ ธ์˜จ ํ›„, key์™€ value์˜ ์ง๋ ฌํ™” ๋ฐฉ์‹์„ ์„ค์ •ํ•œ๋‹ค.
      • ํ•ด๋‹น ์ฝ”๋“œ์—์„œ๋Š” StringRedisSerializer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ž์—ด๋กœ ๋œ ํ‚ค๋ฅผ ์ง๋ ฌํ™” ํ•˜๊ณ , GenericJackson2 JsonRedisSerializer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๋ฐ˜์ ์ธ ๊ฐ์ฒด๋ฅผ JSON ํ˜•์‹์œผ๋กœ ์ง๋ ฌํ™”ํ•œ๋‹ค.
      • Redis ์บ์‹œ ์ด๋ฆ„๊ณผ RedisCacheConfiguration์„ ๋งคํ•‘ํ•˜๋Š” ๋งต์„ ์ƒ์„ฑ ํ•œ๋‹ค. ๋‚˜๋Š” ์œ„์น˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ "all_place"๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์บ์‹œ๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค. 
      • entryTtl(Duration.ofHours())์— ์›ํ•˜๋Š” ์‹œ๊ฐ„์„ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.

 
 

Service

    @Cacheable(cacheNames = "all_place", key = "#memberId")
    public ListResult<GetAllPlaceResDto> getAllPlacesV2(Long memberId) {

		//... ์œ„์น˜ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ฝ”๋“œ

        return responseService.getListResult(new ArrayList<>(getAllPlaceResDtoList));

    }

 
@Cacheable ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•ด์„œ ์บ์‹ฑ์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.
๋‚˜๋Š” key๊ฐ’์„ memberId๋กœ ์„ค์ •ํ–ˆ๋‹ค.!! ์œ ์ €๋งˆ๋‹ค ํ™ˆ์—์„œ ๋ณด์ด๋Š” ํ™”๋ฉด์ด ๋‹ค๋ฅผ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
redis์—์„œ๋Š” key๊ฐ’์ด all_place::{memberId} ํ˜•์‹์œผ๋กœ ์ €์žฅ๋œ๋‹ค.
 
 
์บ์‹œ ์ ์šฉ ์ „

 
์บ์‹œ ์ ์šฉ ํ›„

 
์บ์‹ฑ์„ ์ ์šฉํ•˜๊ธฐ ์ „๊ณผ ํ›„๋ฅผ ๋น„๊ตํ–ˆ์„ ๋•Œ ์กฐํšŒ ์‹œ๊ฐ„์ด 493ms -> 8ms๋กœ ๋ณ€ํ–ˆ๋‹ค
์•ฝ 61๋ฐฐ ๋นจ๋ผ์ง„ ๊ฒฐ๊ณผ์ด๋‹ค!!  ์ด๋ ‡๊ฒŒ ์ฐจ์ด๋‚˜๋„ ๋˜๋Š”๊ฑด๊ฐ€...?
 
 
redis์—๋„ ์ž˜ ์ €์žฅ๋˜์—ˆ๋‹ค.

 
๊ทผ๋ฐ ์ด ๊ณผ์ •์—์„œ ๊ณ ๋ฏผ์ด ์ƒ๊ฒผ๋‹ค. ์บ์‹œ ์œ ํšจ์‹œ๊ฐ„์„ ์„ค์ •ํ•˜๋‹ˆ๊นŒ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋”๋ผ๋„ ์กฐํšŒํ•  ๋•Œ ์„ค์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ธฐ ์ „๊นŒ์ง€ ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๋Š” ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
 
๊ทธ๋ž˜์„œ ๋‚˜๋Š” CachePut์„ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋ ค๋‚˜ ์ƒ๊ฐํ–ˆ๋‹ค.
 

    @CachePut(cacheNames = "all_place", key = "#memberId")
    public ListResult<GetAllPlaceResDto> getAllPlacesV2(Long memberId) {

		// ... ์œ„์น˜ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ฝ”๋“œ

        return responseService.getListResult(new ArrayList<>(getAllPlaceResDtoList));

    }

 
์ด ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋‹ˆ๊นŒ ๋งค๋ฒˆ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ž˜ ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. ์†๋„๋„ @Cacheable๋งŒํผ์€ ์•„๋‹ˆ์ง€๋งŒ ์ถฉ๋ถ„ํžˆ ๋นจ๋ž๋‹ค! ํ•˜์ง€๋งŒ ์—…๋ฐ์ดํŠธ ๋˜์ง€ ์•Š์€ ์ •๋ณด์ธ๋ฐ๋„ ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. 
๋‹น์—ฐํžˆ CachePut ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ฐ˜ํ™˜๊ฐ’์ด ์บ์‹ฑ๋˜์–ด ์žˆ๋Š” ์œ ๋ฌด์™€ ์ƒ๊ด€์—†์ด ๋ฉ”์„œ๋“œ๋ฅผ ๋ฌด์กฐ๊ฑด ์‹คํ–‰ํ•œ๋‹ค!! 
 
๊ทธ๋ž˜์„œ ๋‚˜๋Š” ๊ทธ๋Œ€๋กœ @Cacheable์„ ์‚ฌ์šฉํ•˜๊ณ , ๊ฒŒ์‹œ๊ธ€์„ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ๋  ๋•Œ ์บ์‹œ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค ใ…Žใ…Ž
 

    @Transactional
    @CacheEvict(cacheNames = "all_place", key = "#memberId")
    public SingleResult<UploadPostingResDto> uploadPostingV3(UploadPostingReqDto uploadPostingReqDto, String imageUrl, Long memberId) {
    
    	// ... ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ๋กœ์ง
        return responseService.getSingleResult(uploadPostingResDto);

    }

 
์ด๋ ‡๊ฒŒ ํ•˜๋‹ˆ๊นŒ ์ •์ƒ์ ์œผ๋กœ ์บ์‹œ๊ฐ€ ์‚ญ์ œ๋˜๊ณ , ์กฐํšŒํ•  ๋•Œ ๋‹ค์‹œ ๋“ฑ๋ก๋˜๋Š” ๊ฑธ ํ™•์ธํ–ˆ๋‹ค ใ…Žใ…Ž