구현할 내용
- 카카오맵 현재위치를 기준으로 상호명을 검색하여 마커 표시
- MainActivity는 4. 카카오맵 API로 지도 생성에서 이어짐
이전에는 OkHttp3을 이용하였으나, 이번에는 Retrofit을 사용하여 서버통신을 하게 되었다.
Retrofit은 OkHttp에 비해 Annotation의 사용으로 코드의 가독성이 좋고, 직관적인 설계가 가능하다는 장점이 있다. 또한 JSON으로 변환할 필요가 있었던 OkHttp와는 달리 결과값을 메인스레드에서 바로 사용할 수 있다는 장점이 있다.
그러나, OkHttp는 Client Intercepter로 통신 상황을 모니터링 할 수 있고 서버 통신 시간 조절이 가능하다는 장점이 있기 때문에 어느 쪽이 더 우월하다고는 할 수 없는 것으로 보인다.
아래는 구현 내용을 적용한 코드이다.
dependencies에 Retrofit 라이브러리 추가
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
검색 결과를 담기 위한 클래스
장소 이름과 좌표 정도만 표시하기 위해 간략화된 형태를 채택
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
)
interface KakaoAPI {
@GET("v2/local/search/keyword.json") // Keyword.json의 정보를 받아옴
fun getSearchKeyword(
@Header("Authorization") key: String, // 카카오 API 인증키
@Query("query") query: String // 검색을 원하는 질의어
): Call<ResultSearchKeyword>
}
companion object {
const val BASE_URL = "https://dapi.kakao.com/"
const val API_KEY = "KakaoAK (여기에 REST API 키)"
}
override fun onCreate(savedInstanceState: Bundle?) {
// 생략
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", "Body: ${response.body()}")
val places = response.body()?.documents
if (places != null) {
for (place in places) {
// val place = places[0]
// Log.d("Test", "Body: ${place}")
val marker = MapPOIItem()
marker.itemName = place.place_name
marker.mapPoint =
MapPoint.mapPointWithGeoCoord(place.y.toDouble(), place.x.toDouble())
marker.markerType = MapPOIItem.MarkerType.BluePin
mapView.addPOIItem(marker)
}
}
}
override fun onFailure(call: Call<ResultSearchKeyword>, t: Throwable) {
// 통신 실패
Log.w("MainActivity", "통신 실패: ${t.message}")
}
})
}
}
}