Cache๋?
๋์ค์ ํ ์์ฒญ ๊ฒฐ๊ณผ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅ ํด ๋์๋ค๊ฐ ๋น ๋ฅด๊ฒ ์๋น์ค ํด ์ฃผ๋ ๊ฒ
- Look aside Cache(์ผ๋ฐ์ ์ผ๋ก ๋ง์ด ์ฐ๋ ๋ฐฉ์)
- DB๋ฅผ ๊ฐ๊ธฐ ์ ์ Cache์ ๋จผ์ ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธ ํด๋ณธ๋ค.
- ๋ง์ฝ Cache์ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์บ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ , ์๋ค๋ฉด DB๋ฅผ ์ฝ์ ํ Cache์ ์ ์ฅ & ๊ฒฐ๊ณผ ๋ฆฌํด
- Write Back(๋ก๊ทธ๋ฅผ DB์ ์ ์ฅํ๋ ๊ฒฝ์ฐ, ์ฐ๊ธฐ ์ฐ์ฐ์ด ๋ง์ ๊ฒฝ์ฐ)
- ์บ์์ ๋จผ์ ์ ์ฅํ๋ค๊ฐ, ํน์ ์์ ๋ง๋ค DB์ ์ ์ฅํ๋ ๋ฐฉ์
- ex. ๊ฑธ๋ฆฌ๋ ์๊ฐ(๋ฐฐ์น ์์ ) - DB insert ์ฟผ๋ฆฌ๋ฅผ 1๋ฒ์ฉ * 500๋ฒ >> insert์ฟผ๋ฆฌ 500๊ฐ ํฉ์น ๊ฒ * 1๋ฒ
- ๋จ์ : ์ฅ์ ๊ฐ ์๊ธฐ๋ฉด ๋ฐ์ดํฐ๊ฐ ์ฌ๋ผ์ง ์ํ์ด ์๋ค. ์๋๋ฉด ๋ฆฌ๋ถํ ๋๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ ์ฌ๋ผ์ง๊ธฐ ๋๋ฌธ
์บ์๊ฐ ๋๋ ๋์๋ค
- ๋จ์ํ ๊ตฌ์กฐ์ ์ ๋ณด
- ๋ฐ๋ณต์ ์ผ๋ก ๊ณ์ ์ฌ์ฉํ๋ ์ ๋ณด
- ์ ๋ณด์ ๋ณ๊ฒฝ์ฃผ๊ธฐ๊ฐ ๋น๋ฒํ์ง ์๊ณ , ๋จ์์ฒ๋ฆฌ ์๊ฐ์ด ์ค๋๊ฑธ๋ฆฌ๋ ์ ๋ณด
- ์ ๋ณด์ ์ต์ ํ๊ฐ ์ค์๊ฐ์ผ๋ก ์ด๋ค์ง์ง์์๋ ์๋น์ค์ ์ํฅ์ด ์ ์ ์ ๋ณด
์บ์ฑ ์ ๋ต (Caching Strategies)
๋ณดํต ๋ ๋์ค๋ฅผ cache๋ก ์ฌ์ฉํ ๋ ๋ ๋์ค๋ฅผ ์ด๋ป๊ฒ ๋ฐฐ์นํ๋์ ๋ฐ๋ผ ์์คํ ์ ์ฒด ์ฑ๋ฅ์ ํฐ ์ํฅ์ ๋ผ์น๋ค. ๊ทธ๋์ ๋ ๋์ค๋ฅผ ์ด๋์ ์ด๋ป๊ฒ ๋ฐฐ์นํ ์ง์ ๋ํ ์ ๋ต์ ์ธ์์ผ ํ๋๋ฐ ์ด๋ฅผ, ์บ์ฑ ์ ๋ต(Caching Strategies)์ด๋ผ๊ณ ํ๋ค.
์บ์ฑ ์ ๋ต์ ๋ฐ์ดํฐ์ ์ ํ๊ณผ ํด๋น ๋ฐ์ดํฐ์ ๋ํ ์ก์ธ์ค ํจํด์ ์ ๊ณ ๋ คํด์ ์ ํํด์ผ ํ๋ค. ํฌ๊ฒ ์ฝ๊ธฐ ์ ๋ต๊ณผ ์ฐ๊ธฐ ์ ๋ต์ผ๋ก ๋ ๊ฐ์ง๋ก ๋๋๋ค.
๋จผ์ ์ฝ๊ธฐ ์ ๋ต๋ถํฐ ์์๋ณด์.
์ฝ๊ธฐ ์ ๋ต (Read Strategies)
Look-aside (Lazy Loading) ์ ๋ต : ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ์์ ์ด ๋ง์ ๋ ์ฌ์ฉํ๋ ์ ๋ต์ด๋ฉฐ, ๋ ๋์ค๋ฅผ ์บ์๋ก ์ธ๋ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ค.
๋จผ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ฐ์ดํฐ๋ฅผ ์ฝ์๋, ์บ์๋ฅผ ํ์ธํ์ฌ ์บ์์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋ฉด ์บ์์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์จ๋ค. ๋ง์ฝ ๋ ๋์ค์ ์ฐพ๋ ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด DB์ ์ ๊ทผํด์ ๋ฐ์ดํฐ๋ฅผ ์ง์ ๊ฐ์ ธ์ ๋ ๋์ค์ ์ ์ฅํ๋ค.
๋ฐ๋ผ์, ์บ์์๋ ์ฐพ๋ ๋ฐ์ดํฐ๊ฐ ์์ ๋๋ง ๋ฐ์ดํฐ๊ฐ ์บ์ฑ๋๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์ง์ฐ๋ก๋ฉ(Lazy Loading)์ด๋ผ๊ณ ๋ ๋ถ๋ฅธ๋ค. ์ด ๊ตฌ์กฐ๋ ๋ ๋์ค ์ฅ์ ๋ฐ์ ์ ์์คํ ์ด ๋ค์ด๋์ง ์๊ณ , DB์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์ฌ ์ ์๋ค.
๋์ ์บ์๋ก ๋ถ์ด์๋ ์ปค๋ฅ์ ์ด ๋ง์ด ์์๋ค๋ฉด ๊ทธ ์ปค๋ฅ์ ์ด ๋ชจ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ๋ถ๊ธฐ ๋๋ฌธ์ DB์ ๋ง์ ํธ๋ํฝ์ด ํ๊บผ๋ฒ์ ๋ชฐ๋ฆด ์ ์๋ค.
Look-aside ์ ๋ฌธ์ ์ ์ CUD'์ฐ์ฐ์ ํ๋ ๊ฒฝ์ฐ, DB์ Cache data ์ฌ์ด์ ์ ํฉ์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค๋ ๊ฒ์ด๋ค. DB์๋ ๋ณ๊ฒฝ๋์์ง๋ง Cache Data์์ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฒฝ์ฐ๋ฅผ ๋งํ๋ค.
์ด ๋ฌธ์ ๋ ์บ์์๋ฐ(Cache Warming)์ผ๋ก ํด๊ฒฐ ๊ฐ๋ฅํ๋ค.
์บ์์๋ฐ(Cache Warming) ์ด๋?
๋ฏธ๋ฆฌ cache๋ก db์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ด ๋ฃ์ด๋๋ ์์ ์ ์๋ฏธํ๋ค. ์ด ์์ ์ ์ํํ์ง ์์ผ๋ฉด ์๋น์ค ์ด๊ธฐ์ ํธ๋ํฝ ๊ธ์ฆ์ ๋๋์ cache miss ๊ฐ ๋ฐ์ํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ถํ๊ฐ ๊ธ์ฆ ํ ์ ์๋ค.
์ฐ๊ธฐ ์ ๋ต (Write Strategies)
์ฐ๊ธฐ ์ ๋ต์๋ 2๊ฐ์ง ์ข ๋ฅ๊ฐ ์๋ค.
Write-around : DB์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ Cache miss๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ DB์์ ๋ฐ์ดํฐ๋ฅผ ์บ์ฑํ๋ค. ์ด ๊ฒฝ์ฐ์ cache ๋ด์ ๋ฐ์ดํฐ์ DB ๋ด์ ๋ฐ์ดํฐ๊ฐ ๋ค๋ฅผ ์ ์๋ค.
์๋ํ๋ฉด, ์บ์ฑ๋ ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฅผ ์์ ํ ๋ ์บ์ฑ๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ์ง ์๊ณ , ์บ์์ ๋ฐ์ดํฐ๋ ์๊ธฐ ๋๋ฌธ์ ์๋ก ์บ์ฑ์ ํ์ง ์๋๋ค.
Write-through : DB์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ cache์๋ ํจ๊ป ์ ์ฅํ๋ ๋ฐฉ๋ฒ์ด๋ค. cache๋ ํญ์ ์ต์ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ ์ฅ์ ์ด ์์ง๋ง ์ ์ฅํ ๋๋ง๋ค ๋ ๋จ๊ณ(DB์ ์ ์ฅ, ์บ์์ ์ ์ฅ) ๊ฑฐ์ณ์ผ ํ๊ธฐ ๋๋ฌธ์ ์๋์ ์ผ๋ก ๋๋ฆฌ๋ค.
๊ทธ๋ฆฌ๊ณ ์ฌ์ฌ์ฉ๋์ง ์๋ ๋ฐ์ดํฐ๋ ๋ฌด์กฐ๊ฑด ์บ์์ ๋ฃ์ด๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ผ์ข ์ ๋ฆฌ์์ค ๋ญ๋น๋ฅผ ์ด๋ ํ ์ ์๋ค. ์ด ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋๋ Expire time์ ์ค์ ํด์ฃผ๋ ๊ฒ์ด ์ข๋ค.
Redis๋ฅผ ์ ํํ ์ด์
1. ์ฌ์ฉ์ด ๊ฐํธํ๋ค.
- ๋จ์ํ key-value ๊ตฌ์กฐ ๋ค์ํ ์๋ฃ๊ตฌ์กฐ ์ง์
2. ๋น ๋ฅธ ์ฑ๋ฅ์ ๋ณด์ฌ์ค.
- ํ๊ท ์์ ์๋ < 1 ms
- ์ด๋น ์๋ฐฑ๋ง ๊ฑด์ ์์ ๊ฐ๋ฅ ⇒ ์ง์ฐ์๊ฐ ๊ฐ์, ์ฒ๋ฆฌ๋ ์ฆ๊ฐ
3. ๋ ํผ๋ฐ์ค ์๋ฃ๊ฐ ๋ง์.
- Spring Cache, Caffeine ๋ฑ ๋ค๋ฅธ ์บ์ฑ ๊ตฌํ ๋ฐฉ๋ฒ์ด ์์ง๋ง Redis ๊ด๋ จ ์๋ฃ๊ฐ ์๋์ ์ผ๋ก ๋ง์
4. ์๊ฒฉ ์บ์
- ์ฌ๋ฌ ๋ ธ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ ์ ์์ด ์ผ๊ด๋ ์ ๋ณด๋ฅผ ์ ๊ณตํ๊ณ ํ์ฅ์ฑ์ด ์ข์
Redis ์บ์ ํ์ฑํ๋ฅผ ์ํ ์ด๋ ธํ ์ด์
- @EnableCaching
- SpringBoot์๊ฒ ์บ์ฑ๊ธฐ๋ฅ์ด ํ์ํ๋ค๊ณ ์ ๋ฌ
- SpringBoot Starter class์ ์ ์ฉ
- @Cacheable
- DB์์ ์ ํ๋ฆฌ์ผ์ด์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ Cache์ ์ ์ฅํ๋๋ฐ ์ฌ์ฉ
- DB์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฉ์๋์ ์ ์ฉ
- @CachePut
- DB์ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๊ฐ ์์ ๋ Redis Cache์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธ
- DB์์ PUT/PATCH์ ๊ฐ์ ์ ๋ฐ์ดํธ์์ ์ฌ์ฉ
- @CacheEvict
- DB์ ๋ฐ์ดํฐ ์ญ์ ๊ฐ ์์ ๋ Redis Cache์ ๋ฐ์ดํฐ๋ฅผ ์ญ์
- DB์์ DELETE์ ๊ฐ์ ์ญ์ ์์ ์ฌ์ฉ
์ด์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด์.
๋ณธ ์์๋ Redis๊ฐ ์ค์น๋ ํ๊ฒฝ์ ๊ฐ์ ํ์ฌ ์งํํฉ๋๋ค.
๋ค๋ฅธ ๋ก์ง์ ์บ์ฑ์ฒ๋ฆฌ๋ ์งํํ ๊ฑฐ์ง๋ง ๊ฐ์ฅ ๋จผ์ ํ๊ณ ์ถ์๋ ๋ถ๋ถ์ด ์๋ค.
๋ฐ๋ก ์ด ๋ถ๋ถ์ด๋ค.
token์ ํค๋์ ํฌํจํ์ฌ ์์ฒญ์ด ์ค๋ ๊ฒฝ์ฐ ํญ์ jwt filter๋ฅผ ํ๊ฒ๋๋๋ฐ ์ด๋ member ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค PrincipalDetails๋ฅผ ๋ง๋ค์ด SecurityContextHolder์ ๋ฃ์ด์ค๋ค.
ํ๋ก์ ํธ ํน์ฑ์ 90% ์ด์์ api๊ฐ ํค๋์ token์ ํ์๋ก ํ๊ธฐ ๋๋ฌธ์ ์ฌ์ฉ์๊ฐ ๋ง์ด์ง ์ ์ฑ๋ฅ ๊ฐ์ ์ด ๊ฝค๋ ์ด๋ค์ง ๊ฒ์ผ๋ก ์ง์๋๋ค.
์ฌ์ฉ๋ฒ์ ์ ๋ง ๊ฐ๋จํ๋ค.
๋จผ์ RedisConfig ํ์ผ์ cacheManager๋ฅผ ๋ฑ๋กํด์ฃผ์.
// ์บ์ฑ ์ฒ๋ฆฌ๋ฅผ ์ํ ๋น ๋ฑ๋ก
@Bean
public CacheManager authCacheManager(RedisConnectionFactory cf) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) // Value Serializer ๋ณ๊ฒฝ
.entryTtl(Duration.ofMinutes(30L)); // ์บ์ ์๋ช
30๋ถ
return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(cf).cacheDefaults(redisCacheConfiguration).build();
}
entryTtl ๋ถ๋ถ์ ์บ์๋ฅผ ์ผ๋ง๋์ ๊ฐ๊ณ ์์ ๊ฒ์ธ์ง ์ค์ ํด์ฃผ๋ฉด ๋๋ค. ์ฐ์ ์ 30๋ถ์ผ๋ก ์ก์๋๊ณ ์งํํ๋ค.
๋ @EnableCaching์ ๋ฑ๋กํด์ค์ผ Cache๋ฅผ ์ฌ์ฉํ ์ ์๋ค. ๋๋ RedisConfig์ ๋ฑ๋กํด์ฃผ์๋ค.
loadUserByUsername ๋ฉ์๋ ์์ @Cacheable ์ด๋ ธํ ์ด์ ์ ์ ์ฉํด์ค๋ค.
cacheManager๋ RedisConfig์์ ๋ฑ๋กํ๋ ๋น ์ด๋ฆ์ด๋ค.
cacheNames๋ฅผ loginMember๋ก ์ก์๊ณ key๋ฅผ phone์ผ๋ก ์ก์๊ธฐ ๋๋ฌธ์ phone์ ๊ฐ์ด 01012345678 ์ด์๋ค๋ฉด redis์ loginMember::01012345678 ๋ก key๊ฐ์ด ์ ์ฅ๋๋ค.
๋์ค์ redis-cli ์์ ํ์ธํด๋ณผ ๊ฒ์ด๋ค.
@Override
@Cacheable(cacheNames = "loginMember", key = "#phone", condition = "#phone != null", cacheManager = "authCacheManager")
public PrincipalDetails loadUserByUsername(String phone) throws UsernameNotFoundException {
log.info("loadUserByUsername ์คํ");
Member findMember = memberRepository.findByPhone(phone)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
MemberDto memberDto = MemberDto.builder()
.id(findMember.getId())
.role(findMember.getRole())
.build();
return new PrincipalDetails(memberDto);
}
Redis ์บ์๋ฅผ ์ ์ฉํ๊ณ ์ฒ์ token ์กฐํ๊ฐ ํฌํจ๋๋ api ์์ฒญ์ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ด member ์กฐํ ๋ก์ง์ด ๋๊ฐ๋ค. ์ฆ, redis์ ์บ์ฑ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์์ cache miss๊ฐ ์ผ์ด๋ ๊ฒ์ด๋ค. ๋์์ redis์ ๋ฑ๋กํด์ค๋ค.
์กฐ๊ธ ์ ์ ๋ก๊ทธ์ธํ ์ ์ ๋ก ์ธ์ฆ์ด ํ์๋กํ๋ api ์์ฒญ์ ํด๋ณด๋ฉด? ๋ณ๋์ ์ฟผ๋ฆฌ ์์ด ์ธ์ฆ์ ์๋ฃํ๋ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
redis์ ์ด๋ป๊ฒ ์ ์ฅ๋์ด ์์๊น?
{cacheNames::key} ๊ฐ ํํ๋ก ์ ์ ์ฅ๋์ด ์๋ค.
get ์ผ๋ก ์กฐํํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ ์ ์ฅ๋์ด ์๋๊ฒ์ ํ์ธํ ์ ์๋ค.
์ฌ๊ธฐ์ ๊ถ๊ธํ ์ ์ด ์๊ฒผ๋ค.
์๋ ์ฝ๋ ์ฒ๋ผ ๋ง์ ๋น์ฆ๋์ค ๋ก์ง์์ ํ์ฌ ๋ก๊ทธ์ธํ memberId๋ฅผ ๋ฐ์์ member๋ฅผ ์กฐํํ๊ณ ์๋ค.
์ด ๋ถ๋ถ๋ member ์กฐํ ๋ก์ง๋ Redis๋ก ์บ์ฑ์ฒ๋ฆฌ ํ๋ฉด ์ ๋๋.. ์๊ฐ์ด ๋ค์๋ค.
ํ์ง๋ง Redis๋ก member๋ฅผ ์กฐํ ์ ์์์ฑ ์ปจํ ์คํธ์์ ๋ค์ด๊ฐ์ง ์๋ ๋ฌธ์ ๊ฐ ์๋ค.
๋ ์๋ ์ฌ์ง ์ฒ๋ผ ์ํฐํฐ๋ฅผ ์ธ๋ถ ์บ์์ ์ ์ฅํ๋ฉด ์ ๋!! ์๋๋ค๊ณ ํ๋ค..!
๋ฒ์ธ
๋ฒ์ธ๋ก ๋ค๋ฅธ ๊ฐ๋ฐ์ ๋ถ๋ค๊ณผ ์๊ธฐํ๋ค ์๋ฌธ์ธ ์ ์ด ์๊ฒผ๋ค.
JWT๋ฅผ ์ฌ์ฉํ์ฌ ์ธ์ฆ,์ธ๊ฐ๋ฅผ ์ฒ๋ฆฌํ ๊ฒฝ์ฐ jwt filter์์ loadUserByUsername ๊ฐ์ ํ์ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ ค ํ์ธํด์ผ ํ๋๊ฐ?? ํ์ ์๋๊ฐ?? ์ ๋ํด ๊ณ ๋ฏผํ๊ฒ ๋์๋ค.
๋๋ ๋ก๊ทธ์ธ์ด ๋์ด ํ ํฐ์ ์ด๋ฏธ ๋ฐ๊ธํ ์ํฉ์ด๋๋ผ๋ ์ด๋ฏธ ํ์์ด ํํดํ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ DB์ ์๋ ํ์์ ๋ํ ํ ํฐ์ธ์ง ๊ฒ์ฆํ๋ ๋ก์ง์ ํ์ํ๋ค ์๊ฐํ๋๋ฐ..
์กฐ๊ธ ๋ ์์๋ด์ผ๊ฒ ๋ค.
์ฐธ๊ณ : https://www.youtube.com/watch?v=92NizoBL4uA
'Spring Boot, JAVA ๐ฑ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Event] Spring Event๋? ์ด๋ฒคํธ ๋ฐํ๊ณผ ๊ตฌ๋ ๋ฐฉ๋ฒ (0) | 2024.02.21 |
---|---|
[Redis] Redis๋ก ์ต๊ทผ ๊ฒ์ ๊ธฐ๋ก ๊ด๋ฆฌํ๊ธฐ (0) | 2024.02.02 |
[Spring] AOP ๊ฐ๋ ๋ฐ ์ ์ฉํ๊ธฐ (1) | 2024.01.06 |
๋ฉํฐ ์ค๋ ๋์ ๋จ์ผ ์ค๋ ๋, ๋๊ธฐ์ ๋น๋๊ธฐ ์ ๋๋ก ์๊ณ ์ฐ์๋์? (feat. ์ฑ๋ฅ ๊ฐ์ ) (2) | 2024.01.02 |
[HttpSession] session์ ๋์ ์๋ฆฌ ์ดํด๋ณด๊ธฐ (0) | 2023.12.30 |