본문 바로가기

프로그래밍/안드로이드

[Android/KakaoAPI] 카카오 장소 검색 (Retrofit)

카카오에서 제공하는 API 중에는 REST API를 통한 장소 검색 기능이 있다. 이 글에서는 Retrofit 라이브러리를 이용해서 API 서버와 통신해 장소 검색 결과를 가져오는 방법을 적는다.

 

Kakao Developers | 로컬

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com


Retrofit 라이브러리 추가

앱에서 REST API를 이용하기 위해서는 Retrofit 라이브러리를 이용해야 한다. 앱 Gradle에 다음을 추가한다.

(혹시 REST API가 뭔지 궁금하시다면... 구글에 검색해주세요 저도 자세히는 몰라요)

 

build.gradle (:app)
 
dependencies {
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}

준비작업

라이브러리를 추가했다면 먼저 검색 결과를 담을 클래스와 통신에 사용하는 인터페이스를 만들어야 한다.

검색 시의 매개변수와, 검색 결과 데이터에 대한 자세한 정보는 아래 링크에서 확인한다.

 

Kakao Developers | 키워드로 장소 검색

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

 

우선 검색 결과를 담는 클래스다. ResultSearchKeyword.kt 라는 파일로 생성했다.

 

ResultSearchKeyword.kt
 
// 검색 결과를 담는 클래스
data class ResultSearchKeyword(
    var meta: PlaceMeta,                // 장소 메타데이터
    var documents: List<Place>          // 검색 결과
)

data class PlaceMeta(
    var total_count: Int,               // 검색어에 검색된 문서 수
    var pageable_count: Int,            // total_count 중 노출 가능 문서 수, 최대 45 (API에서 최대 45개 정보만 제공)
    var is_end: Boolean,                // 현재 페이지가 마지막 페이지인지 여부, 값이 false면 page를 증가시켜 다음 페이지를 요청할 수 있음
    var same_name: RegionInfo           // 질의어의 지역 및 키워드 분석 정보
)

data class RegionInfo(
    var region: List<String>,           // 질의어에서 인식된 지역의 리스트, ex) '중앙로 맛집' 에서 중앙로에 해당하는 지역 리스트
    var keyword: String,                // 질의어에서 지역 정보를 제외한 키워드, ex) '중앙로 맛집' 에서 '맛집'
    var selected_region: String         // 인식된 지역 리스트 중, 현재 검색에 사용된 지역 정보
)

data class Place(
    var id: String,                     // 장소 ID
    var place_name: String,             // 장소명, 업체명
    var category_name: String,          // 카테고리 이름
    var category_group_code: String,    // 중요 카테고리만 그룹핑한 카테고리 그룹 코드
    var category_group_name: String,    // 중요 카테고리만 그룹핑한 카테고리 그룹명
    var phone: String,                  // 전화번호
    var address_name: String,           // 전체 지번 주소
    var road_address_name: String,      // 전체 도로명 주소
    var x: String,                      // X 좌표값 혹은 longitude
    var y: String,                      // Y 좌표값 혹은 latitude
    var place_url: String,              // 장소 상세페이지 URL
    var distanc: String                 // 중심좌표까지의 거리. 단, x,y 파라미터를 준 경우에만 존재. 단위는 meter
)

위 코드에서는 서버에서 받을 수 있는 정보를 모두 받아오게 해 놨다.

모든 정보가 필요한 게 아니라면 아래와 같이 필요한 정보에 대한 변수만 남기고 제거해도 상관없다.

 

ResultSearchKeyword.kt
 
// 장소명, 주소, 좌표만 받는 클래스
data class ResultSearchKeyword(
    var documents: List<Place>          // 검색 결과
)

data class Place(
    var place_name: String,             // 장소명, 업체명
    var address_name: String,           // 전체 지번 주소
    var road_address_name: String,      // 전체 도로명 주소
    var x: String,                      // X 좌표값 혹은 longitude
    var y: String,                      // Y 좌표값 혹은 latitude
)

 

다음은 API 서버와 통신 시에 사용하는 인터페이스다. KakaoAPI.kt 라는 파일로 생성했다.

 

KakaoAPI.kt
 
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface KakaoAPI {
    @GET("v2/local/search/keyword.json")    // Keyword.json의 정보를 받아옴
    fun getSearchKeyword(
        @Header("Authorization") key: String,     // 카카오 API 인증키 [필수]
        @Query("query") query: String             // 검색을 원하는 질의어 [필수]
        // 매개변수 추가 가능
        // @Query("category_group_code") category: String

    ): Call<ResultSearchKeyword>    // 받아온 정보가 ResultSearchKeyword 클래스의 구조로 담김
}

검색 조건을 더 추가하고 싶다면 @Query('매개변수 이름')을 이용해서 매개변수를 추가하면 된다. 추가 가능한 매개변수는 상단의 링크를 참고한다.

검색하기

준비를 모두 마쳤으니 사용할 일만 남았다. 아래는 메인 액티비티 코드다.

 

MainActivity.kt
 
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.mechacat.databinding.ActivityMainBinding
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding

    companion object {
        const val BASE_URL = "https://dapi.kakao.com/"
        const val API_KEY = "KakaoAK XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  // REST API 키
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        searchKeyword("은행")

    }

    // 키워드 검색 함수
    private fun searchKeyword(keyword: String) {
        val retrofit = Retrofit.Builder()   // Retrofit 구성
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        val api = retrofit.create(KakaoAPI::class.java)   // 통신 인터페이스를 객체로 생성
        val call = api.getSearchKeyword(API_KEY, keyword)   // 검색 조건 입력

        // API 서버에 요청
        call.enqueue(object: Callback<ResultSearchKeyword> {
            override fun onResponse(
                call: Call<ResultSearchKeyword>,
                response: Response<ResultSearchKeyword>
            ) {
                // 통신 성공 (검색 결과는 response.body()에 담겨있음)
                Log.d("Test", "Raw: ${response.raw()}")
                Log.d("Test", "Body: ${response.body()}")
            }

            override fun onFailure(call: Call<ResultSearchKeyword>, t: Throwable) {
                // 통신 실패
                Log.w("MainActivity", "통신 실패: ${t.message}")
            }
        })
    }
    
}

여기서 XXX 부분을 본인의 REST API 키로 바꿔주면 된다. REST API 키는 카카오 개발자 사이트의 애플리케이션 페이지에서 확인할 수 있다.

검색 조건 입력에서는 자신이 추가한 매개변수의 개수만큼 인자를 적어준다.

 

실행 결과

실행 결과

검색 결과가 ResultSearchKeyword 클래스의 객체로 반환된다.

 

참고사진. API키가 잘못되었을 경우

참고로 API를 잘못 입력하면 message에 Unauthorized가 나타난다.

 

기타 정보

1. 카카오 로컬 검색 API의 일일 제공량은 100,000건이다.

2. 매개변수로 좌표를 넣어주지 않으면 서울시청을 중심으로 검색한다. (지도 처음 나오면 보이는 곳)

3. 로컬 검색 API는 상위 45개의 검색 결과만 이용할 수 있다.

(예를 들어, "은행"이라는 키워드로 검색 시 검색 결과는 43,842개인데 이 중 상위 45개의 정보만 이용할 수 있으며, 나머지 정보는 이용할 수 없다. 원하는 정보를 얻으려면 키워드를 자세하게 쓰거나 조건을 더 줘서 검색 범위를 좁혀야 한다.)