Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

[Server] 2단계: 지역 명 검색 활용 본문

Project/대중교통 길찾기

[Server] 2단계: 지역 명 검색 활용

Seung__ 2022. 1. 26. 23:42

현재는 출발, 도착지의 위도/경도를 직접 입력한다.

 

지역 이름을 검색하면, 위도/경도를 반환하는 api를 활용하자.

 

1. Google Geocoding


Google Cloud Platform에서 key를 발급받고, Geocoding API를 활용해 보자.

호출 예시를 보자.

The following example requests the latitude and longitude of "1600 Amphitheatre Parkway, Mountain View, CA", and specifies that the output must be in JSON format.

https://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&key=YOUR_API_KEY

주소는 QueryParam으로 넘겨주며 String으로 입력한 주소에서 공백은 '+'로 대체한다.

또한 key도QueryParam으로넘겨줌.

 

그렇다면 주소에 꼭 전체 주소가 들어가야 할까??

 

Overview  |  Geocoding API  |  Google Developers

Geocoding converts addresses into geographic coordinates to be placed on a map. Reverse Geocoding finds an address based on geographic coordinates or place IDs.

developers.google.com

꼭 그렇지는 않은 것 같다. 키워드도 가능함.

내가 필요한data는 Location이다. 

 

 

2. API Return값 분석


문서에 나와있는 예시를 보자.

필요한 정보인 location이 어디에 있는지 보자.

"results" 란 JsonArray에서 첫 번째 요소의 "geometry" JsonObject안에 있다.

{
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "1600",
               "short_name" : "1600",
               "types" : [ "street_number" ]
            },
            {
               "long_name" : "Amphitheatre Parkway",
               "short_name" : "Amphitheatre Pkwy",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Mountain View",
               "short_name" : "Mountain View",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Santa Clara County",
               "short_name" : "Santa Clara County",
               "types" : [ "administrative_area_level_2", "political" ]
            },
            {
               "long_name" : "California",
               "short_name" : "CA",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "United States",
               "short_name" : "US",
               "types" : [ "country", "political" ]
            },
            {
               "long_name" : "94043",
               "short_name" : "94043",
               "types" : [ "postal_code" ]
            }
         ],
         "formatted_address" : "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
         "geometry" : {
            "location" : {
               "lat" : 37.4267861,
               "lng" : -122.0806032
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 37.4281350802915,
                  "lng" : -122.0792542197085
               },
               "southwest" : {
                  "lat" : 37.4254371197085,
                  "lng" : -122.0819521802915
               }
            }
         },
         "place_id" : "ChIJtYuu0V25j4ARwu5e4wwRYgE",
         "plus_code" : {
            "compound_code" : "CWC8+R3 Mountain View, California, United States",
            "global_code" : "849VCWC8+R3"
         },
         "types" : [ "street_address" ]
      }
   ],
   "status" : "OK"
}

 

 

3.Front


출발지, 목적지 이름을 받는 간단한 뷰를 만들어보자.

<!DOCTYPE html>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Find Route</title>
</head>
<body>
<H1><b>대중교통 길찾기</b></H1>

<div class="search box">
  <form action="/By-locationName" th:action="@{/By-locationName}" th:object="${searchLocationReq}" method="post">
      <div class="input-group mb-3">
          <span class="input-group-text" id="basic-addon1">출발지</span>
          <input type="text" id="start" th:field="*{start}" class="form-control" placeholder="출발지" aria-label="start" aria-describedby="basic-addon1">
      </div>
      <div class="input-group mb-3">
          <span class="input-group-text" id="basic-addon2">목적지</span>
          <input type="text" id="end" th:field="*{end}" class="form-control" placeholder="목적지" aria-label="end" aria-describedby="basic-addon1">
      </div>
      <button type="submit" class="btn btn-primary" th:onclick="">검색</button>
  </form>
</div>

</body>
</html>

 

 

 

4. Controller


  • Controller의 역할은
  • view에서 출발지, 목적지 이름을 받는다.
  • 구글 API를 호출하여 지역 이름을 위도,경도로 변환한다.
  • 변환한 위도,경도를 Odsay API를 호출하며 넘겨준다.
  • 결과로 이동 경로를 반환한다.
  • 이동 경로에 대한 정보를 model에 담아 view로 넘긴다.
@PostMapping("/By-locationName")
public String searchLocation(@ModelAttribute SearchLocationReq searchLocationReq, Model model){
    JSONObject jsonStartResult = googleClient.searchLocation(searchLocationReq.getStart());
    JSONObject jsonEndResult = googleClient.searchLocation(searchLocationReq.getEnd());

    SearchRouteReq searchRouteReq = getSearchRouteReq(jsonStartResult, jsonEndResult);

    model = searchRoute2(searchRouteReq, model);

    return "resultPage";
}

private SearchRouteReq getSearchRouteReq(JSONObject jsonStartResult, JSONObject jsonEndResult) {
    double SX = (double) jsonStartResult.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location").get("lng");
    double SY = (double) jsonStartResult.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location").get("lat");
    double EX = (double) jsonEndResult.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location").get("lng");
    double EY = (double) jsonEndResult.getJSONArray("results").getJSONObject(0).getJSONObject("geometry").getJSONObject("location").get("lat");

    SearchRouteReq searchRouteReq = new SearchRouteReq(String.valueOf(SX), String.valueOf(SY), String.valueOf(EX), String.valueOf(EY));
    return searchRouteReq;
}

//@PostMapping("/search")
public Model searchRoute2(@ModelAttribute("searchRouteReq") SearchRouteReq searchRouteReq, Model model){
    JSONObject jsonResult = odSayClient.searchRoute(searchRouteReq);
    SearchRouteRes searchRouteRes = new SearchRouteRes(jsonResult);
    model.addAttribute("result", searchRouteRes);
    model.addAttribute("pathList", searchRouteRes.getPathList());
    //result page로 이동.
    return model;
}

 

 

 

5. GoogleClient


앞선 OdsayClient와 유사하다.

@Slf4j
@Component
public class GoogleClient {

    @Value("${google.key}")
    private String key;
    @Value(("${google.uri}"))
    private String locationUri;

   public JSONObject searchLocation(String location){


       String uriString = UriComponentsBuilder.fromUriString(locationUri)
               .queryParam("address", location)
               .queryParam("key", key).build().toUriString();

       URI uri = UriComponentsBuilder.fromUriString(uriString).build().toUri();
       log.info("[request google api] uri = {}", uri);
       //Http Entity
       var httpEntity = new HttpEntity<>(new HttpHeaders());
       var responseType = new ParameterizedTypeReference<String>(){};

       //ResponseEntity
        var responseEntity= new RestTemplate().exchange(
                uri, HttpMethod.GET, httpEntity, responseType
        );
       // log.info("result class : {}", responseEntity.getBody().getClass());


       return new JSONObject(responseEntity.getBody());
   }
}

 

 

 

6. Test결과


네이버 검색결과 ㅋㅋ 

 

 

 

7. GitHub:220126 Front 6(Search by location name)


 

GitHub - bsh6463/commuteMap

Contribute to bsh6463/commuteMap development by creating an account on GitHub.

github.com

 

Comments