๋ง๋์ฐ๐ ย ๋ํ ์บ์ ์์คํ ๊ตฌ์ถํ๊ธฐ
๋์ ๋ฐฐ๊ฒฝ
๋ง๋์ฐ๐
์ย ์์ด ๋ง์ถคํ ๋ํ๋ฅผ ์์ฑํ๊ณ , ์์ด์๊ฒ ๋ํ๋ฅผ ๋ค๋ ค์ฃผ๋ฉฐ ์ง์ ์ํธ์์ฉํ ์ ์๋ ์ ์ฉ ์ธํ ๋๋ฐ์ด์ค๋ฅผ ์ ๊ณตํ๋ ์๋น์ค์ด๋ค.
์ฒ์ AI๊ฐ ์์ด์ ๋์ด, ์ธ์ด, ์ฃผ์ด์ง ํ๋กฌํํธ์ ๋ง๊ฒ ๋ํ๋ฅผ ์์ฑํด์ ์ ๊ณตํ๋ฉด ๊ทธ ์ดํ์ ์ ์ ๋ค์ ์์ฑ๋ ๋ํ๋ฅผ ๊ณต์ ํ๊ฑฐ๋ ์กฐํํ ์ ์๋ค.
์ด๋ ๋ฏ, ๋ํ๊ฐ ์ฌ์ฉ์ ๋ง์ถคํ์ผ๋ก AI์ ์ํด ์์ฑ๋๊ธฐ ๋๋ฌธ์ ์ฒ์ ์์ฑ ์ดํ, ์์ & ์ญ์ ์์ฒญ์ด ๋งค์ฐ ์ ๊ณ ์กฐํ ์์ฒญ์ด ๋ง์ ๊ฒ์ด๋ผ๋ ์ ์ ์ ์ ์์๋ค.
๋ํ ์ธ๊ธฐ ๋ํ, ์ต๊ทผ ์์ฑ๋ ๋ํ ๋ฆฌ์คํธ ๋ฑ์ ์ ๊ณตํ๋ฉด์ ํน์ ๋ํ๋ก์ ์กฐํ๊ฐ ๋ชฐ๋ฆด ์ ์์ ๊ฒ์ด๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
์ด์ ๋ํ ์บ์ ์์คํ ๋์ ์ ๊ฒฐ์ ํ๊ฒ ๋์๋ค.
์บ์๋?
๋ณธ๊ฒฉ์ ์ผ๋ก ์บ์ ์์คํ ์ ๊ตฌ์ถํ๊ธฐ์ ์์ ๋จผ์ ์บ์๋ ๋ฌด์์ธ์ง์ ๋ํด์ ๊ฐ๋ตํ๊ฒ ์ดํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
์บ์๋ ๋ฌด์์ผ๊น?
์ปดํจํฐ ๊ณผํ์์ ๋ฐ์ดํฐ๋ ๊ฐ์ ๋ฏธ๋ฆฌ ๋ณต์ฌํด ๋๋ ์์ ์ฅ์
์บ์๋ย ์ปดํจํฐ ๊ณผํ์์ ๋ฐ์ดํฐ๋ ๊ฐ์ ๋ฏธ๋ฆฌ ๋ณต์ฌํด ๋๋ ์์ ์ฅ์๋ฅผ ๊ฐ๋ฆฌํค๋ฉฐ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ฒฝ์ฐ๋ ๊ฐ์ ๋ค์ ๊ณ์ฐํ๋ ์๊ฐ์ ์ ์ฝํ๊ณ ์ถ์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
๋ํ ์บ์์ ์ข ๋ฅ๋ก๋ CPU ์บ์, ์น ์บ์, ๋ธ๋ผ์ฐ์ ์บ์, ์ดํ๋ฆฌ์ผ์ด์ ์บ์ ๋ฑ๋ฑ ์ฌ๋ฌ ์ข ๋ฅ๊ฐ ์์ผ๋ฉฐ ์ปดํจํฐ ๊ณผํ ์ ๋ฐ์์ ์บ์๊ฐ ์ฌ์ฉ๋๊ณ ์๋ค๊ณ ํด๋ ๊ณผ์ธ์ด ์๋๋ค.
์ด๋ ์บ์๊ฐ ํจ์จ์ ์ผ๋ก ๋์ํ๋ ค๋ฉด ์บ์์ ์ ์ฅํ ๋ฐ์ดํฐ๊ฐ ์ง์ญ์ฑ์ ๊ฐ์ ธ์ผ ํ๋ค.
- ์๊ฐ์ ์ง์ญ์ฑ
- ํน์ ๋ฐ์ดํฐ๊ฐ ํ๋ฒ ์ ๊ทผ๋์์ ๊ฒฝ์ฐ, ๊ฐ๊น์ด ๋ฏธ๋์ ๋ ํ๋ฒ ๋ฐ์ดํฐ์ ์ ๊ทผํ ๊ฐ๋ฅ์ฑ์ด ๋์ ๊ฒ
- ๊ณต๊ฐ์ ์ง์ญ์ฑ
- ํน์ ๋ฐ์ดํฐ์ ๊ฐ๊น์ด ์ฃผ์๊ฐ ์์๋๋ก ์ ๊ทผ๋์์ ๊ฒฝ์ฐ
๋ํ ์บ์ ์์คํ ์ ๊ตฌ์ถํ๋๋ฐ์๋ ๋ค์ํ ์ ๋ต์ด ์์ ์ ์๋ค.
์ฝ๊ธฐ ์ ๋ต โ Look Aside ์ ๋ต
์ฝ๊ธฐ ์ ๋ต โ Read Through ์ ๋ต
์ฐ๊ธฐ ์ ๋ต โ Write Back ์ ๋ต
์ฐ๊ธฐ ์ ๋ต โ Write Through ์ ๋ต
์ฐ๊ธฐ ์ ๋ต โ Write Around ์ ๋ต
Redis๋ฅผ ํ์ฉํ ์บ์ ์์คํ ๊ตฌ์ถํ๊ธฐ
์คํ๋ง์์ ์บ์ ์์คํ ์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์์ง๋ง ๋ณธ ํ๋ก์ ํธ์์๋ ์ต์ํ Redis๋ฅผ ํ์ฉํ์ฌ์ ์งํํด ๋ณด์๋ค.
Cache๋ฅผ ์ฌ์ฉํ๊ธฐ์ ์์ ์ด๋ ํ ์ ๋ต์ผ๋ก ์ ์ฉํ์ฌ ์ฑ๋ฅ์ ๊ฐ์ ํ ์ง ๊ณ ๋ฏผํด๋ณด์์ผ ํ๋๋ฐ, ๋ณธ ํ๋ก์ ํธ์์๋ ์บ์์ ์ฝ๊ธฐ ์ ๋ต์ผ๋ก Read Through ์ ๋ต์, ์ฐ๊ธฐ ์ ๋ต์ผ๋ก๋ Write Through ์ ๋ต์ ์ฌ์ฉํ์๋ค.
RedisConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public CacheManager customCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(15))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(config)
.build();
}
}
๋จผ์ RedisConfig์์ ์บ์์ ๊ด๋ จ๋ ์ค์ ์ ์งํํด์ฃผ์๋ค. ์ฌ๊ธฐ์ TTL, ์บ์ํค์ ์บ์๊ฐ์ ์ง๋ ฌํ ๋ฐฉ์ ๋ฑ ์บ์ฑ ์ ์ฑ ์ ์ค์ ํ ์ ์๋ค.
- entryTtl: ์บ์์ TTL ์ค์
- serializeKeysWith: ์บ์ํค์ ์ง๋ ฌํ ๋ฐฉ์
- serializeValuesWith: ์บ์๊ฐ์ ์ง๋ ฌํ ๋ฐฉ์
MatdongsanServerApplication.java
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableFeignClients
@EnableCaching
public class MatdongsanServerApplication {
public static void main(String[] args) {
SpringApplication.run(MatdongsanServerApplication.class, args);
}
}
๋ค์์ผ๋ก๋ ์๋ฒ๋ฅผ ์คํ์ํค๋ SpringBoot Starter class์ @EnableCaching ์ด๋ ธํ ์ด์ ์ ๋ฃ์ด์ ์บ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋๋ก ํด์ฃผ์๋ค.
StoryCacheService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Service
@RequiredArgsConstructor
public class StoryCacheService {
private final StoryRepository storyRepository;
@Cacheable(value = "stories", key = "#storyId", cacheManager = "customCacheManager")
public Story getStory(String storyId) {
return storyRepository.findByIdOrThrow(storyId);
}
@CachePut(value = "stories", key = "#storyId", cacheManager = "customCacheManager")
public Story updateStory(String storyId, StoryDto.StoryUpdateRequest requestDto) {
return storyRepository.findByIdOrThrow(storyId)
.updateStoryDetail(requestDto);
}
@CachePut(value = "stories", key = "#storyId", cacheManager = "customCacheManager")
public Story likeStory(String storyId) {
return storyRepository.findByIdOrThrow(storyId)
.addLikes();
}
@CachePut(value = "stories", key = "#storyId", cacheManager = "customCacheManager")
public Story unlikeStory(String storyId) {
return storyRepository.findByIdOrThrow(storyId)
.removeLikes();
}
}
์บ์ ํ์ฑํ๋ฅผ ์ํด์ ๋ณ๋๋ก StoryCacheService๋ฅผ ๊ตฌํํ์๊ณ ๋ค๋ฅธ ํด๋์ค์์ ํด๋น ํด๋์ค์ ๋ฉ์๋๋ฅผ ํธ์ถํด ๋ํ์ CRUD ์์ ์ ์ฒ๋ฆฌํ๋๋ก ๊ตฌํํ์๋ค.
์บ์ ์์คํ ๊ตฌ์ถ์๋ ์ ๊ณต๋๋ @Cacheable๊ณผ @CachePut ์ด๋ ธํ ์ด์ ์ ํ์ฉํ์๊ณ , ๋ํ ID๋ฅผ KEY๋ก ๋ํ ๋ด์ฉ์ ์บ์ํ ์ ์๋๋ก ๊ตฌํํ์๋ค.
@Cacheable๊ณผ @CachePut์ ์ญํ ์ ์๋์ ๊ฐ๋ค.
- @Cacheable
- ๋ฉ์๋ ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅํ๊ณ , ์ดํ ๋์ผํ ๋งค๊ฐ๋ณ์๋ก ๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด ์บ์์์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
- ๋ฉ์๋ ์คํ ์ ์ ์บ์๋ฅผ ๋จผ์ ํ์ธ ํ, ์บ์์ ๊ฐ์ด ์์ผ๋ฉด ๋ฉ์๋๋ฅผ ์คํํ ๋ค ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ์ฅ
- @CachePut
- ๋ฉ์๋ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ๋ก ์บ์์ ์ ์ฅ
- ํญ์ ๋ฉ์๋๋ฅผ ์คํํ๋ฉฐ, ๋ฐํ๋ ๊ฒฐ๊ณผ๋ฅผ ์บ์์ ์ ๋ฐ์ดํธ
์บ์๋ฅผ ๋น์ฐ๋๋ฐ ์ฌ์ฉ๋๋ @CacheEvict๋ ์๋๋ฐ ๋ณธ ํ๋ก์ ํธ์์๋ ๋ํ ์ญ์ ๊ธฐ๋ฅ์ ๋ณ๋๋ก ๊ตฌํํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ์ง๋ ์์๋ค.
์ฑ๋ฅ ํ ์คํธ
๊ตฌ์ถํ ์บ์ ์์คํ ์ด ์ด๋ ์ ๋์ ์ฑ๋ฅ์ด ๋์ค๋์ง ๊ฐ๋จํ ์ฑ๋ฅ ํ ์คํธ๋ฅผ ์งํํด๋ณด์๋ค.
ํ ์คํธ์๋ nGrinder๋ฅผ ํ์ฉํ์๊ณ ๋ฏธ๋ฆฌ 1000๊ฐ์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ์์ฑ ํ, ํ๋ ํ ์ ๋ฒ์น์ ๋ฐ๋ฅด๋ ์กฐํ ์์ฒญ์ ๋ณด๋ด๋๋ก ํ์๋ค.
ํ ์คํธ ์๋๋ฆฌ์ค๋ ์๋์ ๊ฐ์ด ๊ตฌ์ฑํ์๋ค.
- Agent: 1๋
- ํ ์คํธ ์ ์ : 1000
- ํ ์คํธ ์๊ฐ: 1๋ถ
- Ramp-Up (์๊ฐ์ ๋ฐ๋ผ ์ฌ์ฉ์ ์ฆ๊ฐ)
์ฑ๋ฅ ํ ์คํธ์ ๊ฒฐ๊ณผ๋ก ์๋์ ๊ฐ์ ์งํ๋ฅผ ํ์ธํ ์ ์์๋ค.
| ย | ์บ์ ์ ์ฉ X | ์บ์ ์ ์ฉ | ์ฑ๋ฅ ๊ฐ์ |
|---|---|---|---|
| TPS | 141.4 | 224.4 | ์ฝ 58.7% ๊ฐ์ |
| Mean Test Time | 1227.27 | 1024.08 | ์ฝ 16.6% ๊ฐ์ |
TPS์ ๊ฒฝ์ฐ ์ฝ 58.7%์ ์ฑ๋ฅ ํฅ์, ํ๊ท ์๋ต ์๊ฐ์ ๊ฒฝ์ฐ ์ฝ 16.6%์ ์ฑ๋ฅ ํฅ์์ ํ์ธํ ์ ์์๋ค.
์๊ฐ๋ณด๋ค๋ ๋ฎ์ ํญ์ ์ฑ๋ฅ ํฅ์์ ํ์ธํ ์ ์์๋๋ฐ ์๋ง ๋ํ ์กฐํ ์์ฒญ์์ ํด๋น ๋ํ์ ์ข์์๋ฅผ ๋๋ ๋์ง ๋ฑ์ ์ ๋ณด๋ ์ด์ฉ ์ ์์ด ๋๋น์์ ๊ฐ์ ธ์์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฐ ๊ฒฐ๊ณผ๊ฐ ๋์๋ ๊ฒ ๊ฐ๋ค.
๋ง์น๋ฉฐ
์ ๋ชฐ๋๋ ์บ์์ ๋ํด์ ํ์ตํ๊ณ ์ง์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๋ฉด์, ๋ด๊ฐ ์ค๊ณํ ์๋ฒ์ ์ฑ๋ฅ ํฅ์์ ๋ํด์ ๊ณ ๋ฏผํ ์ ์์๋ ์ข์ ๊ฒฝํ์ด์๋ค.
ํนํ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์บ์ ๊ฐ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ ์ ๋ต์ ์ค์์ฑ์ ๊นจ๋ฌ์๊ณ , ์ค๋ฌด์์์ ์บ์ ๋์ ์ ์ํด์ ํจ๊ณผ์ ์ธ ์ ๋ต ์๋ฆฝ์ด ํ์ํ ๊ฒ์ด๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
๋ ์ง์ nGrinder๋ฅผ ํตํด์ ํ ์คํธ๋ฅผ ์งํํ๋ฉฐ, ์ฑ๋ฅ ๊ฐ์ ์ฌํญ์ ์์น๋ก ํ์ธํ ์ ์์ด์ ์ข์๋ค.