늦은 프로그래밍 이야기
230217 TIL (최종프로젝트) 본문
프로젝트
현재 위치의 반경 3km 내의 레스토랑 목록 조회
작업을 분배받은 것들 중 프론트 구현을 제외하고 가장 마지막 남은 기능이었다. 가장 어려운 기능이어서 앞쪽에서 작업 했다가는 시간을 다 허비할 것 같고 다른 팀원이 담당한 레스토랑 생성 부분이 완료되어야 할 수 있는 기능이어서 제일 후순위에 작업을 하였다.
해당 작업을 진행하면서 가장 어려웠던 부분은 역시나 위도 경도를 이용하여 반경 3키로 이내의 레스토랑의 위도 경도를 구하는 것이었다. 어제 작업하였던 검색을 사용하여 현재 위치의 위도 경도와 레스토랑의 위도 경도를 사용하여 거리를 구하는 것에서 살짝 변형된 식이었지만, 해당 산식을 정확히 이해하지 못해서 식을 변형하는데 어려움이 따랐다.
구글에 검색한 결과 해당 식을 SQL문으로 작성한 것을 찾았고, SQL문을 JPQL로 바꿔 보았다. 쉽지 않았지만 IDE의 도움을 받아 밑줄이 안뜨는 코드를 작성하는데 성공하였다.
@Query(value = "select r, (6371 * acos(cos(radians(:latitude)) * cos(radians(r.position.latitude)) "
+ "* cos(radians(r.position.longitude) - radians(:longitude)) + sin(radians(:latitude)) "
+ "* sin(radians(r.position.latitude)))) as distance "
+ "from Restaurant r "
+ "where distance < 3")
List<Restaurant> findRestaurantsByDistance(
@Param("latitude") double latitude, @Param("longitude") double longitude);
Where 문에서만 Alias를 설정할 수 있어서 발생한 문제
하지만 테스트 결과 작동하지 않았고, distance 컬럼을 찾을 수 없다는 에러 메시지를 확인하였다. 동료 수강생의 도움을 받아 JPQL에서 Alias를 where 문에서만 사용할 수 있다는 사실을 알게 되었고, 그 이유는 select 문의 컬럼들을 JPA가 임의로 설정하기 때문에 Alias를 설정할 수 없었던 것이다.
따라서 해당 산식을 select에서 사용하지 않을 방법이 없을까 고민하다가 어차피 distance로 뒤에서 받아오는데 바로 where문에 넣어주면 되지 않을까 생각이 들었다.
@Query(value = "select r from Restaurant r "
+ "where (6371 * acos(cos(radians(:latitude)) * cos(radians(r.position.latitude)) "
+ "* cos(radians(r.position.longitude) - radians(:longitude)) + sin(radians(:latitude)) "
+ "* sin(radians(r.position.latitude)))) < 3")
List<Restaurant> findRestaurantsByDistance(
@Param("latitude") double latitude, @Param("longitude") double longitude);
위와 같이 select에 있던 산식을 distance 자리로 옮겨주니 쿼리가 제대로 작동하는 것을 확인할 수 있었다. 하지만 API 문서를 확인하고 엔티티를 반환하는 것이 아닌 어제와 같이 특정 값을 반환해줘야 한다는 사실을 깨닫고 다시 join fetch를 사용하여 RestaurantInfo에서 데이터를 조회하여 반환하는 방식으로 변경하였다.
@Query(value = "select new team.waitingcatch.app.restaurant.dto.restaurant.RestaurantsWithin3kmRadiusJpaResponse("
+ "r.name, r.images, i.rate, r.searchKeywords, r.position, i.currentWaitingNumber, i.isLineupActiveStatus) "
+ "from Restaurant r join fetch RestaurantInfo i on r.id = i.restaurant.id "
+ "where (6371 * acos(cos(radians(:latitude)) * cos(radians(r.position.latitude)) "
+ "* cos(radians(r.position.longitude) - radians(:longitude)) + sin(radians(:latitude)) "
+ "* sin(radians(r.position.latitude)))) < 3")
List<RestaurantsWithin3kmRadiusJpaResponse> findRestaurantsByDistance(
@Param("latitude") double latitude, @Param("longitude") double longitude);
SQL 내장함수를 사용했을 때의 성능 개선에 대한 고찰 (리팩토링 및 성능 개선 시간에 계속)
이후 쿼리가 너무 길어진 것 같아서 ChatGPT에게 간단한 쿼리가 있는지 물어보았고 다음과 같은 답변을 받았다.

답변받은 함수를 사용하여 위의 코드를 변형해 보았는데 문제없이 작동하는 것을 확인하였다. 추후 성능 테스트를 하여 어떤 쿼리가 시간을 덜 소모하는지 확인하고 적용하도록 해야겠다.
'내일배움캠프 > TIL, WIL' 카테고리의 다른 글
| 230216 TIL (최종프로젝트) (0) | 2023.02.17 |
|---|---|
| 230214 TIL (최종프로젝트) (0) | 2023.02.14 |
| 230213 TIL (최종프로젝트) (0) | 2023.02.13 |
| 230210 TIL (알고리즘, 프로젝트) (0) | 2023.02.10 |
| 230209 TIL (알고리즘, 프로젝트) (0) | 2023.02.09 |