ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 15. 외부 API를 호출해보자
    스프링개발자/201 - 일반 2020. 8. 1. 07:06

    [배경]

    Vehicle Routing Problem(VRP)에서 Routing을 하기 위해서는 맵 정보가 필요하다. A,B,C 라는 장소가 있으면 A에서 B까지의 거리, A에서 C 까지의 거리, B에서 A까지 등등, 3x3 matrix가 필요하다. 이 Matrix를 ODMatrix라고 부른다. OD는 Origin Destination의 약자이다. ODMatrix를 구하는 가장 쉬운 방법은, 두 위치의 lat,long coordinate의 차이를 구해서 속도로 나눠서 travel time을 구하는 단순한 방법도 있다. 하지만 교통상황 등을 고려하기 위해서 현실에서는, Heremaps와 같은 mapping provider 외부 api를 호출한다. 이 글에서 Heremaps의 api를 호출해서 이 OD Matrix를 얻어보자.


    1. Heremaps 회원가입

    https://developer.here.com/ 에서 개발자로 회원가입후에, apiKey를 받자. 무료로 2개까지 생성 가능하다.

     

    2. Postman에서 api 호출하기

    Developer Documentation 공식 문서의 설명을 읽고, 예제를 따라하는것이 경험상 가장 빠른 onboarding 길이다.

    처음에는 시간이 좀 더 걸리는 길 같아도, 처음에 할때 제대로 보는 것이 나중 시간을 아낀다. 내가 필요한 endpoint 예제는 다음의 페이지에 나와있다.

    https://developer.here.com/documentation/examples/rest/routing/many-to-many-matrix-routing

     

    Postman을 이용해 다음의 GET request를 보내보자.

    https://matrix.route.ls.hereapi.com/routing/7.2/calculatematrix.json?
    start0=52.5139%2C13.3576&start1=52.5214%2C13.4155&start2=52.5253%
    2C13.3693&destination0=52.5411%2C13.2127&destination1=52.5163%
    2C13.3780&destination2=52.4920%2C13.2849&destination3=52.4987%
    2C13.5228&destination4=52.5547%2C13.4578&mode=fastest%3Bcar&
    apiKey=님꺼쓰세요

    출발지가 3곳이고, 목적지가 5곳이다. 

     

    http status code 200이 나오고, 결과값은 다음과 같다.

     

    {
      "response": {
        "metaInfo": {
          "timestamp": "2020-08-01T01:18:57Z",
          "mapVersion": "8.30.111.150",
          "moduleVersion": "7.2.202030-7495",
          "interfaceVersion": "2.6.76",
          "availableMapVersion": [
            "8.30.111.150"
          ]
        },
        "matrixEntry": [
          {
            "startIndex": 0,
            "destinationIndex": 0,
            "summary": {
              "costFactor": 1241
            }
          },
          {
            "startIndex": 0,
            "destinationIndex": 1,
            "summary": {
              "costFactor": 307
            }
          },
          {
            "startIndex": 0,
            "destinationIndex": 2,
            "summary": {
              "costFactor": 800
            }
          },
          {
            "startIndex": 0,
            "destinationIndex": 3,
            "summary": {
              "costFactor": 1304
            }
          },
          {
            "startIndex": 0,
            "destinationIndex": 4,
            "summary": {
              "costFactor": 1165
            }
          },
          {
            "startIndex": 1,
            "destinationIndex": 0,
            "summary": {
              "costFactor": 1790
            }
          },
          {
            "startIndex": 1,
            "destinationIndex": 1,
            "summary": {
              "costFactor": 412
            }
          },
          {
            "startIndex": 1,
            "destinationIndex": 2,
            "summary": {
              "costFactor": 1292
            }
          },
          {
            "startIndex": 1,
            "destinationIndex": 3,
            "summary": {
              "costFactor": 866
            }
          },
          {
            "startIndex": 1,
            "destinationIndex": 4,
            "summary": {
              "costFactor": 784
            }
          },
          {
            "startIndex": 2,
            "destinationIndex": 0,
            "summary": {
              "costFactor": 1574
            }
          },
          {
            "startIndex": 2,
            "destinationIndex": 1,
            "summary": {
              "costFactor": 477
            }
          },
          {
            "startIndex": 2,
            "destinationIndex": 2,
            "summary": {
              "costFactor": 1236
            }
          },
          {
            "startIndex": 2,
            "destinationIndex": 3,
            "summary": {
              "costFactor": 1260
            }
          },
          {
            "startIndex": 2,
            "destinationIndex": 4,
            "summary": {
              "costFactor": 1000
            }
          }
        ]
      }
    }

    costFactor는 두 지역간의 거리에 따른 값이다.

     

    3. 스프링부트에서 외부 api를 호출하자

    Spring web package에 있는 UriComponentsBuilder를 이용해서 parameter들을 좀 더 손쉽게 전달할 수 있다.

     

    Parameter로 전달하는 key값은 모두 hereMaps API에서 요구하는 값들이다.

    apiKey와 mode를 각각 전달하였고,

    start와 destination또한 전달한다. Location은 lat과 long의 double 좌표값이고, 샘플 location들을 전달하였다.

    21번째 줄을 보면, 위에서 준비한 URI를 생성하여서 restTemplate에 넘겨준다.

     

    4. 테스트

    Test를 하나 만든다.

    sout으로 "my result is: "로 시작하는 http get의 result를 볼 수 있다.

    소스코드 보기

    https://github.com/2ndPrince/routeOptimization/tree/call_external_api


    [TODOs]

    1. apiKey를 application.properties로 옮기자

    2. 샘플 location이 아니라, user request에서 location을 받아오자

     

    [TroubleShooting]

    1. Location의 toString을 재정의해야했다. hereMaps가 요구하는 포멧대로.

    2. UriComponentsBuilder에서 queryParams는 multiValueMap을 요구한다

    3. map에 들어가는 key와 value는 hereMaps가 요구하는 포멧을 (1번과 마찬가지로) 따라야 한다. 예를들어 start0, start1, destination0, destination2의 key값들은 받아드리지만, 유저가 임의로 키 값을 정해서 origin0, stop3 과 같은 string을 만들수 없다.

Designed by Tistory.