https://navermaps.github.io/android-map-sdk/guide-ko/5-8.html
화면에 대량의 마커가 노출되면 성능이 저하될 뿐만 아니라 여러 마커가 겹쳐서 눈에 쉽게 보이지 않을 것이다. 이때 사용할 수 있는 것이 마커 클러스터링이다.
마커 클러스터링 기능을 이용하려면 데이터의 키를 의미하는 ClusteringKey
인터페이스를 구현한 클래스를 정의해야 한다. ClusteringKey
인터페이스는 데이터의 좌표뿐만 아니라 두 데이터가 동일한지를 정의한다. 따라서 이 인터페이스를 구현하는 클래스는 equals()
및 hashCode()
도 구현하는 것이 권장된다.
아래가 문서에 나와있는 ClusteringKey
를 구현하는 클래스를 정의하는 예제인데 코틀린의 data class를 이용하면 equals()
와 hashCode()
를 굳이 구현하지 않아도 될 것 같다.
class ItemKey(val id: Int, private val position: LatLng) : ClusteringKey {
override fun getPosition() = position
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
val itemKey = other as ItemKey
return id == itemKey.id
}
override fun hashCode() = id
}
data class는 equals()
, hashCode()
, toString()
, componentN()
, copy()
를 기본적으로 구현해주기 때문이다.
data class ItemKey(val id: Int, private val position: LatLng) : ClusteringKey {
override fun getPosition() = position
}
나는 ClusteringKey가 해당 마커가 어떤 정보를 가지고 있는지를 정의하는 것이라고 이해했다. 프로젝트에서 마커는 픽의 정보를 가지고 있어야 하므로 아래처럼 키를 정의했다.
data class MarkerKey(val pick: Pick) : ClusteringKey {
override fun getPosition() = LatLng(pick.location.latitude, pick.location.longitude)
}
실제 클러스터링 동작은 Clusterer
객체가 수행한다. 이 클래스의 인스턴스는 직접 생성할 수 없고 Clusterer.Builder
나 Clusterer.ComplexBuilder
빌더 클래스를 사용하여 생성할 수 있다. Clusterer.Builder
는 데이터의 키를 의미하는 타입 파라미터가 필요하므로 앞서 정의한 클래스(ItemKey)를 지정하고, build()
를 호출하면 Clusterer 객체가 생성된다.
val clusterer: Clusterer<ItemKey> = Clusterer.Builder<ItemKey>().build()
Clusterer.Builder로 생성한 Clusterer 객체는 기본적인 기능을 제공하고, Clusterer.ComplexBuilder로 생성한 Clusterer 객체는 복잡한 전략과 기능을 제공한다. 말만 들어서는 잘 모르겠지만 각각의 공식문서에서 제공하는 메서드를 보면 확실히 차이가 있음을 알 수 있다.