[기타] 데이터 조회 성능 향상시키기 2편

KIM Jongwan·7일 전
0
post-thumbnail

이전 포스트에서 Index를 적용하여 데이터 조회 성능을 향상시키는 방법에 대하여 알아보았습니다. 이번 포스트에서는 Redis in-memory cache를 적용하여 조회 성능을 향상시키는 방법에 대해 알아보겠습니다.

Index 적용의 한계

데이터베이스의 Index는 데이터 조회 성능을 향상시키기 위해 추가적인 색인 자료구조를 생성하는 방식입니다. 때문에 읽기의 성능을 향상될 수 있으나 쓰기 작업에 대하여는 데이터 이외 색인 쓰기 작업이 추가로 발생하기 때문에 성능 저하가 발생할 수 있습니다. 또한 컴퓨팅 자원 증설의 한계로 일정 시점 이상으로 성능 향상을 기대할 수 없다는 단점이 있습니다.

(출처:데이터베이스 배움터)

in-memory cache

위와 같이 Index로는 더이상 효과를 보기 어려운 상황이거나 추가적으로 조회 성능에 개선이 필요한 시점이 오게 될 경우, in-memory cache의 도입을 검토해 볼 수 있겠습니다. 컴퓨터의 연산 작업은 일반적으로 아래와 같은 절차를 거치게됩니다.

비지니스 로직 실행 -> 연산 장치(CPU)의 데이터 요청 -> 주 기억장치 (memory) -> 보조 기억장치(SSD, HDD 등) -> 연산 장치 데이터 전송 -> 결과 반환

이 과정에서 연산 장치가 필요로 하는 데이터가 주기억장치에 존재한다면 보조 기억장치로의 데이터 요청 작업이 생략되고 연산이 수행되며 결과를 반환하게 됩니다. 하지만 주기억장치에 데이터가 존재하지 않을 경우 이를 보조기억장치에 요청하게되고 주기억장치와 보조기억장치간의 데이터 교환 비용이 발생하게 됩니다.(연산 과정에서 가장 많은 비용 발생)

in-memory cache는 연산에 필요한 데이터 혹은 연산의 결과값을 주기억장치에 저장하여 보조 기억장치로의 데이터 요청 작업을 생략할 수 있게 도와줍니다.

주로 사용되는 in-memory cache에는 Ehcache, Redis, Memcached등이 있습니다.


Redis

in-memory cache의 종류

Spring framework을 사용하고 있다면 간단하게 적용 가능한 Ehcache가 유효한 선택지가 될 수 있습니다. (이동욱 개발자님의 ehcache 예제 포스팅) 다만 프레임워크 라이브러리로 제공되는 기능이다보니 cli를 활용한 데이터 조회나 외부 서비스 연동에 어려움이 있습니다. 하여 이번 포스팅에서는 범용적으로 사용 가능한 Redis를 예로 들어 작성해보겠습니다.

Redis 설치 (macOS)

맥 PC의 경우 brew 패키지 관리자를 사용하면 간단하게 Redis를 설치할 수 있습니다.
터미널을 실행 후 brew install redis 명령어를 입력하면 Redis가 설치됩니다. (설치 완료 후 redis-server --version로 확인할 수 있습니다.)

설치가 완료되었다면 redis를 실행해보겠습니다.
현재는 foregraund로 실행된 상태이기때문에 터미널을 종료하면 redis도 함께 종료가 됩니다. brew의 프로세스 관리 명령어를 사용하여 background로 실행 하는 방법을 알아보겠습니다.

redis가 background모드로 실행되고있는 것을 확인할 수 있습니다. (프로세스 종료 명령어 brew services stop redis) Redis가 실행중이라면 cli를 활용하여 접속할 수 있습니다.

redis는 기본적으로 6379번 port에서 실행됩니다.


Spring project 연동

앞서 Redis를 설치하고 실행하는 방법에 대해 알아보았습니다. 이제 실행된 Redis를 Spring boot 프로젝트와 연동하여 데이터를 등록하거나 조회, 수정하는 방법을 알아보겠습니다.

프로젝트 환경

  • OS: macOS
  • JDK: openJDK 17
  • Spring version: spring boot 3.x
  • Database: H2 database

spring-boot redis 환경 설정

spring boot와 redis를 연동하기 위해 build.gradle > dependencies에
implementation 'org.springframework.boot:spring-boot-starter-data-redis' 를 추가하였습니다.

다음으로 application.yml(application.properties)에 연결할 redis의 port와 host를 명시해주겠습니다.
로컬 환경에서의 연동 테스를 위한 프로젝트이기 때문에 접속 password는 설정하지않았습니다.(상용 환경에서이 도입을 원할 경우 반드시 password를 설정해주세요.)

RedisConfig.class

다음으로 redis bean 생성을 위한 class 파일을 추가해보겠습니다.

@Configuration
public class RedisConfig {

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

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

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

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());

        return redisTemplate;
    }

}

java에서 제공하는 Redis client에는 Jedis와 Lettuce 두 종류가 있습니다. 저는 Lettuce를 선택하여 사용하도록 하겠습니다.(이동욱 개발자님의 Jedis 보다 Lettuce 를 쓰자)

Redis test

Redis client를 사용하여 데이터를 입력 / 조회하는 테스트 코드를 작성해보겠습니다.

@SpringBootTest
public class RedisServiceTest {

    @Autowired
    private StringRedisTemplate redisTemplate;


    @Test
    @Transactional
    public void redis_key_insert_test(){
        String key = "test-redis-key-01";
        String value = "test-redis-value-01";

        final ValueOperations<String, String> stringStringValueOperations = redisTemplate.opsForValue();
        stringStringValueOperations.set(key, value);

        String redisValue = redisTemplate.opsForValue().get(key);

        Assertions.assertEquals(value, redisValue);
    }
}

"test-redis-key-01":"test-redis-value-01"과 같이 key:value를 입력하고 입력된 데이터를 key값으로 조회하여 일치 여부를 검증하는 테스트 코드입니다.

테스트가 정상적으로 실행되었습니다. 이제 redis-cli로 실제 입력된 데이터를 확인해보겠습니다.

테스트 코드를 통하여 입력하였던 key:value가 등록되어있습니다.


마무리

실제 조회 로직에 redis를 적용하기 위해서는 @CachePut, @Cacheable, @CacheEvict을 사용하여 캐싱 전략을 결정하여야합니다. 이번 포스팅에서는 기본적인 Redis의 설치와 사용법을 알아보았다면, 다음 포스팅에서는 실제 데이터를 조회하고 변경된 데이터에 대하여 캐시를 갱신하는 등의 작업과 redis적용 이전과 이후의 성능 차이를 비교해보도록 하겠습니다.

profile
3년차 백앤드 개발자입니다.

0개의 댓글