코딩과 결혼합니다

230815 - 코드 리팩토링 멋진 3중 for문을 하나의 for문으로 본문

코딩과 매일매일♥/Seoulvival

230815 - 코드 리팩토링 멋진 3중 for문을 하나의 for문으로

코딩러버 2023. 8. 15. 17:00
728x90
    //커뮤니티 전체조회(위치 태그)
    public PostListResponse getLocationPost(int page, int size, String locationTagName) {
        // 페이지 및 사이즈 계산
        Pageable pageable = PageRequest.of(page,size, Sort.by(Sort.Direction.DESC, "createdAt"));

        Page<Post> postPages = postRepository.findAllByLocationTagContaining(locationTagName, pageable);
        //#장소1#장소2
        List<PostResultDto> postResultDtos = new ArrayList<>();

        if (postPages == null) {
            throw new IllegalArgumentException("존재하지 않는 태그입니다.");
        }

        for (Post checkLocationName : postPages){
            String[] checkLocationTagNames = checkLocationName.getLocationTag().split("#");

            for (int i = 0; i < checkLocationTagNames.length; i++) {
                if (locationTagName.equals(checkLocationTagNames[i])) {
                    for (Post post : postPages){
                        UserResponseDto userResponseDto = new UserResponseDto(post.getUser());
                        PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(post);
                        postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto));
                    }
                }
            }
        }
        return new PostListResponse("검색 조회 성공",postPages.getTotalPages(),postPages.getTotalElements(), size, postResultDtos);
    }

926ms

    //커뮤니티 전체조회
    public PostListResponse getLocationPost(int page, int size, String locationTagName) {
        // 페이지 요청을 생성하고, 날짜를 기준으로 내림차순 정렬 설정
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));

        // 입력된 위치 태그를 포함하는 게시물을 페이지네이션하여 조회
        Page<Post> postPages = postRepository.findAllByLocationTagContaining(locationTagName, pageable);

        // 조회 결과를 담을 리스트 초기화
        List<PostResultDto> postResultDtos = new ArrayList<>();

        // 조회된 게시물 페이지가 비어있지 않은 경우
        if (!postPages.isEmpty()) {
            // 각 게시물에 대해서 위치 태그 검사 수행
            for (Post post : postPages) {
                // 게시물의 위치 태그를 '#' 문자를 기준으로 분리
                String[] checkLocationTagNames = post.getLocationTag().split("#");

                // 분리된 태그들을 순회하며 입력된 위치 태그와 일치하는지 확인
                for (String tag : checkLocationTagNames) {
                    if (locationTagName.equals(tag)) {
                        // 일치하는 경우 해당 게시물의 사용자 정보와 게시물 정보를 DTO로 생성하여 리스트에 추가
                        UserResponseDto userResponseDto = new UserResponseDto(post.getUser());
                        PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(post);
                        postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto));
                        break; // 일치하는 태그를 찾았으므로 더 이상 검사하지 않음
                    }
                }
            }
        }

        // 최종적으로 검색 결과와 페이징 정보를 담은 응답을 생성하여 반환
        return new PostListResponse("검색 조회 성공", postPages.getTotalPages(), postPages.getTotalElements(), size, postResultDtos);
    }

826ms

    //커뮤니티 전체조회(위치 태그)
    public PostListResponse getLocationPost(int page, int size, String locationTagName) {
        // 페이지 요청을 생성하고, 날짜를 기준으로 내림차순 정렬 설정
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));

        // 입력된 위치 태그를 포함하는 게시물을 페이지네이션하여 조회
        Page<Post> postPages = postRepository.findAllByLocationTagContaining(locationTagName, pageable);

        if (postPages.isEmpty()) {
            throw new IllegalArgumentException("존재하지 않는 태그입니다.");
        }

        // 조회 결과를 담을 리스트 초기화
        List<PostResultDto> postResultDtos = new ArrayList<>();

        // 조회된 게시물 페이지를 순회
        for (Post post : postPages) {
            // 게시물의 위치 태그를 '#' 문자를 기준으로 분리
            String[] checkLocationTagNames = post.getLocationTag().split("#");

            // 분리된 태그들 중 입력된 위치 태그와 일치하는지 확인
            if (Arrays.asList(checkLocationTagNames).contains(locationTagName)) {
                UserResponseDto userResponseDto = new UserResponseDto(post.getUser());
                PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(post);
                postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto));
            }
        }

        // 최종적으로 검색 결과와 페이징 정보를 담은 응답을 생성하여 반환
        return new PostListResponse("검색 조회 성공", postPages.getTotalPages(), postPages.getTotalElements(), size, postResultDtos);
    }

870 ms

1. **중복된 반복문 제거:** 원래 코드에는 게시물 리스트를 두 번 순회하는 부분이 있었다. 리팩토링을 통해 이를 한 번만 순회하도록 변경하였다. 이는 CPU 사용량을 줄이며 코드의 실행 시간을 단축시킨다.

2. **태그 비교 최적화:** 원래의 코드는 게시물의 모든 태그를 순회하면서 입력된 태그와 일치하는지 확인했다. 리팩토링된 코드에서는 `Arrays.asList().contains()` 메서드를 사용하여 태그 존재 유무를 더 빠르게 확인한다.

3. **불필요한 객체 생성 최소화:** 원래 코드에서는 조건에 맞는 게시물을 찾을 때마다 DTO 객체를 여러 번 생성하는 문제가 있었다. 리팩토링을 통해 이를 최소화하여 메모리 할당과 가비지 컬렉션에 따른 오버헤드를 줄였다.

4. **예외 처리 최적화:** 리팩토링된 코드에서는 게시물 페이지가 비어 있는 경우에만 예외를 발생시킨다. 이를 통해 불필요한 예외 처리 로직의 실행을 피하며, 성능 향상을 꾀했다.

다만, 위의 최적화들이 실제 애플리케이션의 전반적인 성능에 얼마나 큰 영향을 미치는지는 사용하는 데이터의 크기, 데이터베이스의 성능, 시스템의 스펙 등 여러 요인에 따라 달라진다. 예를 들어, 만약 postRepository의 `findAllByLocationTagContaining` 메서드가 데이터베이스에서 많은 양의 데이터를 조회하는 데 시간이 많이 소요된다면, 위에서 언급한 최적화 효과는 상대적으로 미미할 수 있다.