본문 바로가기

트러블 슈팅

spring에서 cache 활용 시 key 값 설정 주의점

문제 정의

spring boot와 redis를 활용해 cache 저장소를 구현하려고 할 때 발생했던 문제입니다. 

 

@Cacheable(cacheNames = "itemCache", key = "args[0]")
    public ItemDto readOne(Long id) {
        log.info("Read One: {}", id);
        return itemRepository.findById(id)
                .map(ItemDto::fromEntity)
                .orElseThrow(() ->
                        new ResponseStatusException(HttpStatus.NOT_FOUND));
    }

    @Cacheable(cacheNames = "itemAllCache", key = "methodName")
    public List<ItemDto> readAll() {
        return itemRepository.findAll()
                .stream()
                .map(ItemDto::fromEntity)
                .toList();
    }

    @CachePut(cacheNames = "itemCache", key = "#result.id")
    public ItemDto create(ItemDto dto) {
        return ItemDto.fromEntity(itemRepository.save(Item.builder()
                .name(dto.getName())
                .description(dto.getDescription())
                .price(dto.getPrice())
                .build()));
    }

코드를 보시게 되면 어떤 곳에서는 key에 args, methodName, #result.id를 사용하고 있는데요. 주의할 점이 key값에 #result를 사용한다면 메서드가 반환하기 전에 캐시가 설정되므로, 만약 메서드가 예외를 발생시키거나 반환값이 null이라면 캐시 키가 예상과 다르게 설정되거나 NullPointException이 발생할 수 있게 됩니다. 

 

해결 과정

 이 부분은 args 등을 사용해서 해결하면 되지만 위에서 언급했듯이 반환값이 없으면 null이 들어갈 수도 있겠구나..라는 생각을 미리 머리속에 담아두는 것이 앞으로는 필요할 것 같습니다.