Dev

위치 기반으로 글 조회 기능 구현

khjoon 2024. 12. 4. 21:59

들어가며

게시판 기능인데 근처에 거주하고 있는 사람의 글을 조회할 수 있는 기능이 필요해서 게시글을 저장할때와 조회할때 위치를 반영해서 조회와 저장하도록 구현했습니다.

Tool

Spring boot 버전 2.7.7
Naver Cloud Maps

Naver Cloud Platform에서 Service 이용신청하기

저는 위도, 경도를 이용해서 위치를 찾아낼 수 있는 Reverse Geocoding API를 사용했습니다.

API요청은 가이드대로 요청하였습니다.
https://api.ncloud-docs.com/docs/ai-naver-mapsreversegeocoding

 

일단 사용자 위치를 저장하고 조회할 수 있는 기능을 먼저 구현했습니다.

 

위도와 경도는 클라이언트에서 받아온 뒤 위치를 저장하고 조회하는 기능을 구현했습니다.

클라이언트에서 받아온 위도와 경도로 위에서 등록한 Naver Server에 요청을 보내서 해당 주소를 받아올 수 있습니다.

public void createLocation(Member member, PostRequestDTO.LocationDTO request){

        String coords = request.getLongitude() + "," + request.getLatitude();
        NaverGeoResponse naverGeoResponse = naverGeoFeignClient.generateLocation("coordsToaddr",coords,"epsg:4326","json","legalcode");

        Optional<Location> location = locationRepository.findByAddress(naverGeoResponse.getResults().get(0).getRegion().getArea3().getName());

        if(!location.isPresent()) {

            Location newLocation = Location.builder()
                    .latitude(request.getLatitude())
                    .longitude(request.getLongitude())
                    .address(naverGeoResponse.getResults().get(0).getRegion().getArea3().getName())
                    .member(member)
                    .build();

            locationRepository.save(newLocation);
        }


    }

 

조회는 저장한 위치를 불러왔습니다.

public List<Location> getLocationList(Member member){

        return locationRepository.findAllByMember(member);

    }

 

Post를 작성할 때 위치도 같이 저장해서 조회할 때 사용자의 현 주소(동 단위)를 가진 Post를 조회할 수 있도록 구현했습니다.

위치 조회를 통해 얻은 위치 id를 request parameter로 넘겨주면 해당 위치 범위에서 작성한 post를 조회할 수 있도록 구현했습니다.(rquest parameter로 null인 경우는 전체 조회되도록 했습니다.)

//controller
@GetMapping("/")
@Operation(summary = "커뮤니티 글 조회 API", description = "커뮤니티에서 글 조회하는 api입니다.postType: 나눔, 레시피, 빈값(전체 조회) ")
@Parameters(value = {
            @Parameter(name = "lastIndex", description = "lastIndex 첫 조회는 0이고 스크롤 내릴때마다 마지막 index 입력하시면 됩니다. 맨 처음인 경우 Null"),
            @Parameter(name = "postType", description = "나눔, 레시피, 선택하지 않으면 전체가 조회됩니다."),
            @Parameter(name = "locationId", description = "위치 조회 해서 나온 현재 위치 id를 입력하면 됩니다. Null인 경우 전체 조회")

    })
    public ResponseDTO<PostResponseDTO.PostListDTO> getPostList(Authentication auth,
                                                                      @RequestParam(value = "lastIndex", required = false) Long lastIndex,
                                                                      @RequestParam(value = "postType", required = false) PostTopicType postTopicType,
                                                                @RequestParam(value = "locationId",required = false) Long locationId ){

        Member member = memberQueryService.findMemberById(Long.valueOf(auth.getName().toString())).orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
        if(lastIndex == null){
            lastIndex = 0L;
        }
        List<Post> posts = postService.getPostList(lastIndex,postTopicType,locationId);

        return ResponseDTO.onSuccess(PostConverter.toPostList(posts, member));
    }
//service
public List<Post> getPostList(Long lastIndex, PostTopicType postTopicType, Long locationId){
        Location location;

        if(locationId == null){
            location = null;
        }else{
            location = locationRepository.findById(locationId).orElseThrow(()->new PostHandler(ErrorStatus.LOCATION_NOT_FOUND));
        }


        return postRepository.findPostList(lastIndex, postTopicType, location);
    }
//Repository
public interface PostRepository extends JpaRepository<Post, Long> {
    @Query("SELECT p FROM Post p WHERE (:postTopicType IS NULL OR p.topic = :postTopicType) AND p.id > :lastIndex AND(:location IS NULL OR p.location = :location) ORDER BY p.id ASC")
    List<Post> findPostList(Long lastIndex, PostTopicType postTopicType, Location location);
}