콘텐츠로 이동

2022 10 03

2022-10-03

Spring Boot Data Redis

  • StringRedisTemplate

    • 레디스 key-value 문자열 위주라서 문자열에 특화된 템플릿
      • String-focused extension of RedisTemplate
    • RedisTemplate을 상속받음
      public class StringRedisTemplate extends RedisTemplate<String, String> {
      }
      
    • 일반적인 String 값을 Key-Value로 사용하는 경우 사용하면 됨
  • 사용법
    • RedisTemplate / StringRedisTemplate을 호출하여 사용
    • redisTemplate에는 redis가 제공하는 list/set/sortedSet/hash 등과 같은 다양한 Command 지원
      • opsFor* method를 통해 작업
    • opsForValue() - ValueOperations
    • opsForHash() - HashOperations
    • opsForList() - ListOperations
    • opsForSet() - SetOperations
    • ...
  • ValueOperation이 뭐야?
    • 레디스를 그냥 통으로 아주 큰 해시 맵으로 보는 것
    • Simple Value에 대한 연산 결과를 반환

Thread.sleep() Noncompliant Code vs Compliant Code

  • Noncompliant Code - SonarLint가 얘기하는 해로움
    @Test
    void testDoTheThing() {
        MyClass myClass = new MyClass();
        myClass.doTheThing();
    
        Thread.sleep(500); // Noncompliant
        // assertions
    }
    
  • Compliant Code - SonarLint가 추천하는 코드
    @Test
    public void testDoTheThing(){
          MyClass myClass = new MyClass();
          myClass.doTheThing();
    
          await().atMost(2, Duration.SECONDS).until(didTheThing());  // Compliant
          // assertions...
    }
    
    private Callable<Boolean> didTheThing() {     
        return new Callable<Boolean>() {
            public Boolean call() throws Exception {
                // check the condition that must be fulfilled...
            }
        };
    }
    

Awaitility

  • Awaitility를 활용한 테스트

    • 참고: http://awaitility.org
    • Polling 방식을 활용하여 Condition이 매칭되는지 확인 (이게 쓰레드 컨텍스트 스위칭보다 저렴한가보네)
    • 아래와 같이 await()를 활용하여, 해당 시간 안에 데이터가 null로 조회되면 (그니까 조건이 true)가 되면 테스트 통과
      @DisplayName("레디스에 데이터를 만료 시간을 정하여 조회할 수 있다.")
      @Test
      void setDataExpire() {
          // given
          String key = "key";
          String value = "value";
          redisRepository.setDataExpire(key, value, 1);
      
          // when & then
          String dataRightAfter = redisRepository.getData(key);
          assertThat(dataRightAfter).isEqualTo(value);
      
          await().atMost(1, TimeUnit.SECONDS).until(() -> {
              return (redisRepository.getData(key) == null);
          });
      }
      
    • 만약 1초 지날때까지 데이터가 expire가 안되어있다면, 아래와 같은 메시지를 뿜으며 fail
      • org.awaitility.core.ConditionTimeoutException: Condition with lambda expression in com.backend.connectable.global.redis.RedisRepositoryTest was not fulfilled within 1 seconds.