본문 바로가기

좋아하는 것_매직IT/7.gin

Tmap Openapi 와 텔레그램 봇을 활용한 주변 맛집 검색 기능 간단 구현!

반응형

블로그 목적 

Tmap Openapi 와 텔레그램 봇을 활용한 주변 맛집 검색 기능 구현에 대해서 공부및 정리후 나만의 노하우와 지식을 공유한다.

블로그 요약

1. Tmap Openapi 에 대해서 알아본다.
2. Tmap Openapi 와 텔레그램 봇을 활용한 주변 맛집 검색 기능을 간단하게 구현해 본다. 

블로그 상세내용

요즘에 Tmap Openapi 에 관심이 생겨서 공부해서 어떤 기능을 개인적으로 구현해 볼까? 고민하던 중 ..
텔레그램 봇을 활용해서 내가 검색하고자 하는 위치의 맛집과 음식점들을 전송해보면 어떨까? 해서 바로 Tmap Openapi를 공부해봅니다.

Tmap Openapi 에 대해서 공부를 하기위해서 우선 SK open API 사이트에 접속합니다. 

아래와 같이 TMAP 관련해서 openapi 를 지원하고 있습니다. 

클릭해서 들어가보면 아래와 같은데요. TMAP  은 여러가지를 지원하는 것으로 보이고요. 
저는 제가 사용할 openapi 가 존재하는지 확인합니다. 

찾아보던 중 아래 openapi를 발견합니다. 

그리고 자세히 읽어보니, 제가 찾던 openapi 를 지원하고 있었습니다. 감사하게도요..!

https://openapi.sk.com/products/detail?svcSeq=4&menuSeq=12

 

SK open API

장소 장소 검색 장소 통합 검색 장소 상세 정보 검색 주변 카테고리 검색 읍면동/도로명 검색 지역 분류 코드 검색 경로 반경 검색 지오펜싱 공간 검색 영역 검색 지오코딩 Reverse Geocoding Geocoding F

openapi.sk.com

아래와 같이 예시도 있으니 참고합니다. 

그리고 친절하게도 다양한 언어로 구현할 수 있도록 예시코드도 제공하고 실행도 가능합니다. 
저는 이번 블로그에서 개발할 Go 를 선택해봅니다. 

아래는 golang 예시코드입니다. 

package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://apis.openapi.sk.com/tmap/pois?version=1&searchKeyword=SK%20T%ED%83%80%EC%9B%8C&searchType=all&searchtypCd=A&reqCoordType=WGS84GEO&resCoordType=WGS84GEO&page=1&count=20&multiPoint=N&poiGroupYn=N"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Accept", "application/json")
	req.Header.Add("appKey", 자신의 Appkey)

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(string(body))

}

실행해보니 아래와 같이 결과가 나오네요.

{
  "searchPoiInfo": {
    "totalCount": "41",
    "count": "20",
    "page": "1",
    "pois": {
      "poi": [
        {
          "id": "1128603",
          "pkey": "112860300",
          "navSeq": "0",
          "collectionType": "poi",
          "name": "SKT타워",
          "telNo": "",
          "frontLat": "37.56656541",
          "frontLon": "126.98452047",
          "noorLat": "37.56648210",
          "noorLon": "126.98510375",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주요빌딩",
          "detailBizName": "30층이상",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56648210",
                "centerLon": "126.98510375",
                "frontLat": "37.56656541",
                "frontLon": "126.98452047",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "1128603",
          "pkey": "112860303",
          "navSeq": "3",
          "collectionType": "poi",
          "name": "SKT타워 정문",
          "telNo": "",
          "frontLat": "37.56620435",
          "frontLon": "126.98474268",
          "noorLat": "37.56620435",
          "noorLon": "126.98474268",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주요빌딩",
          "detailBizName": "30층이상",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56620435",
                "centerLon": "126.98474268",
                "frontLat": "37.56620435",
                "frontLon": "126.98474268",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "1128603",
          "pkey": "112860304",
          "navSeq": "4",
          "collectionType": "poi",
          "name": "SKT타워 후문",
          "telNo": "",
          "frontLat": "37.56670430",
          "frontLon": "126.98521485",
          "noorLat": "37.56670430",
          "noorLon": "126.98521485",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주요빌딩",
          "detailBizName": "30층이상",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56670430",
                "centerLon": "126.98521485",
                "frontLat": "37.56670430",
                "frontLon": "126.98521485",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10202403",
          "pkey": "1020240302",
          "navSeq": "2",
          "collectionType": "poi",
          "name": "SKT타워 주차장",
          "telNo": "",
          "frontLat": "37.56656541",
          "frontLon": "126.98452047",
          "noorLat": "37.56650987",
          "noorLon": "126.98507598",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "교통편의",
          "middleBizName": "자동차시설",
          "lowerBizName": "주차장",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56650987",
                "centerLon": "126.98507598",
                "frontLat": "37.56656541",
                "frontLon": "126.98452047",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "0",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10140126",
          "pkey": "1014012601",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤T타워B4 전기차충전소",
          "telNo": "",
          "frontLat": "37.56656541",
          "frontLon": "126.98452047",
          "noorLat": "37.56642655",
          "noorLon": "126.98504821",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "교통편의",
          "middleBizName": "자동차시설",
          "lowerBizName": "전기차충전소",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "6",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56642655",
                "centerLon": "126.98504821",
                "frontLat": "37.56656541",
                "frontLon": "126.98452047",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "0",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": [
              {
                "operatorId": "EV",
                "stationId": "EV003215",
                "chargerId": "03",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730153610",
                "updateDateTime": "20240730203749",
                "isFast": "N",
                "isAvailable": "Y"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003215",
                "chargerId": "01",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240729114026",
                "updateDateTime": "20240730080132",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003215",
                "chargerId": "02",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730171917",
                "updateDateTime": "20240730172953",
                "isFast": "N",
                "isAvailable": "Y"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003215",
                "chargerId": "04",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730103936",
                "updateDateTime": "20240730191947",
                "isFast": "N",
                "isAvailable": "Y"
              }
            ]
          }
        },
        {
          "id": "10140136",
          "pkey": "1014013601",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤T타워B3 전기차충전소",
          "telNo": "",
          "frontLat": "37.56656541",
          "frontLon": "126.98452047",
          "noorLat": "37.56648210",
          "noorLon": "126.98504820",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "교통편의",
          "middleBizName": "자동차시설",
          "lowerBizName": "전기차충전소",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "6",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56648210",
                "centerLon": "126.98504820",
                "frontLat": "37.56656541",
                "frontLon": "126.98452047",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "0",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": [
              {
                "operatorId": "EV",
                "stationId": "EV003214",
                "chargerId": "04",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730092203",
                "updateDateTime": "20240730093643",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003214",
                "chargerId": "02",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730141739",
                "updateDateTime": "20240730181002",
                "isFast": "N",
                "isAvailable": "Y"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003214",
                "chargerId": "01",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730145834",
                "updateDateTime": "20240730190310",
                "isFast": "N",
                "isAvailable": "Y"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003214",
                "chargerId": "03",
                "status": "1",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240729133209",
                "updateDateTime": "20240730090627",
                "isFast": "N",
                "isAvailable": "N"
              }
            ]
          }
        },
        {
          "id": "10140131",
          "pkey": "1014013101",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤T타워B5 전기차충전소",
          "telNo": "",
          "frontLat": "37.56656541",
          "frontLon": "126.98454825",
          "noorLat": "37.56648210",
          "noorLon": "126.98504820",
          "upperAddrName": "서울",
          "middleAddrName": "중구",
          "lowerAddrName": "을지로2가",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "11",
          "secondNo": "0",
          "roadName": "을지로",
          "firstBuildNo": "65",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "교통편의",
          "middleBizName": "자동차시설",
          "lowerBizName": "전기차충전소",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "6",
          "zipCode": "04539",
          "adminDongCode": "1114055000",
          "legalDongCode": "1114010500",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.56648210",
                "centerLon": "126.98504820",
                "frontLat": "37.56656541",
                "frontLon": "126.98454825",
                "roadName": "을지로",
                "bldNo1": "65",
                "bldNo2": "0",
                "roadId": "00255",
                "fullAddressRoad": "서울 중구 을지로 65"
              }
            ]
          },
          "evChargers": {
            "evCharger": [
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "03",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240724212545",
                "updateDateTime": "20240730182942",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "05",
                "status": "2",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240730082752",
                "updateDateTime": "20240730190025",
                "isFast": "N",
                "isAvailable": "Y"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "04",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240723230014",
                "updateDateTime": "20240724120702",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "01",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240723231805",
                "updateDateTime": "20240724120702",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "02",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240724195416",
                "updateDateTime": "20240729191037",
                "isFast": "N",
                "isAvailable": "N"
              },
              {
                "operatorId": "EV",
                "stationId": "EV003216",
                "chargerId": "06",
                "status": "3",
                "type": "02",
                "powerType": "완속(7kW단독)",
                "operatorName": "에버온",
                "chargingDateTime": "20240729171154",
                "updateDateTime": "20240730075749",
                "isFast": "N",
                "isAvailable": "N"
              }
            ]
          }
        },
        {
          "id": "1130908",
          "pkey": "113090800",
          "navSeq": "0",
          "collectionType": "poi",
          "name": "SK M CITY",
          "telNo": "031-931-9001",
          "frontLat": "37.65385701",
          "frontLon": "126.77175964",
          "noorLat": "37.65438471",
          "noorLon": "126.77070417",
          "upperAddrName": "경기",
          "middleAddrName": "고양시 일산동구",
          "lowerAddrName": "장항동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "869",
          "secondNo": "0",
          "roadName": "백마로",
          "firstBuildNo": "195",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주상복합",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "10403",
          "adminDongCode": "4128559000",
          "legalDongCode": "4128510400",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.65438471",
                "centerLon": "126.77070417",
                "frontLat": "37.65385701",
                "frontLon": "126.77175964",
                "roadName": "백마로",
                "bldNo1": "195",
                "bldNo2": "",
                "roadId": "00109",
                "fullAddressRoad": "경기 고양시 일산동구 백마로 195"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "1130908",
          "pkey": "113090801",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK M CITY 정문",
          "telNo": "031-931-9001",
          "frontLat": "37.65385701",
          "frontLon": "126.77175964",
          "noorLat": "37.65385701",
          "noorLon": "126.77175964",
          "upperAddrName": "경기",
          "middleAddrName": "고양시 일산동구",
          "lowerAddrName": "장항동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "869",
          "secondNo": "0",
          "roadName": "백마로",
          "firstBuildNo": "195",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주상복합",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "10403",
          "adminDongCode": "4128559000",
          "legalDongCode": "4128510400",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.65385701",
                "centerLon": "126.77175964",
                "frontLat": "37.65385701",
                "frontLon": "126.77175964",
                "roadName": "백마로",
                "bldNo1": "195",
                "bldNo2": "",
                "roadId": "00109",
                "fullAddressRoad": "경기 고양시 일산동구 백마로 195"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "1130908",
          "pkey": "113090802",
          "navSeq": "2",
          "collectionType": "poi",
          "name": "SK M CITY 후문",
          "telNo": "031-931-9001",
          "frontLat": "37.65474576",
          "frontLon": "126.77017643",
          "noorLat": "37.65474576",
          "noorLon": "126.77017643",
          "upperAddrName": "경기",
          "middleAddrName": "고양시 일산동구",
          "lowerAddrName": "장항동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "869",
          "secondNo": "0",
          "roadName": "백마로",
          "firstBuildNo": "195",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "건물/시설",
          "middleBizName": "주요건물",
          "lowerBizName": "주상복합",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "10403",
          "adminDongCode": "4128559000",
          "legalDongCode": "4128510400",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.65474576",
                "centerLon": "126.77017643",
                "frontLat": "37.65474576",
                "frontLon": "126.77017643",
                "roadName": "백마로",
                "bldNo1": "195",
                "bldNo2": "",
                "roadId": "00109",
                "fullAddressRoad": "경기 고양시 일산동구 백마로 195"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "8086964",
          "pkey": "808696401",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "커피빈 여의도K타워점",
          "telNo": "02-3468-1600",
          "frontLat": "37.51976429",
          "frontLon": "126.92844357",
          "noorLat": "37.51973651",
          "noorLon": "126.92805472",
          "upperAddrName": "서울",
          "middleAddrName": "영등포구",
          "lowerAddrName": "여의도동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "45",
          "secondNo": "1",
          "roadName": "국제금융로8길",
          "firstBuildNo": "31",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "생활편의",
          "middleBizName": "카페",
          "lowerBizName": "커피전문점",
          "detailBizName": "커피빈",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "07332",
          "adminDongCode": "1156054000",
          "legalDongCode": "1156011000",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.51973651",
                "centerLon": "126.92805472",
                "frontLat": "37.51976429",
                "frontLon": "126.92844357",
                "roadName": "국제금융로8길",
                "bldNo1": "31",
                "bldNo2": "0",
                "roadId": "00070",
                "fullAddressRoad": "서울 영등포구 국제금융로8길 31"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "8086964",
          "pkey": "808696403",
          "navSeq": "3",
          "collectionType": "poi",
          "name": "커피빈 여의도K타워점 주차장",
          "telNo": "02-3468-1600",
          "frontLat": "37.51976429",
          "frontLon": "126.92844357",
          "noorLat": "37.51976429",
          "noorLon": "126.92844357",
          "upperAddrName": "서울",
          "middleAddrName": "영등포구",
          "lowerAddrName": "여의도동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "45",
          "secondNo": "1",
          "roadName": "국제금융로8길",
          "firstBuildNo": "31",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "생활편의",
          "middleBizName": "카페",
          "lowerBizName": "커피전문점",
          "detailBizName": "커피빈",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "07332",
          "adminDongCode": "1156054000",
          "legalDongCode": "1156011000",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.51976429",
                "centerLon": "126.92844357",
                "frontLat": "37.51976429",
                "frontLon": "126.92844357",
                "roadName": "국제금융로8길",
                "bldNo1": "31",
                "bldNo2": "0",
                "roadId": "00070",
                "fullAddressRoad": "서울 영등포구 국제금융로8길 31"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10165080",
          "pkey": "1016508001",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤 HK대리점 동탄영천직영점",
          "telNo": "070-4617-0400",
          "frontLat": "37.20733133",
          "frontLon": "127.09849245",
          "noorLat": "37.20719246",
          "noorLon": "127.09840912",
          "upperAddrName": "경기",
          "middleAddrName": "화성시",
          "lowerAddrName": "영천동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "658",
          "secondNo": "1",
          "roadName": "동탄대로",
          "firstBuildNo": "599",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "쇼핑",
          "middleBizName": "정보통신기기",
          "lowerBizName": "SK텔레콤",
          "detailBizName": "SKT대리점",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "1",
          "desc": "SK텔레콤 공식인증대리점 HK대리점 동탄영천직영점입니다.",
          "dataKind": "",
          "zipCode": "18471",
          "adminDongCode": "4159059000",
          "legalDongCode": "4159013100",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.20719246",
                "centerLon": "127.09840912",
                "frontLat": "37.20733133",
                "frontLon": "127.09849245",
                "roadName": "동탄대로",
                "bldNo1": "599",
                "bldNo2": "0",
                "roadId": "01767",
                "fullAddressRoad": "경기 화성시 동탄대로 599"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10019939",
          "pkey": "1001993901",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "김도희의갈치창고",
          "telNo": "064-712-1802",
          "frontLat": "33.46707731",
          "frontLon": "126.45717132",
          "noorLat": "33.46710508",
          "noorLon": "126.45675469",
          "upperAddrName": "제주",
          "middleAddrName": "제주시",
          "lowerAddrName": "해안동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "2171",
          "secondNo": "0",
          "roadName": "노형로",
          "firstBuildNo": "121",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "생활편의",
          "middleBizName": "음식점",
          "lowerBizName": "한식",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "1",
          "desc": "애월에서는 이름만 걸고 영업했는데 이전하고는 얼굴까지 걸고 영업 개시했습니다. 오시는 손님마다 제주은갈치조림과 통갈치구이 등 갈치요리 찐맛집이라고 엄지척! 하는 대한민국 최고의 갈치전문식당을 지향하는 갈치맛집입니다. 엄청난 홍보비용으로 호객 행위를 하는 관광객을 1회성 소비자로 보는  몇몇 유명 관광식당들과는 달리 오시는 한 분 한 분 평생 고객으로 생각하고 만족한 식사를 하고 가실 수 있도록 최고의 맛을 낼 수 있도록 노력하고 있으며, 실제로 재방문율이 아주 높습니다. 2021년 9월 25일 이전 첫날, 네이버플레이스를 제외한 온라인-일반네비게이션 주소 변경이 되지 않은 상황에서도 수십 팀이 소개 받고, 재방문으로..전화로 물어 물어 찾아올 정도네요.\n애월 하귀에서 2019년 10월 14평 작은 규모로 오픈, 개업한지 얼마되지 않은 2020년 초 코로나사태가 발생했으나 개업 초기부터 맛집으로 입소문을 타 코로나 정국속에서도 많은 분들이 찾아주셔서 좁은 가게로는 더 이상 감당이 안 돼, 보다 쾌적하고 편안하게 식사하고 가실 수 있도록 개업 2년이 안 되어 100여평 넓은 가게를 얻어 확장 이전하게 되었습니다. \n재료 신선도 보장합니다. \n맛 보장합니다.\n갈치 퀄리티 대비 가성비 보장합니다.\n위생, 청결, 친절은 기본입니다.\n저희는 집밥 + 갈치전문식당의 컨셉으로 100% 직접 만든 집반찬 제공합니다. 가격상승요인인 곁반찬(일명 스끼다시)은 제공하지 않습니다. 문어/전복/새우 등 갈치 본연의 맛을 지워버리는 각종 해산물 넣고 통갈치조림으로 비주얼 장사하는 유명 식당들에 현혹되지 마시고 갈치 자체의 맛을 극대화시킨 저희 조림/통갈치구이 드시러 오세요. 밤새 잡은 우주 최고 신선도의 당일바리갈치 도매가로 전국택배 판매하니 참조하세요.\n코로나 때문에 고가의 바이러스 클린존을 설치하고, 홀에 식탁을 다 채우지 않고 넓게 배치하였으니 안심하고 방문하십시오.\n각종 광고 대행 연락 사절! 각종 포스팅, 리뷰(후기) 유인 인센티브 운영하지 않습니다. 감사합니다.",
          "dataKind": "",
          "zipCode": "63076",
          "adminDongCode": "5011025300",
          "legalDongCode": "5011013900",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "33.46710508",
                "centerLon": "126.45675469",
                "frontLat": "33.46707731",
                "frontLon": "126.45717132",
                "roadName": "노형로",
                "bldNo1": "121",
                "bldNo2": "0",
                "roadId": "00452",
                "fullAddressRoad": "제주 제주시 노형로 121"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10019939",
          "pkey": "1001993902",
          "navSeq": "2",
          "collectionType": "poi",
          "name": "김도희의갈치창고 주차장",
          "telNo": "064-712-1802",
          "frontLat": "33.46707731",
          "frontLon": "126.45717132",
          "noorLat": "33.46707731",
          "noorLon": "126.45717132",
          "upperAddrName": "제주",
          "middleAddrName": "제주시",
          "lowerAddrName": "해안동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "2171",
          "secondNo": "0",
          "roadName": "노형로",
          "firstBuildNo": "121",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "생활편의",
          "middleBizName": "음식점",
          "lowerBizName": "한식",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "1",
          "desc": "애월에서는 이름만 걸고 영업했는데 이전하고는 얼굴까지 걸고 영업 개시했습니다. 오시는 손님마다 제주은갈치조림과 통갈치구이 등 갈치요리 찐맛집이라고 엄지척! 하는 대한민국 최고의 갈치전문식당을 지향하는 갈치맛집입니다. 엄청난 홍보비용으로 호객 행위를 하는 관광객을 1회성 소비자로 보는  몇몇 유명 관광식당들과는 달리 오시는 한 분 한 분 평생 고객으로 생각하고 만족한 식사를 하고 가실 수 있도록 최고의 맛을 낼 수 있도록 노력하고 있으며, 실제로 재방문율이 아주 높습니다. 2021년 9월 25일 이전 첫날, 네이버플레이스를 제외한 온라인-일반네비게이션 주소 변경이 되지 않은 상황에서도 수십 팀이 소개 받고, 재방문으로..전화로 물어 물어 찾아올 정도네요.\n애월 하귀에서 2019년 10월 14평 작은 규모로 오픈, 개업한지 얼마되지 않은 2020년 초 코로나사태가 발생했으나 개업 초기부터 맛집으로 입소문을 타 코로나 정국속에서도 많은 분들이 찾아주셔서 좁은 가게로는 더 이상 감당이 안 돼, 보다 쾌적하고 편안하게 식사하고 가실 수 있도록 개업 2년이 안 되어 100여평 넓은 가게를 얻어 확장 이전하게 되었습니다. \n재료 신선도 보장합니다. \n맛 보장합니다.\n갈치 퀄리티 대비 가성비 보장합니다.\n위생, 청결, 친절은 기본입니다.\n저희는 집밥 + 갈치전문식당의 컨셉으로 100% 직접 만든 집반찬 제공합니다. 가격상승요인인 곁반찬(일명 스끼다시)은 제공하지 않습니다. 문어/전복/새우 등 갈치 본연의 맛을 지워버리는 각종 해산물 넣고 통갈치조림으로 비주얼 장사하는 유명 식당들에 현혹되지 마시고 갈치 자체의 맛을 극대화시킨 저희 조림/통갈치구이 드시러 오세요. 밤새 잡은 우주 최고 신선도의 당일바리갈치 도매가로 전국택배 판매하니 참조하세요.\n코로나 때문에 고가의 바이러스 클린존을 설치하고, 홀에 식탁을 다 채우지 않고 넓게 배치하였으니 안심하고 방문하십시오.\n각종 광고 대행 연락 사절! 각종 포스팅, 리뷰(후기) 유인 인센티브 운영하지 않습니다. 감사합니다.",
          "dataKind": "",
          "zipCode": "63076",
          "adminDongCode": "5011025300",
          "legalDongCode": "5011013900",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "33.46707731",
                "centerLon": "126.45717132",
                "frontLat": "33.46707731",
                "frontLon": "126.45717132",
                "roadName": "노형로",
                "bldNo1": "121",
                "bldNo2": "0",
                "roadId": "00452",
                "fullAddressRoad": "제주 제주시 노형로 121"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "8534096",
          "pkey": "853409601",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "에이미스커피 가산SK트윈타워점",
          "telNo": "02-355-1911",
          "frontLat": "37.47562971",
          "frontLon": "126.88292118",
          "noorLat": "37.47562971",
          "noorLon": "126.88292118",
          "upperAddrName": "서울",
          "middleAddrName": "금천구",
          "lowerAddrName": "가산동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "345",
          "secondNo": "9",
          "roadName": "가산디지털1로",
          "firstBuildNo": "119",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "생활편의",
          "middleBizName": "카페",
          "lowerBizName": "카페기타",
          "detailBizName": "기타",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "08589",
          "adminDongCode": "1154551000",
          "legalDongCode": "1154510100",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.47562971",
                "centerLon": "126.88292118",
                "frontLat": "37.47562971",
                "frontLon": "126.88292118",
                "roadName": "가산디지털1로",
                "bldNo1": "119",
                "bldNo2": "",
                "roadId": "00002",
                "fullAddressRoad": "서울 금천구 가산디지털1로 119"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10165066",
          "pkey": "1016506601",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤 PS&M 둔산본점",
          "telNo": "070-7470-7641",
          "frontLat": "36.35176825",
          "frontLon": "127.38790662",
          "noorLat": "36.35146273",
          "noorLon": "127.38793441",
          "upperAddrName": "대전",
          "middleAddrName": "서구",
          "lowerAddrName": "둔산동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "1455",
          "secondNo": "0",
          "roadName": "둔산로",
          "firstBuildNo": "125",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "쇼핑",
          "middleBizName": "정보통신기기",
          "lowerBizName": "SK텔레콤",
          "detailBizName": "SKT대리점",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "1",
          "desc": "기계식 주차장으로 승용차만 가능합니다. 2시간 지원됩니다.",
          "dataKind": "",
          "zipCode": "35240",
          "adminDongCode": "3017063000",
          "legalDongCode": "3017011200",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "36.35146273",
                "centerLon": "127.38793441",
                "frontLat": "36.35176825",
                "frontLon": "127.38790662",
                "roadName": "둔산로",
                "bldNo1": "125",
                "bldNo2": "0",
                "roadId": "00342",
                "fullAddressRoad": "대전 서구 둔산로 125"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "10165066",
          "pkey": "1016506602",
          "navSeq": "2",
          "collectionType": "poi",
          "name": "SK텔레콤 PS&M 둔산본점 주차장",
          "telNo": "070-7470-7641",
          "frontLat": "36.35176825",
          "frontLon": "127.38790662",
          "noorLat": "36.35176825",
          "noorLon": "127.38790662",
          "upperAddrName": "대전",
          "middleAddrName": "서구",
          "lowerAddrName": "둔산동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "1455",
          "secondNo": "0",
          "roadName": "둔산로",
          "firstBuildNo": "125",
          "secondBuildNo": "0",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "쇼핑",
          "middleBizName": "정보통신기기",
          "lowerBizName": "SK텔레콤",
          "detailBizName": "SKT대리점",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "1",
          "desc": "기계식 주차장으로 승용차만 가능합니다. 2시간 지원됩니다.",
          "dataKind": "",
          "zipCode": "35240",
          "adminDongCode": "3017063000",
          "legalDongCode": "3017011200",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "36.35176825",
                "centerLon": "127.38790662",
                "frontLat": "36.35176825",
                "frontLon": "127.38790662",
                "roadName": "둔산로",
                "bldNo1": "125",
                "bldNo2": "0",
                "roadId": "00342",
                "fullAddressRoad": "대전 서구 둔산로 125"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "7402574",
          "pkey": "740257401",
          "navSeq": "1",
          "collectionType": "poi",
          "name": "SK텔레콤 코넥대리점 위례광장직영점",
          "telNo": "031-759-5530",
          "frontLat": "37.47330144",
          "frontLon": "127.14975808",
          "noorLat": "37.47352364",
          "noorLon": "127.15006360",
          "upperAddrName": "경기",
          "middleAddrName": "성남시 수정구",
          "lowerAddrName": "창곡동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "513",
          "secondNo": "0",
          "roadName": "위례동로",
          "firstBuildNo": "153",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "쇼핑",
          "middleBizName": "정보통신기기",
          "lowerBizName": "SK텔레콤",
          "detailBizName": "SKT대리점",
          "rpFlag": "16",
          "parkFlag": "1",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "13642",
          "adminDongCode": "4113162500",
          "legalDongCode": "4113110800",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.47352364",
                "centerLon": "127.15006360",
                "frontLat": "37.47330144",
                "frontLon": "127.14975808",
                "roadName": "위례동로",
                "bldNo1": "153",
                "bldNo2": "",
                "roadId": "00661",
                "fullAddressRoad": "경기 성남시 수정구 위례동로 153"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        },
        {
          "id": "7402574",
          "pkey": "740257402",
          "navSeq": "2",
          "collectionType": "poi",
          "name": "SK텔레콤 코넥대리점 위례광장직영점 주차장",
          "telNo": "031-759-5530",
          "frontLat": "37.47330144",
          "frontLon": "127.14975808",
          "noorLat": "37.47330144",
          "noorLon": "127.14975808",
          "upperAddrName": "경기",
          "middleAddrName": "성남시 수정구",
          "lowerAddrName": "창곡동",
          "detailAddrName": "",
          "mlClass": "1",
          "firstNo": "513",
          "secondNo": "0",
          "roadName": "위례동로",
          "firstBuildNo": "153",
          "secondBuildNo": "",
          "radius": "0.0",
          "bizName": "",
          "upperBizName": "쇼핑",
          "middleBizName": "정보통신기기",
          "lowerBizName": "SK텔레콤",
          "detailBizName": "SKT대리점",
          "rpFlag": "16",
          "parkFlag": "0",
          "detailInfoFlag": "0",
          "desc": "",
          "dataKind": "",
          "zipCode": "13642",
          "adminDongCode": "4113162500",
          "legalDongCode": "4113110800",
          "newAddressList": {
            "newAddress": [
              {
                "centerLat": "37.47330144",
                "centerLon": "127.14975808",
                "frontLat": "37.47330144",
                "frontLon": "127.14975808",
                "roadName": "위례동로",
                "bldNo1": "153",
                "bldNo2": "",
                "roadId": "00661",
                "fullAddressRoad": "경기 성남시 수정구 위례동로 153"
              }
            ]
          },
          "evChargers": {
            "evCharger": []
          }
        }
      ]
    }
  }
}

Tmap openapi 파라미터 중 에 필요한 정보를 찾아보자면요.

검색하는데 searchKeyword 가 존재하는데 가장 중요한 파라미터입니다. 

그리고 아래 파라미터들도 중요하겠죠?

그리고 검색 반경이나  count , mutipoint 등도 눈여겨 볼만합니다. 

아무튼, 저는 Tmap openapi를 공부해서 테스트도 해보고 파라미터들도 눈여겨보면서 어떻게 구현할지 머릿속에 정리해봅니다. 

그리고 머리속에 정리한 내용을 토대로 제가 구해야할 함수는 아래와 같이 2가지 정도를 구현하면 될것 같다는 생각이 듭니다. 

우선, 기준이 될 위치의 경도와 위도를 가져올 함수를 작성합니다. 
둘, 기준이 될 위치의 경도와 위도에서 2km 반경에 음식점을 조회하는 함수를 작성합니다. 

아래와 같이 함수를 구현합니다. 

1. 기준위치 

특정 위치 keyword를 파라미터로 받고, POI 정보를 리턴하면 될것 같습니다. 

// POI 데이터를 검색하는 함수 정의
func getPOIByKeyword(keyword string) (*POI, error) {
	// URL 인코딩
	encodedKeyword := url.QueryEscape(keyword)

	// Tmap API URL 생성
	url := fmt.Sprintf("https://apis.openapi.sk.com/tmap/pois?version=1&appKey=%s&searchKeyword=%s", TmapApiKey, encodedKeyword)

	// HTTP GET 요청
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// JSON 응답 파싱
	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	pois := result["searchPoiInfo"].(map[string]interface{})["pois"].(map[string]interface{})["poi"]

	var retPOI *POI

	for _, poi := range pois.([]interface{}) {
		item := poi.(map[string]interface{})

		Name := item["name"].(string)
		noorLat := item["noorLat"].(string)
		noorLon := item["noorLon"].(string)

		fmt.Printf("검색키워드[%s] : POI 반환위치[%s] 위도[%s] 경도[%s]\n", keyword, Name, noorLat, noorLon)

		retPOI = &POI{
			Latitude:  noorLat,
			Longitude: noorLon,
			Name:      Name,
		}

		break
	}

	return retPOI, nil
}

2.기준위치 반경 2km 음식점 

위 함수에서 구한 기준 위치의 위도과 경도를 파라미터로 받고 radius 를 2로 주며, multipoint 를 Y 로 주게 되면 드디어 원하던 주변 음식점 정보를 얻어올 수 있습니다. 

func findRestaurants(centerLat string, centerLon string) ([]string, error) {

	endpoint := "https://apis.openapi.sk.com/tmap/pois?version=1&format=json"

	params := url.Values{}
	params.Set("appKey", TmapApiKey)
	params.Set("searchKeyword", "음식점")
	params.Set("centerLat", centerLat)
	params.Set("centerLon", centerLon)
	params.Set("radius", "2") // 2km 반경
	params.Set("count", "5")
	params.Set("multiPoint", "Y")

	reqURL := fmt.Sprintf("%s&%s", endpoint, params.Encode())
	resp, err := http.Get(reqURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	pois := result["searchPoiInfo"].(map[string]interface{})["pois"].(map[string]interface{})["poi"]
	var restaurantInfo []string
	for _, poi := range pois.([]interface{}) {
		item := poi.(map[string]interface{})

		name := item["name"].(string)
		radius, err := strconv.ParseFloat(item["radius"].(string), 64)

		if err != nil {
			log.Fatalf("Error converting string to float64: %v", err)
		}

		desc := "정보없음"
		if value, ok := item["desc"].(string); ok && value != "" {
			desc = strings.ReplaceAll(value, "%", "프로")
			desc = strings.ReplaceAll(desc, "\n", " ") // 줄 바꿈을 공백으로 변경
		}

		radiusStr := formatRadius(radius)

		lat := item["noorLat"].(string)
		lon := item["noorLon"].(string)

		googleMapURI := fmt.Sprintf(`<a href="https://www.google.com/maps?q=%s,%s" target="_blank">구글지도보기</a>`, lat, lon)

		restaurantInfo = append(restaurantInfo, fmt.Sprintf("이름: %s\n주소: %s\n전화번호: %s\n특징: %s\n반경: %s\n%s\n",
			name,
			item["newAddressList"].(map[string]interface{})["newAddress"].([]interface{})[0].(map[string]interface{})["fullAddressRoad"].(string),
			item["telNo"].(string),
			desc,
			radiusStr,
			googleMapURI,
		))
	}

	return restaurantInfo, nil
}

아래는 gin 프레임워크를 활용한 전체 코드입니다. 

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
)

const telegramBotToken = "텔레그램봇 토큰정보"
const telegramChannelID = 텔레그램봇 채널ID
const TmapApiKey = "SK openapi Appkey"

// POI 정보를 담는 구조체 정의
type POI struct {
	Latitude  string `json:"noorLat"`
	Longitude string `json:"noorLon"`
	Name      string `json:"name"`
}

// RequestData 구조체 정의
type RequestData struct {
	Msg        string `json:"msg"`
	SenderName string `json:"sender_name"`
}

func formatRadius(radius float64) string {
	if radius < 1 {
		// radius가 1보다 작은 경우 미터 단위로 표시
		meters := radius * 1000 // 미터 단위로 변환
		return fmt.Sprintf("%.0fm", meters)
	} else {
		// radius가 1 이상인 경우 킬로미터 단위로 표시
		return fmt.Sprintf("%.1fkm", radius)
	}
}

// POI 데이터를 검색하는 함수 정의
func getPOIByKeyword(keyword string) (*POI, error) {
	// URL 인코딩
	encodedKeyword := url.QueryEscape(keyword)

	// Tmap API URL 생성
	url := fmt.Sprintf("https://apis.openapi.sk.com/tmap/pois?version=1&appKey=%s&searchKeyword=%s", TmapApiKey, encodedKeyword)

	// HTTP GET 요청
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// JSON 응답 파싱
	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	pois := result["searchPoiInfo"].(map[string]interface{})["pois"].(map[string]interface{})["poi"]

	var retPOI *POI

	for _, poi := range pois.([]interface{}) {
		item := poi.(map[string]interface{})

		Name := item["name"].(string)
		noorLat := item["noorLat"].(string)
		noorLon := item["noorLon"].(string)

		fmt.Printf("검색키워드[%s] : POI 반환위치[%s] 위도[%s] 경도[%s]\n", keyword, Name, noorLat, noorLon)

		retPOI = &POI{
			Latitude:  noorLat,
			Longitude: noorLon,
			Name:      Name,
		}

		break
	}

	return retPOI, nil
}

func findRestaurants(centerLat string, centerLon string) ([]string, error) {

	endpoint := "https://apis.openapi.sk.com/tmap/pois?version=1&format=json"

	params := url.Values{}
	params.Set("appKey", TmapApiKey)
	params.Set("searchKeyword", "음식점")
	params.Set("centerLat", centerLat)
	params.Set("centerLon", centerLon)
	params.Set("radius", "2") // 2km 반경
	params.Set("count", "5")
	params.Set("multiPoint", "Y")

	reqURL := fmt.Sprintf("%s&%s", endpoint, params.Encode())
	resp, err := http.Get(reqURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	var result map[string]interface{}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return nil, err
	}

	pois := result["searchPoiInfo"].(map[string]interface{})["pois"].(map[string]interface{})["poi"]
	var restaurantInfo []string
	for _, poi := range pois.([]interface{}) {
		item := poi.(map[string]interface{})

		name := item["name"].(string)
		radius, err := strconv.ParseFloat(item["radius"].(string), 64)

		if err != nil {
			log.Fatalf("Error converting string to float64: %v", err)
		}

		desc := "정보없음"
		if value, ok := item["desc"].(string); ok && value != "" {
			desc = strings.ReplaceAll(value, "%", "프로")
			desc = strings.ReplaceAll(desc, "\n", " ") // 줄 바꿈을 공백으로 변경
		}

		radiusStr := formatRadius(radius)

		lat := item["noorLat"].(string)
		lon := item["noorLon"].(string)

		googleMapURI := fmt.Sprintf(`<a href="https://www.google.com/maps?q=%s,%s" target="_blank">구글지도보기</a>`, lat, lon)

		restaurantInfo = append(restaurantInfo, fmt.Sprintf("이름: %s\n주소: %s\n전화번호: %s\n특징: %s\n반경: %s\n%s\n",
			name,
			item["newAddressList"].(map[string]interface{})["newAddress"].([]interface{})[0].(map[string]interface{})["fullAddressRoad"].(string),
			item["telNo"].(string),
			desc,
			radiusStr,
			googleMapURI,
		))
	}

	return restaurantInfo, nil
}

func restaurantInfo(requestData *RequestData) string {
	message := "맛집을 찾을 수 없네요"

	poi, err := getPOIByKeyword(requestData.Msg)

	if err != nil {
		return message
	}

	restaurantInfo, err := findRestaurants(poi.Latitude, poi.Longitude)

	if err != nil {
		return message
	}

	restaurantInfoStr := strings.Join(restaurantInfo, "\n")

	message = fmt.Sprintf("To.%s님\n[오늘의 맛집(%s)]\n%s\n",
		requestData.SenderName, requestData.Msg, restaurantInfoStr)

	return message
}

func sendToTelegram(message string) error {

	bot, err := tgbotapi.NewBotAPI(telegramBotToken)
	if err != nil {
		return err
	}

	msg := tgbotapi.NewMessage(telegramChannelID, message)
	msg.ParseMode = "HTML"

	_, err = bot.Send(msg)

	return err
}

func tmapRestaurant(c *gin.Context) {
	requestData := &RequestData{}

	if err := c.ShouldBindJSON(&requestData); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"code": 200, "msg": "JSON data parsing error"})
		fmt.Printf("JSON data parsing error:", err)
		return
	}

	fmt.Printf("Message[%s] SenderName[%s]\n", requestData.Msg, requestData.SenderName)

	var message string
	message = restaurantInfo(requestData)

	// 메시지 전송
	sendErr := sendToTelegram(message)
	if sendErr != nil {
		fmt.Printf("Today 메시지 전송 중 오류 발생:", sendErr)
		return
	}

	c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "Message sent successfully"})
}

func main() {
	//Gin 라우터 설정
	r := gin.New()

	r.POST("/tmap/restaurant", tmapRestaurant)

	//서버 실행
	go func() {
		err := r.Run(":" + "18082")
		if err != nil {
			fmt.Printf("Failed to start server:", err)
		}
	}()

	select {}
}

코드 작성을 완료했으면 아래와 같이 go 를 빌드하고 실행합니다. 

그리고 insomnia 툴을 사용해서 테스트 요청을 전송합니다. 

msg : SKT타워
sender_name : 매직

그러면 위와 같이 정상적으로 전송했다는 200 OK 코드를 받게되고요...

아래와 같이 텔레그램봇이 있는 방으로 메시지가 수신됩니다. 

그리고 명동교자 본점의 구글지도보기 링크를 클릭하면 아래와 같이 구글 지도로도 위치를 확인할 수 있습니다.

여기까지가 제가 한번 Tmap openapi 를 활용해서 golang 과 gin 프레임워크 으로 구현한 주변맛집 검색 기능입니다. 

항상 믿고 봐주셔서 감사합니다. 

 

728x90
300x250