80일차 길찾기 코드 수정, 랜덤 길찾기(1)

이해찬·2023년 10월 30일
0

항해일지

목록 보기
33/35

2023.10.25

🚗 기존 길찾기 코드(카카오 api)

  • https://developers.kakao.com/docs/latest/ko/local/dev-guide#address-coord
  • 로컬 REST API를 활용해서 사용자가 주소 값을 입력하면 해당 주소를 db와 비교해서 지도 좌표로 변환해주는 코드를 작성
  • 요청 형식에 맞는 uri 코드 작성 -> restTemplate 카카오 api호출
  • 응답 객체 받아오기 -> 입력한 주소의 좌표
  • 로컬에서 사용한 형식을 카카오 길찾기 api에 맞춰서 요청 -> 응답 객체 받아와서 해당 좌표를 프론트 상에서 폴리라인으로 경로 그려주기


📟 카카오 요청 api -> uri

private static final String KAKAO_LOCAL_SEARCH_ADDRESS_URL = "https://dapi.kakao.com/v2/local/search/address.json";

 public URI buildUriByAddressSearch(String address) {
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(KAKAO_LOCAL_SEARCH_ADDRESS_URL);
        uriBuilder.queryParam("query", address);

        URI uri = uriBuilder.build().encode().toUri(); // encoding -> 브라우저에서 해석할 수 없는 것들-> UTF-8 로 인코딩해줌
        log.info("*** 로그 [KakaoUriBuilderService buildUriByAddressSearch] address: {}, uri: {}", address, uri);

        return uri;
    }
    
    // ->주소검색 api를 uri 형태로 빌더 해줌
    

📟 uri로 만든 주소로 카카오api 호출

public class KakaoAddressSearchService{

   private final RestTemplate restTemplate;
    private final KakaoUriBuilderService kakaoUriBuilderService;

    @Value("${kakao.rest.api.key}")
    private String kakaoRestApiKey;

    // 해당 메서드를 호출 -> 입력한 주소값 -> 요청할 수 있는 uri + headers에 key값
    // 요청한 것에 대한 응답 값 -> kakaoApiResponseDto 객체로 반환
    public KakaoApiResponseDto requestAddressSearch(String address){ // 주소 -> 위도, 경도로 변환

        if(ObjectUtils.isEmpty(address)) return null;

        URI uri = kakaoUriBuilderService.buildUriByAddressSearch(address);

        HttpHeaders headers = new HttpHeaders();
        headers.set(HttpHeaders.AUTHORIZATION, "KakaoAK " + kakaoRestApiKey);
        HttpEntity httpEntity = new HttpEntity(headers);

        // kakao api 호출
        return restTemplate.exchange(uri, HttpMethod.GET, httpEntity, KakaoApiResponseDto.class).getBody();

    }
 }


  • 길찾기 요청에 맞는 형식으로 요청해서 응답값을 받아옴




🚗 기존 랜덤 길찾기 코드(카카오 api)

  • 기존에 사용한 api는 자동차 길찾기 api를 활용해서 구현
  • 랜덤 길찾기는 다중 경유지 길찾기 api를 활용해서 응답값에 받아오는 경유지를 랜덤으로 설정해서 경로를 그려주는 식으로 구현
  • 주소를 입력하고 좌표를 받아오고, uri를 만들어서 요청을 보내는 방식은 거의 동일

📟 랜덤 길찾기 -> 출발지, 반경 기반

  public KakaoRouteAllResponseDto requestAllRandomWay(String username, String originAddress, Integer redius) {

       if (ObjectUtils.isEmpty(originAddress) || ObjectUtils.isEmpty(redius)) return null;

        // 출발지와 도착지 주소를 각각 좌표로 변환
        DocumentDto origin = kakaoAddressSearchService.requestAddressSearch(originAddress).getDocumentDtoList().get(0);

        /***
         목적지와 경유지 값을 반경으로 계산해서 가져오는 메소드
         ***/
        KakaoApiResponseDto responses = kakaoCategorySearchService.requestAttractionCategorySearch(origin.getLatitude(), origin.getLongitude(), redius);

        List<String> addressNames = responses.getDocumentDtoList().stream()
                .map(DocumentDto::getAddressName)
                .collect(Collectors.toList());

        log.info("getDocumentDtoList addressNames : {} " , addressNames.toString());
        // DocumentDto 리스트 확인


        /***
         랜덤으로 다중 목적지와 경유지 만들기 알고리즘
         ***/
        int RandomLength = responses.getDocumentDtoList().size();
        Random rd = new Random();

        int destinationCnt = rd.nextInt(RandomLength);
        int waypointsCnt = rd.nextInt(RandomLength);

        if(destinationCnt == waypointsCnt){
            if(destinationCnt == 0){
                destinationCnt += 1;
            }
            waypointsCnt = destinationCnt - 1;
        }
        log.info("destinationCnt : {}",destinationCnt);
        log.info("waypointCnt : {}",waypointsCnt);

        DocumentDto destination = responses.getDocumentDtoList().get(destinationCnt);
        DocumentDto waypoints = responses.getDocumentDtoList().get(waypointsCnt);

        // 목적지 DB에 남김, 만일 동일 사용자가 이미 목적지를 저장해 놓았다면, 삭제
        RandomDestination randomDestination = new RandomDestination(username, destination.getAddressName());
        RandomDestination olderRandomDestination = randomDestinationRepository.findByUsername(username);
        if (olderRandomDestination != null)
            randomDestinationRepository.delete(olderRandomDestination);
        randomDestinationRepository.save(randomDestination);

        /***
         요청 헤더 만드는 공식
         ***/

        return makeRequestForm(origin,destination,waypoints);
    }
  • requestAttractionCategorySearch -> 를 활용해서 카카오 api의 카테고리 검색을 사용
  • 카테고리에 맞는 값을 입력하면 해당하는 범위의 카테고리를 찾아줌
  • 현재는 관광명소로 설정해서 -> 사용자가 주소를 입력하면 그 좌표 주변의 반경을 기반으로 좌표를 받아와서 경유지,목적지로 설정 -> 길찾기 api에 요청

🤷‍♂️ 현재 랜덤 길찾기 문제점

  • 랜덤으로 받아온 경유지를 경유지, 목적지로 설정하고 있으므로 경로가 겹칠 수가 있다.
  • 지나온 길을 다시 지나간다던가 하는 효율적인 경로를 생성하지 못한다.
  • 정확한 지명, 정확한 관광명소에 대한 정보를 완벽하게 가져오지 못한다.(가져올때도 있고 없을때도 있다.)
  • 출발지 검색 -> 도로명만을 검색 가능, 키워드 기반 검색도 가능하게 기능 추가




  • 계양맛길 음식문화시범거리 -> 카카오맵에 정확한 주소지로 나온다.
    -> 네이버 지도에서는 안나온다. 카카오맵에만 있는 주소이다. 네이버는 "계양맛길"
  • 독산 -> 독산동 전체가 나온다
  • 영월의숲 -> 영월의 숲도 전체지역을 아우르는 키워드
  • 정확한 장소 지명이 안되고 있다.
    -> 인기순, 리뷰 많은 순 등의 작업은 어렵다. 이게 가능하게 할려면 따로 카테고리별에 맞는 데이터를 만들어서 비교하며 찾아줘야 할 듯 하다.



🤷‍♂️ 장소명과 지번의 주소가 불일치 하는 경우도 발생

  • place_name : 장소명,업체명
  • address_name : 전체 지번
    -> 위의 두 개의 주소가 일치하는 경우도 있지만, 밑에처럼 불일치 하는 경우도 발생


  • 인천 계양구 방축동 뒷동산 2 개의 키워드는 어찌보면 무관해 보이기까지 한다.



💻 개선 방향

  1. 카테고리에 맞는 정확한 지명과 주소의 매칭
  2. 효율적인 길찾기 경로 생성
  3. 도로교통 정보를 반영 -> 거리가 더 멀어지더라도 정체 -> 서행으로 드라이브를 할 수 있게
  4. 출발지 도착지 명확하게 표시


✅ 1. 카테고리에 맞는 정확한 지명과 주소의 매칭= 정확한 address + 지명

  • 키워드를 입력하면 해당 주소를 반환해주는 키워드 api 활용
  • address_name시, 구 + 키워드 조합 -> 주소 요청 + 해당 카테고리 맞는지 검사
  • 해당 키워드 place_name 요청 -> address_name 가져와서 좌표로 변환

키워드 검색 -> 주소 & 정확한 주소 탐색



✅ 2. 효율적인 길찾기 경로 생성

  • 경유지 리스트들 중 2개를 랜덤으로 뽑아서 경유지, 목적지로 설정 -> 중복된 경로가 발생
  • 효율적인 경로 생성이 어려움 -> 중복된 경로가 생성되지 않고 이어지는 경로 생성
  • 반경이 제한적인 상황
  • 하나의 경유지가 아닌 다양한 경유지(관광 명소 카테고리)를 잡아서 다채로운 경로 생성

효율적인 길찾기 -> 알고리즘을 구현해서 길찾기 해보기



✅ 3. 도로교통 정보를 반영

  • 키워드를 입력하면 해당 주소를 반환해주는 키워드 api 활용
  • address_name시, 구 + 키워드 조합 -> 주소 요청 + 해당 카테고리 맞는지 검사
  • 해당 키워드 place_name 요청 -> address_name 가져와서 좌표로 변환

-링크



✅ 4. 출발지 도착지 명확하게 표시

  • 키워드를 입력하면 해당 주소를 반환해주는 키워드 api 활용
  • address_name시, 구 + 키워드 조합 -> 주소 요청 + 해당 카테고리 맞는지 검사
  • 해당 키워드 place_name 요청 -> address_name 가져와서 좌표로 변환

-링크

profile
디자인에서 개발자로

0개의 댓글