구현할 내용
- 카카오맵 현재위치를 기준으로 상호명을 검색하여 마커 표시
- 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}")
}
})
}
}
}