나와바리 - 페이징 처리

Sungmin·2023년 9월 8일
0

Spring Data JPA Slice, No-offset

프로젝트의 메인 페이지 , 식당 리뷰 페이지 , 내가 작성한 리뷰 목록 페이지 에서
페이징 기능을 사용하여 구현하였다. 모바일 환경인 점을 고려해 무한 스크롤 방식을 사용하였다.

Spring Data JPA의 Slice


무한 스크롤은 다음에 조회할 페이지가 있는지 내부적으로 체크한 다음, 클라이언트에게 다음 페이지 여부를 알려주는 방식으로 구현할 수 있다.

"last" 라는 속성을 통해 클라이언트에게 남은 페이지가 더 있는지 알려줄 수 있다.


클라이언트에게 위치정보와 page, size를 받아와서 처리하는 컨트롤러


    /**
     * 현위치를 받아와 동 이름이 일치하는 식당들 조회
     */
    @PostMapping("/api/v1/location/restaurants")
    public ResponseEntity<Slice<RestaurantDTO>> getCurrentLocation(@RequestBody LocationDTO locationDTO,
                                                                   @PageableDefault Pageable pageable) {
        float current_lat = locationDTO.getCurrent_lat();
        float current_lng = locationDTO.getCurrent_lng();
        String dongName = currentLocationService.getCurrentLocation(current_lat, current_lng);

        //동 이름이 없을경우 404 Not Found 반환
        if (dongName == null) {
            return ResponseEntity.notFound().build();
        }

        Slice<Restaurant> restaurants = restaurantService.searchByCurrentRestaurant(dongName, pageable);

        List<RestaurantDTO> restaurantDTOS = restaurants.getContent().stream()
                .map(RestaurantDTO::convertToDTO)
                .collect(Collectors.toList());
        return ResponseEntity.ok(new SliceImpl<>(restaurantDTOS, restaurants.getPageable(), restaurants.hasNext()));
        //content가 null일 경우 동과 일치하는 주소가 없는것 = 서울 이외의 지역인 경우
    }

KAKAO API를 이용해 받아온 위도 경도의 주소값을 활용해 서울특별시의 해당하는지 확인하고 동 단위를 받아온다.


    public String getCurrentLocation(float current_lat, float current_lng) {
        String url = kakaoMapApi + "?x=" + current_lng + "&y=" + current_lat;

        HttpClient httpClient = HttpClient.newHttpClient();
        HttpRequest httpRequest = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "KakaoAK " + kakaoApiKey)
                .build();

        try {
            HttpResponse<String> response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
            String responseBody = response.body();

            Gson gson = new Gson();
            JsonObject responseJson = gson.fromJson(responseBody, JsonObject.class);

            JsonArray documents = responseJson.getAsJsonArray("documents");

            if (documents.size() > 0) {
                String siName = documents.get(0).getAsJsonObject().get("region_1depth_name").getAsString();
                String dongName = documents.get(0).getAsJsonObject().get("region_3depth_name").getAsString();

                if (!siName.equals("서울특별시")) {
                    return null;
                }
                return dongName;
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }

        return null;
    }

받아온 위도, 경도를 기반으로 URL을 생성하고 HttpRequest 객체에 URI와 인증 정보를 요청 헤더에 추가한다.
그리고 httpClient.send() 메서드를 사용해 HTTP 요청을 보내고 API응답을 받는다.
받은 Json 문자열을 Gson 라이브러리를 사용해 Java 객체로 변환해서 값을 꺼내온다.


동 이름이 일치한다면 DB에서 동 이름을 포함하는 식당을 조회 한다.


//동이름으로 식당찾기
    public Slice<Restaurant> searchByDongName(String dongName, Pageable pageable) {
        List<Restaurant> restaurantList = em.createQuery("select r from Restaurant r where r.address_name like :dongName", Restaurant.class)
                .setParameter("dongName", "%" + dongName + "%")
                .setFirstResult((int) pageable.getOffset())
                .setMaxResults(pageable.getPageSize())
                .getResultList();

        return new SliceImpl<>(restaurantList, pageable, restaurantList.size() >= pageable.getPageSize());
    }

setFirstResult()setMaxResults() 를 사용하여 페이징을 적용한다.
첫 번째 결과의 위치와 최대 결과 수가 설정.
SliceImpl 을 사용하여 현재 페이지에 포함된 레스토랑 목록, 페이징 및 정렬 정보, 현재 페이지에 더 많은 결과가 있는지 여부를 나타내는 불리언 값을 전달.

이러한 방식으로 통합검색, 식당 리뷰 페이지 , 내가 작성한 리뷰 목록 페이지 에서도 페이징 처리를 적용해 주었다.

profile
Let's Coding

0개의 댓글