반응형
고민
- 이미 RedisTemplate를 많이 쓰고 있는 와중에 특정 spring profile에서만 prefix를 붙이는 니즈가 생겼다.
- cacheManager에서는 prefix를 지원하지만 cacheManager를 사용하고 있는 상황도 아니었고 모든걸 찾아 바꾸기에는 다른작업자분들의 내용이 있어 쉽지 않았다.
결론
- 정식으로 지원되는 메소드는 찾을 수 없었다.
- redisTemplate의 keySerializer 메소드로 해결할 수 있엇다.
접근방법
RedisConfig에서 RedisTemplate를 정의할때, setKeySerializer를 커스텀하게 만들어준다.
@Configuration public class RedisConfig { @Autowired private PrefixedStringKeySerializer prefixedStringKeySerializer; @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate(); ... 중략 ... redisTemplate.setKeySerializer(prefixedStringKeySerializer); return redisTemplate; }
PrefixedStringKeySerializer는 StringRedisSerializer를 상속한다.
env에서 active profile을 파악하고 타겟한 profile(코드 중 TARGET_ACTIVE_PROFILE)이 있을때는 prefix(코드 중 KEY_PREFIX)를 key에 더해서 serialize가 진행되도록 넘겨준다.
@Component public class PrefixedStringKeySerializer extends StringRedisSerializer { private static final Logger log = LoggerFactory.getLogger(PrefixedStringKeySerializer.class); @Autowired private Environment env; @Override public byte[] serialize(@Nullable String string) { try { Optional<String> opStageProfile = Stream.of(env.getActiveProfiles()) .filter(profile -> StringUtils.equals(profile, TARGET_ACTIVE_PROFILE)) .findAny(); if (opStageProfile.isPresent()) { return super.serialize(KEY_PREFIX + string); } } catch (Exception e) { log.error("[PREFIXED_STRING_KEY_SERIALIZER] failed to find active profile", e); } return super.serialize(string); } }
spring-data-redis에 관련된 내용만 테스트하니 @DataRedisTest를 사용해준다.
TARGET_ACTIVE_PROFILE에서만 실행되도록 @ActiveProfiles를 이용해준다.
위의 설정으로 테스트할 수 있게 IMPORT
@RunWith(SpringRunner.class) @DataRedisTest @Import({RedisConfig.class, PrefixedStringKeySerializer.class}) @ActiveProfiles(TARGET_ACTIVE_PROFILE) public class RedisConfigStageTest { private final String redisKey= "stagePrefixTestKey" + LocalDateTime.now().toLocalTime(); @Autowired private RedisTemplate redisTemplate; @Test public void stage_prefix적용_테스트() { //when redisTemplate.opsForValue().set(redisKey, "1"); String result = String.valueOf(redisTemplate.opsForValue().get(redisKey)); Set<String> stageNamedKeySet = redisTemplate.keys(redisKey); String storedKeyName = stageNamedKeySet.stream().findFirst().orElseThrow(() -> new RuntimeException()); //then assertThat(result).isEqualTo("1"); assertThat(storedKeyName).isEqualTo(KEY_PREFIX + redisKey); } @After public void teardown() { redisTemplate.delete(redisKey); } }
테스트 작성중 재밌었던 부분은 확인하는 과정이다. 모든 키가 자동으로 prefix가 붙어서 실제로 잘 들어갔는지 테스트가 난감했었는데 redisTemplate.keys(-) 메소드를 통해서 실제 등록된 키를 가져와서 비교해볼 수 있었다.
'새로운 로직접근' 카테고리의 다른 글
.findout(java와 mysql에서 emoji 길이 통일시키기) (0) | 2020.12.22 |
---|---|
.findout(Redis를 이용해 CyclicBarrier만들어보기) (0) | 2020.12.21 |
.findout(react에서 spring으로 배열 파라미터 넘기기) (0) | 2020.12.20 |