์คํ๋ง์ ๋ฒ์ 3.1๋ถํฐ ์บ์ฑ์ ํธํ๊ฒ ์ ์ฉ์ํฌ ์ ์๋๋ก ์ง์ํ๊ณ ์๋ค.
๊ธฐ์กด์ @Transactional
์ฒ๋ผ ๊ธฐ์กด ์ฝ๋์ ํฐ ๋ณ๊ฒฝ์์ด ์บ์ฑ์ ์ ์ฉ ์ํฌ ์ ์๋ค.
๋ค์ ๋งํด, ์คํ๋ง์ด ํธ๋์ญ์ ์ AOP๋ฅผ ์ด์ฉํ์ฌ ์ถ์ํ์ํจ ๊ฒ๊ณผ ์ ์ฌํ๋ค. (๋ฌผ๋ก IoC๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฉํ๋ค)
์บ์ฑ๋ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ์ AOP๋ฅผ ํ์ฉํ์ฌ ์ ๋ ธํ ์ด์ ๋ง ๋ถ์ฌ์ฃผ๋ฉด ์ฝ๊ฒ ์ ์ฉ์ํฌ ์ ์๋๋ก ์ถ์ํํด๋์๋ค.
Spring Framwork 4.1 ๋ถํฐ๋ JSR-107์ ์ค์ํ๋ ์ด๋ ธํ ์ด์ ์ ํตํด ์ ์ธ์ ์ธ ์บ์ฑ ๊ตฌํ์ด ๊ฐ๋ฅํด์ก๋ค.
๊ธฐ๋ณธ์ ์ ๊ฐ๋ ์ ๋ํ ๋ด์ฉ์ ๋ชจ๋ Spring Docs - Cache๋ฅผ ์ฐธ๊ณ ํ์๋ค.
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์คํ๋ง ์บ์ฑ ์ฝ์ด์ ๋ํด์ ๋ค๋ฃฌ๋ค.
์ฐ์ ์คํ๋ง์์ ์ด๋ค ๋ฐฉ์์ผ๋ก ์บ์ฑ์ ์ฒ๋ฆฌํ๊ณ , ์ถ์ํ ์์ผฐ๋์ง ์ดํด๋ณธ๋ค.
TIP) ๋ฒํผ์ ์บ์์ ๋ํ ์ฐจ์ด์ ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์.
ํต์ฌ์ ๋งํ์๋ฉด, ์คํ๋ง์ ์บ์ฑ์ ์ ์ฉํ๋ ์ฝ๋๋ฅผ ์ถ์ํํ์ฌ ์๋ฐ ๋ฉ์๋์ ์ ์ฉ์ํฌ ์ ์๋๋ก ํ์๋ค.
์๋ฅผ ๋ค์ด, MySQL๊ณผ ๊ฐ์ DB๋ก๋ถํฐ ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ์คํํ๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ฉ์๋๊ฐ ์กด์ฌํ๋ค๊ณ ๊ฐ์ ํด๋ณด์.
๊ทธ๋ผ ํด๋น ๋ฉ์๋์ ์บ์ฑ ์ ๋ ธํ ์ด์ ์ ๋ถ์ด๋ฉด AOP๋ฅผ ํตํด, ์บ์ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๊ฒ์ด๋ค.
์ด๋ ๋ง์ฝ ์บ์ DB (ex. Redis)์ ์กฐํํ๊ณ ์ํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ํด๋น ํ๊ฒ ๋ฉ์๋์ ๋ก์ง (์ค์ DB์ ์กฐํ ์ฟผ๋ฆฌ)์ ์คํ๋์ง ์๋๋ค.
์บ์ํด๋ ๊ฒฐ๊ณผ๋ฅผ Proxy์์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฌผ๋ก , ์บ์ DB์ ์กฐํํ๊ณ ์ํ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, ์ค์ DB์ ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค ๋ฐ์ดํฐ๊ฐ ๊ฐ์ ธ์์ ์บ์ DB์ ์ ์ฅํ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ค.
์บ์ฑ ์ ๋ต์ค
Look aside Cache
๋ฅผ ์๊ฐํ๋ฉด ์ดํดํ๊ธฐ ์ฝ๋ค.
์ ๋ง ํธํ ๊ฒ์ ์บ์ฑ ์ ๋ ธํ ์ด์ ๋ง ๋ถ์ด๋ฉด ์์ ๊ฐ์ด ์บ์ฑ ์ ๋ต์ AOP๋ฅผ ํตํด ์๋์ผ๋ก ์ ์ฉ๋๋ค๋ ๊ฒ์ด๋ค.
๊ฐ๋ฐ์๋ ๊ทธ์ ํต์ฌ ๋ก์ง (์ค์ DB๋ก๋ถํฐ ๋ฐ์ดํฐ ์กฐํ)๋ง์ ์์ฑํ๋ฉด ๋๋ค.
๋ฌผ๋ก ์บ์ฑ DB์ ๋ฐ์ดํฐ๋ฅผ ์ค์ DB์ ๋๊ธฐํ์ํค๊ธฐ ์ํ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค.
์ฆ, ์บ์ฑ DB์ ์ ์ฅ๋๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๊ฑฐ๋ ์ญ์ ํ๋ ๊ธฐ๋ฅ๋ ์ ๊ณตํ๋ค.
์ด๋ ๋ฐ์ดํฐ์ ๋ณ๊ฒฝ์ด ๋ฐ์ํ์ ๋ ๊ต์ฅํ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ฉฐ, ์ด ๋ํ ์ ๋ ธํ ์ด์ ์ ๋ถ์ด๋ฉด ์ฝ๊ฒ ์ ์ฉ์ํฌ ์ ์๋ค.
์ฝ๊ฒ ์๊ธฐํด์ get-if-not-found-then-proceed-and-put-eventually code blocks
๋ผ๊ณ ์ดํดํ๋ฉด ์ฝ๋ค.
์คํ๋ง์ ํ๋ ์์ํฌ๋ต๊ฒ ๊ฐ๋ฐ์๋ค์ด ํต์ฌ ๋ก์ง๋ง ์์ฑํ๋ฉด ์ฝ๊ฒ ๋ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ (ex. ํธ๋์ญ์ , ์บ์ฑ)๋ฑ์ ์ ์ฉ์ํฌ ์ ์๋๋ก ์ถ์ํ์์ผ๋์๋ค.
๋ค์ ํ๋ฒ, ์คํ๋ง์ ์ฌ์ฉํ๋ฉด์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ, ๊ฐ์ฒด์งํฅ ์์น์ ๋ํ ์ดํด๋ฅผ ๋์ผ ์ ์์๋ค.
์ด ์ฅ์ ๊ทธ๋ฅ ๋๊ฒจ๋ ๋๋ค. ์ถํ์ ์ง์ ๊ตฌํํ๋ฉฐ ๊ธ์ ์์ฑํ ์์ ์ด๋ค.
์ด์ ์คํ๋ง์ด ์ถ์์ ์ผ๋ก ์ด๋ค ๋ฐฉ์์ ํตํด ์บ์ฑ์ ์ฒ๋ฆฌํ๋์ง๋ ์์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ค์ ๋ก ์ด๋ค ๊ฐ์ฒด๋ค์ด ์ฑ ์์ ๋๋ ๊ฐ์ ธ๊ฐ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ผ๊น?
์์์ ์ธ๊ธํ๋ฏ์ด, ์บ์ฑ ๋ก์ง๋ ์คํ๋ง์ ๋ชจ๋ ์ถ์ํ์์ผ๋์๋ค.
ํ์ด ์๊ธฐํ์๋ฉด, AOP๋ฅผ ์ ์ฉ์ํค๊ธฐ์ํ Aspect
, CacheAnnocationParser
, CacheProxyFactoryBean
๋ฑ๋ฑ์ ์ถ์ํ์์ผฐ๋ค.
์คํ๋ง ์บ์ฑ ์์กด์ฑ์ ์ถ๊ฐํ๊ณ , @EnableCaching
์ ๋
ธํ
์ด์
์ ์ ์ธํด์ฃผ๋ฉด ์๋์ผ๋ก ๊ตฌํ์ฒด๊ฐ ์ฃผ์
๋๋ค.
CacheAspectSupport
: Base class for caching aspects, such as the CacheInterceptor or an AspectJ aspect.CacheInterceptor
: ๊ตฌํ์ฒด
SpringCacheAnnotationParser
: Strategy implementation for parsing Spring's {@link Caching}, {@link Cacheable},CacheProxyFactoryBean
: Proxy factory bean for simplified declarative caching handling.
์คํ๋ง์ด ์ถ์ํ๋ฅผ ์ ํด๋์๊ธฐ ๋๋ฌธ์, ์ฌ์ค ์ฌ์ฉํ๋๋ฐ ์์ด์ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ๋ณผ ์ผ์ ๋ง์ด ์๋ค.
๊ทธ๋์ ์ด๋ฒ ๊ธ์์ ๊ฐ๋จํ๋ง ๋ค๋ฃจ๊ณ , ์ถํ์ ์ง์ AOP๋ฅผ ์ด์ฉํ์ฌ ์บ์ฑ์ ๊ตฌํํ๋ ๊ธ์ ์์ฑํด์ ๊ณต์ ํ ์์ ์ด๋ค.
์คํ๋ง์ด ์บ์ฑ ๊ธฐ๋ฅ์ ์ ์ถ์ํ์์ผฐ๊ณ , ๊ทธ์
@EnableCaching
์ด๋ผ๋ ์ ๋ ธํ ์ด์ ์ ์ ์ธ๋งํด์ฃผ๋ฉด, ์บ์ ๊ด๋ จ๋ ์ ๋ ธํ ์ด์ ์ ์ค์บํ์ฌ ์บ์ฑ ๋ก์ง์ ์ํํ๋ค.
์ฌ์ค ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ์บ์ ๋ฐ์ดํฐ๋ฅผ ์ด๋์ ์ ์ฅํ๋๋์ด๋ค.
๋ค์ ๋งํด, ์คํ๋ง์ ์บ์ ๊ด๋ จ๋ ๋ก์ง์ ์ ๊ณตํ์ง๋ง, ์บ์ ๋ฐ์ดํฐ๋ฅผ ์ด๋์ ์ ์ฅํ ์ง๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ํด์ค์ผํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋ถ๋ถ์ ์คํ๋ง์ ์๋ ๋ ๊ฐ์ง ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํด ์ถ์ํํด๋์๋ค.
org.springframework.cache.Cache
: ์บ์ ๋ฐ์ดํฐ์ ๋ํ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด.- is managed by Cache Manager, which manages the life cycle of Cache. Cache exists in the context of Cache Manager and is a map-like data structure that temporarily stores key-indexed values.A Cache is owned by only one CacheManager.
org.springframework.cache.CacheManager
: ์บ์๋ฅผ ๊ด๋ฆฌํด์ฃผ๋ ๋งค๋์ .Cache
๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๋ค.- Create, configure, acquire, manage, and control multiple uniquely named Caches that exist within the context of CacheManager. A CacheManager corresponds to only one CachingProvider
๋ ์์ธํ ์ํคํ ์ฒ ๋ถ๋ถ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์.
์คํ๋ง์ ์๋์ ๊ฐ์ ์บ์ DB์ ๋ํ ๊ตฌํ์ฒด๋ฅผ ์ ๊ณตํ๋ค.
- ConcurrentMapCacheManager: Java์ConcurrentHashMap์ ์ฌ์ฉํด ๊ตฌํํ ์บ์๋ฅผ ์ฌ์ฉํ๋ ์บ์๋งค๋์
- SimpleCacheManager: ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ์บ์๊ฐ ์์ด ์ฌ์ฉํ ์บ์๋ฅผ ์ง์ ๋ฑ๋กํ์ฌ ์ฌ์ฉํ๊ธฐ ์ํ ์บ์๋งค๋์
- EhCacheCacheManager: ์๋ฐ์์ ์ ๋ช ํ ์บ์ ํ๋ ์์ํฌ ์ค ํ๋์ธ EhCache๋ฅผ ์ง์ํ๋ ์บ์ ๋งค๋์
- CompositeCacheManager: 1๊ฐ ์ด์์ ์บ์ ๋งค๋์ ๋ฅผ ์ฌ์ฉํ๋๋ก ์ง์ํด์ฃผ๋ ํผํฉ ์บ์ ๋งค๋์
- CaffeineCacheManager: Java 8๋ก Guava ์บ์๋ฅผ ์ฌ์์ฑํ Caffeine ์บ์๋ฅผ ์ฌ์ฉํ๋ ์บ์ ๋งค๋์
- JCacheCacheManager: JSR-107 ๊ธฐ๋ฐ์ ์บ์๋ฅผ ์ฌ์ฉํ๋ ์บ์ ๋งค๋์
- RedisCacheManager: ์บ์ ์ ์ฅ์๋ก ์ ๋ช ํ Redis๋ฅผ ์ง์ํ๋ ์บ์ ๋งค๋์ .
๋ํ, ๊ฐ ์บ์ ๋งค๋์ ๋ณ Cache
๊ฐ์ฒด์ ๊ตฌํ์ฒด๋ ์ ๊ณตํ๋ค.
์คํ๋ง์ ์บ์ฑ ์ถ์ํ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฉํฐ ์ค๋ ๋๋ ๋ฉํฐ ํ๋ก์ธ์ค๋ฅผ ์ํ ์ฒ๋ฆฌ๋ฅผ ์ ๊ณตํ์ง ์๋๋ค.
๋ง์ฝ ์ฌ๋ฌ ๋ฉํฐ ์ค๋ ๋ ํ๊ฒฝ์์ ์บ์ฑ ์ฒ๋ฆฌ๋ฅผ ํ๋ ค๊ณ ํ๋ค๋ฉด ๋ฐ๋ก ์ค์ ํด์ค์ผ ํ๋ค. (DB Lock๊ฐ์ ๊ธฐ๋ฅ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ์ง ์๋๋ค)
๊ทธ๋ฌ๋ฏ๋ก ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ์์ดํ ๋ฅผ ์ ๊ทผํ๊ณ ์์ ํ๋ ค๊ณ ํ๋ฉด, ์์๊ณผ ๋ค๋ฅด๊ฒ ๋์ํ ์ ์๋ค.
๋ฌผ๋ก sync
๋ผ๋ ์ค์ ์ด ์กด์ฌํ์ง๋ง, ๋๋ถ๋ถ์ ์บ์ ์ ์ฅ์๊ฐ ์ด๋ฅผ ์ง์ํ์ง ์๋๋ค. (๋ฌผ๋ก ์ง์ํ๋ ์ ์ฅ์๊ฐ ์์์๋...)
๋ค๋ง, ํ์ ์๊ฐ์ ์บ์ ๋ฐ์ดํฐ๋ ์ฑ๋ฅ์ ๋์ด๊ธฐ ์ํ ์์ ๋ฐ์ดํฐ์ผ ๋ฟ ํธ๋์ญ์ ๋ฝ๊ณผ ๊ฐ์ ์ฑ๋ฅ์ ์ ํํ ์ ์๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ค๋ ๊ฒ์ ๋ง์ง ์๋ค๊ณ ์๊ฐํ๋ค.
๋ง์ฝ ์ด๋ ๊ฒ ์ฌ์ฉํด์ผํ๋ค๋ฉด ์ด๋ ์ค๊ณ์์ ์๋ชป๋ ๋ถ๋ถ์ด ์กด์ฌํ์ง ์๋์ถ๋ค.
์คํ๋ง์์ ์บ์ฑ์ฒ๋ฆฌ๋ฅผ ์ ์ฉ์ํค๊ธฐ์ํด ์ ๊ฒฝ์จ์ผํ ๋ถ๋ถ์ ์ฌ์ค ๋ฑ ๋๊ฐ์ง์ด๋ค.
- Caching declaration: Identify the methods that need to be cached and their policy.
- ์ ๋ ธํ ์ด์ ์ ํตํด ์ด๋ค ๋ฉ์๋๊ฐ ์บ์ฑ์ด ํ์ํ์ง, ๋ํ ์ ๋ ธํ ์ด์ ์ ํตํด ์ด๋ค ์บ์ฑ ์ ์ฑ ์ ์ฌ์ฉํ ์ง ์ค์ ํด์ฃผ๋ฉด๋๋ค.
- Cache Configuration: The backing cache where the data is stored and from which it is read.
- ์บ์ํ ๋ฐ์ดํฐ๋ฅผ ์ด๋์ ์ ์ฅํ๊ณ ์ฝ์ด์ฌ์ง ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
์์์ ์ธ๊ธํ๋ฏ์ด ์คํ๋ง ์บ์ฑ์ ์ ์ธ์ ์ ๋ ธํ ์ด์ ์ ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ค.
๊ทธ๋ฌ๋ฏ๋ก ๊ฐ ์ ๋ ธํ ์ด์ ์ ๋ํ ์ดํด๊ฐ ํ์ํ๋ค.
- @Cacheable: Triggers cache population. (์บ์ ๋ฐ์ดํฐ ์กฐํ ํธ๋ฆฌ๊ฑฐ)
- @CacheEvict: Triggers cache eviction. (์บ์ ๋ฐ์ดํฐ ์ญ์ ํธ๋ฆฌ๊ฑฐ)
- @CachePut: Updates the cache without interfering with the method execution. (๋ฉ์๋ ์คํ์ ๋ฐฉํดํ์ง ์๊ณ ์บ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธ)
- @Caching: Regroups multiple cache operations to be applied on a method. (๋ฉ์๋์ ์ ์ฉํ ์ฌ๋ฌ ์บ์ ์์ ์ ๋ค์ ๊ทธ๋ฃนํ)
- @CacheConfig: Shares some common cache-related settings at class-level. (ํด๋์ค ๋ ๋ฒจ์์ ๊ณตํต ์บ์ฑ ์ค์ )
์๋ฐ ๋ฉ์๋์ @Cacheable
์ ์ค์ ํจ์ผ๋ก์จ ํด๋น ๋ฉ์๋์ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ ์ ์๋ค.
ํ๊ฒ๋ฉ์๋๊ฐ ํธ์ถ๋์์ ๋, ์บ์์ ํด๋น ๋ฉ์๋๊ฐ ์ด๋ฏธ ๋์ผํ ์ธ์๋ก ์กด์ฌํ๋ค๋ฉด ์บ์ํด๋ ๊ฒฐ๊ณผ๋ฅผ Proxy์์ ๋ฐํํ๋ค.
๋ง์ฝ ์บ์ฑ์ด ํํธ๋์ด ์บ์ฑ์ ์ฅ์์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ๋ค๋ฉด, ํ๊ฒ๋ฉ์๋๊ฐ ์คํ์กฐ์ฐจ๋์ง์๋๋ค.
์บ์ฑํด๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด, ํ๊ฒ๋ฉ์๋๋ฅผ ์คํ์์ผ ์ค์ DB๋ก๋ถํฐ ์กฐํํ์ฌ ์บ์ฑ ์ ์ฅ์์ ์ ์ฅํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ค.
@Cacheable("books")
public Book findBook(ISBN isbn) {...}
- ์บ์ฑ ์ ๋ต (์กฐ๊ฑด)์์ด ๋ชจ๋ ์ธ์๋ฅผ ์บ์ฑํ๊ณ ์ํ๋ค๋ฉด ์์ ๊ฐ์ด ์ฌ์ฉํ๋ฉด ๋๋ค.
books
๋ผ๋ ์ด๋ฆ์ผ๋ก ์บ์์ ์ฅ์๊ฐ ์ฌ์ฉ๋๋ค.- ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋ ๋งค๋ฒ
books
๋ผ๋ ์บ์ ๋ฐ์ดํฐ๋ฅผ ํ์ธํ๋ค.
- ๋ฉ์๋๊ฐ ํธ์ถ๋ ๋ ๋งค๋ฒ
- ์บ์ ์ ์ฅ์๋ ์ฌ๋ฌ ๊ฐ ์ ์ํ ์ ์๋ค.
- ex.
@Cacheable({"books", "isbns"})
->books
์ isbns`๋ผ๋ ๋ ๊ตฐ๋ฐ์ ์บ์ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๋ค.
- ex.
Redis๋ฅผ ์ด์ฉํ์ฌ books ์บ์ ์ ์ฅ์์ ์ ์ฅ์ํจ ์์
Redis๋ฅผ ์ด์ฉํ์ฌ books์ isbns ์บ์ ์ ์ฅ์์ ์ ์ฅ์ํจ ์์
redis-cli๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๊ณ ์ถ๋ค๋ฉด
get books::test-isbn
ํน์get isbns::test-isbn
๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ๋ฉด ๋๋ค.
์บ์๋ ํ์์ ์ผ๋ก key:value
ํ์์ผ๋ก ์ ์ฅ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ๊ฐ ๋ฉ์๋๋ง๋ค ์ด๋ค key๋ฅผ ํตํด ์บ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์กฐํํ ์ง ์ค์ ํด์ฃผ์ด์ผํ๋ค.
๋ณ๋์ ์ปค์คํ ํค๋ฅผ ์ ์ํ์ง ์์ผ๋ฉด, ๋ํดํธ๋ก ์๊ณ ๋ฆฌ์ฆ ๊ธฐ๋ฐ์ KeyGenerator๋ฅผ ์ฌ์ฉํ์ฌ ํค๋ฅผ ์์ฑํ๋ค.
๋ํดํธ๋ก ์ ์๋์ด์๋ KeyGenerator
๋ ์๋์ ๊ฐ์ด ๋์ํ๋ค. (๋ํดํธ๋ก SimpleKeyGenerator
๋ฅผ ์ฌ์ฉํ๋ค.)
- ๋งค๊ฐ๋ณ์๊ฐ ์๋ฌด๊ฒ๋ ์์ผ๋ฉด
SimpleKey.EMPTY
์ ๋ฐํ. - ๋งค๊ฐ๋ณ์๊ฐ ํ๋๋ฉด, ๊ทธ ์ธ์คํด์ค๋ฅผ ๋ฐํ.
- ๋งค๊ฐ๋ณ์๊ฐ ๋ ์ด์์ด๋ฉด,
SimpleKey
๋ฅผ ๋ฐํ. (๋ชจ๋ ๋งค๊ฐ๋ณ์์ Hash ๊ฐ์ผ๋ก ๊ณ์ฐ๋ ํค)
๊ธฐ๋ณธํค๋ ๋งค๊ฐ๋ณ์์ ๊ธฐ๋ณธ ํ์
ํ์๋๋ฉด hashCode()
์ equals()
๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐ๋ ํค๋ฅผ ์ ์ฅํ๋ค.
SimpleKey
์์Object[]
ํ์์ผ๋ก ํค๋ฅผ ๊ฐ์ง๊ณ ์๋๋ค.
์ปค์คํ
key ์ ์ฑ
์ ์ค์ ํ๋ ค๋ฉด org.springframework.cache.KeyGenerator
์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ , CacheResolver
์ ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
์ ์ธ์ Custom Key ์ค์
์คํ๋ง์์ ๊ฐ ๋ฉ์๋๋ง๋ค ์ฝ๊ฒ ์ํ๋ key๋ฅผ ์ปค์คํ ํ ์ ์๋๋ก ์ ์ธ์ ์ค์ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ค.
์ํ๋ Key๊ฐ ์๋ค๋ฉด ์๋์ ๊ฐ์ด SpEL
์ ์ฌ์ฉํ๋ฉฐ ์ ์ํด์ฃผ๋ฉด ๋๋ค.
@Cacheable(value="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(value="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@Cacheable(value="books", key="T(someType).hash(#isbn)")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
๋ง์ฝ SpEL๋ก key์ ๋ํ ์ปค์คํ
์ค์ ์ด ๋ณต์กํด์ง๋ค๋ฉด ์๋์ ๊ฐ์ด ์ง์ KeyGenerator
๋ฅผ ๊ตฌํํ์ฌ ์ค์ ํด์ฃผ๋ฉด ๋๋ค.
@Cacheable(cacheNames="books", keyGenerator="myKeyGenerator")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
์ฐธ๊ณ ๋ก key์ keyGenerator๋ ์ํธ๋ฐฐํ์ ์ด๋ค. ์ฆ, ๋์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋ค.
์คํ๋ง์์ ์ถ์ํํ ์บ์ฑ์ ๊ธฐ๋ณธ์ ์ผ๋ก CacheResolver
์์ CacheManger
์ ์ค์ ์ ๋ณด๊ณ ์บ์๋ฅผ ํ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ํดํธ๋ก ์ฌ์ฉ๋๋ CacheResolver
๋ SimpleCacheResolver
์ด๋ฉฐ, ์ด ๊ตฌํ์ฒด๋ ์ค์ ๋ CacheManager
์ ๋ฐ๋ผ ์บ์๋ฅผ ํ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ ํ๋์ CacheManager
์ ์ ํฉํด์, ๋ณต์กํ ์ค์ ์ ํ ์ ์๋ค.
๋ง์ฝ ์ ํ๋ฆฌ์ผ์ด์
์ด ์ฌ๋ฌ ๊ฐ์ CacheManager
๋ฅผ ์ค์ ํด์ผํ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ค์ ํด์ ์ฌ์ฉํ๋ฉด๋๋ค.
@Cacheable(cacheNames="books", cacheManager="anotherCacheManager")
public Book findBook(ISBN isbn) {...}
๋ง์ฝ CacheResolver
์์ฒด๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ค์ ํด์ค ์ ์๋ค.
@Cacheable(cacheResolver="runtimeCacheResolver")
public Book findBook(ISBN isbn) {...}
์ด ๋ ์ค์ ๋ ์ํธ๋ฒ ํ์ ์ผ๋ฏ๋ก ํ๋๋ง ์ค์ ๊ฐ๋ฅํ๋ค. ๋ ๋ค ์ค์ ํ ๊ฒฝ์ฐ ์์ธ๊ฐ ๋ฐ์ํ๋ค.
...์ผ๋ ์บ์ฑ์ ํด๋ผ
SpEL์ ์ฌ์ฉํ์ฌ ์บ์ฑ ์กฐ๊ฑด์ ์ค์ ํด์ค ์ ์๋ค.
- Condition๋ก ์ฃผ์ด์ง ๊ฐ์ด
true
๋ฉด ์บ์ฑ O- ๋ฉ์๋ ๋ด๋ถ(ํต์ฌ ๊ฐ์ฒด)๊ฐ ์คํ๋์ง ์๋๋ค.
- Condition๋ก ์ฃผ์ด์ง ๊ฐ์ด
false
๋ฉด ์บ์ฑ X- ๋ฉ์๋ ๋ด๋ถ(ํต์ฌ ๊ฐ์ฒด)๊ฐ ์คํ๋๋ค.
@Cacheable(value="book", condition="#name.length < 32")
public Book findBook(String name)
์ด์ธ์๋ SpEL์ ์ด์ฉํ์ฌ ๋ฉํ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ ์๋ ์๋ค.
์ด์ ๊ด๋ จ๋ ๋ด์ฉ์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์.
SpEL์ ๋ํ ๋ด์ฉ์ Baeldung - SpEL์ ๊ณต์ ๋ฌธ์์ ์ฐธ๊ณ ํ์.
...๋ง ์๋๋ฉด ์บ์ฑํ๋ผ
condition
๊ณผ ๋์ผํ๊ฒ ์บ์ฑ ์กฐ๊ฑด์ ์ค์ ํด์ค ์ ์๋ค.
๋จ, condition
๊ณผ ๋ค๋ฅด๊ฒ unless
๋ ๋ฉ์๋์ ๊ฒฐ๊ณผ๊ฐ ๋ฐํ ์์ ์ ๊ฒฐ๊ณผ๊ฐ์ ํ์ธํ์ฌ ์บ์ฑ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค.
๋ค์ ๋งํด, ๋ฉ์๋ ๋ด๋ถ (ํต์ฌ ๊ฐ์ฒด)๊ฐ ํญ์ ์คํ๋๋ค.
- unless๋ก ์ฃผ์ด์ง ๊ฐ์ด
true
๋ฉด ์บ์ฑ X - unless๋ก ์ฃผ์ด์ง ๊ฐ์ด
false
๋ฉด ์บ์ฑ O
@Cacheable(value="book", condition="#name.length < 32", unless="#result.hardback")
public Book findBook(String name)
- ๋ฉ์๋ ๋งค๊ฐ๋ณ์์
name
์ ๊ธธ์ด๊ฐ 32์ด ์ดํ๋ฉฐ, ๋ฐํ๋๋ ๊ฒฐ๊ณผ์Optional
์ ๊ฐ์ด null์ด๋ฉด ์บ์ฑ๋์ง ์๋๋ค. #result
๋ฅผ ํตํด ๋ฉ์๋ ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๋ค. (unless
์ cache evict ํํ์์๋ง ์ฌ์ฉ๊ฐ๋ฅํ๋ค.)
@Cacheable(value="book", condition="#name.length < 32", unless="#result == null")
public Book findBook(String name)
- ๋ฐํ๋๋ ๊ฒฐ๊ณผ๊ฐ
null
์ด๋ฉด ์บ์ฑํ์ง ๋ง๋ผ๋ ์๋ฏธ.
๋ํดํธ๋ false๋ค.
sync = true
๋ก ์ค์ ํ๋ฉด, ํด๋น ๋ฉ์๋๋ ํ๋์ ์ค๋ ๋์์๋ง ์ ๊ทผํ ์ ์๋ค. (๋๊ธฐ)
@Cacheable(cacheNames="foos", sync=true)
public Foo executeExpensiveOperation(String id) {...}
๋๋ถ๋ถ์ ์บ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ด๋ฅผ ์ง์ํ์ง ์๋๋ค๊ณ ํ๋ค. (์ฌ์ค์ ์บ์ ์ ์ฅ์๋ก ์ฌ์ฉํ๋ค๋ฉด ๊ตณ์ด ์ฌ์ฉํ ํ์ ์์ด๋ณด์ธ๋ค.)
@CachePut
์ด ๋ถ์ ๋ฉ์๋๋ ํญ์ ์คํ ๋๋ฉฐ, ๊ฒฐ๊ณผ๋ @CachePut
์ต์
์ ๋ฐ๋ผ ์บ์์ ์ ์ฅ๋๋ค.
์ฆ, ์บ์๋์ด์๋ ๋ฐ์ดํฐ๊ฐ ์์ด๋, @CachePut
์ด ๋ถ์ ๋ฉ์๋๋ ํญ์ ํธ์ถ๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ ์บ์์ ์ ์ฅ๋๋ค.
๋ณดํต ์บ์์ ์ ์ฅํ๊ฑฐ๋ ์ ๋ฐ์ดํธ๋ฅผ ํด์ผํ๋ ๊ฒฝ์ฐ ์ฌ์ฉ๋๋ค.
@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor)
@CachePut
์ @Cacheable
๊ณผ ๋์ผํ ์ต์
์ ์ ๊ณตํ๋ค. ๋ค๋ง, ์บ์์ ์ ์ฅํ๋ ๊ฒ๋ณด๋ค๋ ๋ฉ์๋ ํ๋ฆ์ ์ต์ ํํ๋๋ฐ ์ฌ์ฉ๋์ด์ผํ๋ค.
ํ ๋ฉ์๋์
@Cacheable
์@CachePut
์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์๋๋ค.
Evict: ์ถ์ถ, ์ซ์๋
@CacheEvict
๋ @Cacheable
๊ณผ ๋ฐ๋๋ก, ์บ์ ์ ์ฅ์์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ง์ธ ๋ ์ฌ์ฉ๋๋ค.
@CacheEvict
๋ ์ฌ๋ฌ ๊ฐ์ ์บ์๋ฅผ ๋ช
์ํ ์ ์์ผ๋ฉฐ, key
์ condition
์ ์ฌ์ฉํ ์ ์๋ค.
๋ํ, allEntries
์์ฑ์ ํตํด ํค๊ฐ์ผ๋ก Cache Entrie
ํ๋๋ง ๋น์ฐ๋ ๊ฒ์ด ์๋, ์บ์ ์์ญ์ ๋ชจ๋ Entrie
๋ฅผ ๋น์ด๋ค.
์ด ๊ฒฝ์ฐ์๋ ํค๋ฅผ ๋ช ์ํ๋๋ผ๋ ์ด๋ฅผ ๋ฌด์ํ๊ณ ๋ชจ๋ Entrie๋ฅผ ๋น์ฐ๊ฒ ๋๋ค.
๋ค์์ ์บ์ ์ ๋
ธํ
์ด์
์ ์ฐ๊ณ ์ ํ ๋ @Caching
์ ์ด๋ค. @Cacheable
, @CacheEvic
, @CachePut
์ ์ง์ํ๋ค.
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(value = "secondary", key = "#p0") })
public Book importBooks(String deposit, Date date)
์๋ฅผ ๋ค์ด ๊ฐ์ ๋ฉ์๋์ด์ง๋ง ์บ์ ์ ์ฅ์์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์บ์ ์ค์ ์ ํด์ค์ผํ ๋ ์ฌ์ฉ๋ ์ ์๋ค.
์ง๊ธ๊น์ง์ ์ค์ ์ ๋๋ถ๋ถ ๋ฉ์๋์ ์ค์ ํด์ฃผ๋ ๊ฒ์ด์๋ค.
๋ง์ฝ ํน์ ํด๋์ค์์ ์๋ ๋ฉ์๋ ๋ชจ๋์ ์บ์ ๊ด๋ จ๋ ์ค์ ์ ํ๋ฒ์ ํ๊ณ ์ถ๋ค๋ฉด, @CacheConfig
๋ฅผ ์ฌ์ฉํ๋ฉด๋๋ค.
์๋ฅผ ๋ค์ด, ํน์ ํด๋์ค์ ์๋ ์บ์ name์ ๋ชจ๋ books
๋ก ํ๊ณ ์ถ๋ค๋ฉด ์๋์ ๊ฐ์ด ์ค์ ํ ์ ์๋ค.
@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
}
@CacheConfig
๋ฅผ ํตํด ํน์ ํด๋์ค์์ ๋ชจ๋ ๋ฉ์๋์ cacheName
, CacheManager
, KeyGenerator
, CacheResolver
๋ฑ์ ์ค์ ํด์ค ์ ์๋ค.
@CacheConfig
๋ ํด๋์ค ๋ ๋ฒจ ์ ๋
ธํ
์ด์
์ด๋ค.
๋ฌผ๋ก ๋ฉ์๋ ๋ ๋ฒจ๋ก ์ฌ์ ์ํ๋ค๋ฉด ํด๋น ๋ฉ์๋ ๋ ๋ฒจ ์ ๋ ธํ ์ด์ ์ ์ฐ์ ์์๊ฐ ๋ ๋๋ค.
์บ์ ์ค์ ๋ ๋ฒจ
์บ์ ์ค์ ์ ์ธ ๊ฐ์ง ๋ ๋ฒจ๋ก ๋๋๋ฉฐ, ๋ฎ์์ง ์๋ก ์ค๋ฒ๋ผ์ด๋ฉ๋๋ค. (๋ฎ์์ง ์๋ก ์ฐ์ ์์๊ฐ ๋๋ค.)
- Global ์ค์ .
@EnableCaching
์ด ๋ถ์ Configuration์์CacheManger
,KeyGenerator
์ ์ฌ์ฉํ ์ ์๋ค.
- ํด๋์ค ๋ ๋ฒจ ์ค์ .
@CacheConfig
๋ฅผ ์ฌ์ฉํ๋ค.
- ๋ฉ์๋ ๋ ๋ฒจ ์ค์ .
๋ง์ง๋ง ์ ๋ ธํ ์ด์ ์ ์บ์ ์ค์ ์ ๋ ธํ ์ด์ ์ด๋ค.
์๋ฌด๋ฆฌ ์บ์ ๊ด๋ จ ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ ์บ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ค์ ํด๋์ด๋, ํ์ฑํ๋ฅผ ์ํค์ง ์์ผ๋ฉด ๋์ํ์ง ์๋๋ค.
๋ชจ๋ ์บ์ฑ ์ ๋
ธํ
์ด์
๋ฅผ ํ์ฑํ์ํค๋ ค๋ฉด @EnableCaching
์ ์๋ฌด @Configuration
ํด๋์ค์ ์ถ๊ฐํด์ค์ผํ๋ค.
@Configuration
@EnableCaching
public class AppConfig {
}
์ด๋ Global ์ค์ ์ ์ํ๋ฉฐ, ์ ๋
ธํ
์ด์
์ ์ค์ ์ ํตํด ErrorHandler
, CacheManager
, KeyGenerator
, CacheResolver
๋ฑ์ ์ค์ ํด์ค ์ ์๋ค.
@SpringBootApplication
์ด@Configuration
์ ์์๋ฐ์ผ๋ฏ๋ก, Application ์์๋ถ๋ถ์ ๋ฃ๋ ์์๋ ๋ง์ด ๋ดค๋ค.
์์ํ ๋ ๊ณต์ ๋ฌธ์์ ์ด์ ๋ ๋ถ์ผ ์์ ์ด์์ง๋ง, ๊ฑฐ์ ๊ณต์ ๋ฌธ์ ๋ฒ์ญ์ด ๋์๋ค...
๊ทธ๋๋ ์ฝ๊ณ ๋ฒ์ญํ๊ณ ์ ๋ฆฌํ๋ฉฐ, ์คํ๋ง ์บ์ฑ์ ๋ํด์ ๋ ๊น๊ฒ ์ดํดํ ์ ์์๋ค.
๋ถ๋ ์ด ์๋ฃ๊ฐ ๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋๊ธฐ๋ฅผ..ใ