[Spring Boot] Page/Slice 컨텐츠 변경으로 인한 버그

Loopy·2022년 2월 8일
0

삽질기록

목록 보기
3/28
post-thumbnail

☁️ 문제 원인 및 배경

오늘의 옷 프로젝트중 옷 검색 기능 중에, 공개 설정된 옷만 가져오도록 기능을 바꾸었다. 따라서, 처음에는 Slice 를 통해 가져온 데이터에 옷이 비공개인것만 그 리스트에서 삭제하려고 하고 아래와 같이 코드를 짰다.

 @Override
    public SliceDto<SearchResponse> searchByTag(SearchRequest request, Pageable pageable) {
        Slice<Clothes> clothes = clothesRepository.searchByTag(request, pageable);
        clothes.getContent().removeIf((Clothes::isLocked)); // 이후 문제가 되는 부분
        return SliceDto.create(clothes.map(this::createSearchDtoResponse));
    }

하지만, 테스트를 돌려보니까 다음과 같이 UnsupportedOperationException 에러가 났다. 불가능한 연산이라는 것인데, 어디서 올라온 예외인지 찾아보려고 인터페이스와 구현 클래스들을 찾아보아 나갔다.

☁️ 코드 분석

먼저, Slice 인터페이스는 Streamable 인터페이스를 상속받고 있다.

Slice 인터페이스의 구현체인 SliceImpl 클래스는, Chunk 클래스를 상속받고 있다.

Chunck 클래스를 가보니 컨텐츠 필드가 보여서 내가 코드에서 사용했던 getContent()함수를 찾아보니, Collections.unmodifiableList()를 반환하고 있었다. 즉 말 그대로 변경 불가능한 리스트를 반환하고 있는 것이다.

마지막으로 Collections 클래스에 가보니,
add(), remove(), addAll()과 같이 리스트의 값을 변경시킬 수 있는 모든 연산에 대해 UnsupportedOperationException 예외를 터트리고 있던 것이다.

☁️ 해결

따라서, Slice나 Page의 content의 값을 필터링 하거나 변경 시켜야 한다면, 새로 생성한 List에서 값을 처리 후 새로운 SliceImpl 객체에 변경된 리스트를 담아서 반환 시켜 주었다.

 @Override
    public SliceDto<SearchResponse> searchByKeyword(String keyword, Pageable pageable) {
        Slice<Clothes> sliceEntity = this.clothesRepository.findByContentContaining(keyword, pageable);
        
        //새로운 리스트 생성 후 필터링
        List<Clothes> clothes = new ArrayList<>(sliceEntity.getContent());
        clothes.removeIf(Clothes::isLocked);
        
        //새로운 SliceImpl 객체 반환
        return SliceDto.create(new SliceImpl<>(clothes, pageable, sliceEntity.hasNext()).map(this::createSearchDtoResponse));
    }

"앞으로는 에러가 나면, 구글링 보다는 코드를 먼저 파헤쳐 보는 습관을 들이면 문제를 더 쉽게 해결할 수 있을 것 같다!"

profile
개인용으로 공부하는 공간입니다. 잘못된 부분은 피드백 부탁드립니다!

0개의 댓글