Today's

길을 나서지 않으면 그 길에서 만날 수 있는 사람을 만날 수 없다

모바일 앱(안드로이드)

Android에서 Kakao 로컬 API로 주소/좌표 변환하기 : 앱에 적용해 보기.

Billcorea 2025. 7. 21. 15:47
반응형

 

📍 Android에서 Kakao 로컬 API로 주소/좌표 변환하기

주소검색

 

이 글에서는 안드로이드 앱에서 Kakao REST API를 사용하여 좌표 → 주소 변환, 주소 → 좌표 변환을 구현하는 방법을 설명합니다.
초보 개발자도 쉽게 따라 할 수 있도록 Retrofit2 + Coroutine + ViewModel 기반으로 단계별로 안내합니다.


✅ 1. 사전 준비

1.1. Kakao REST API 키 발급

  • 카카오 개발자 사이트에 로그인
  • 애플리케이션 등록 → 앱 키 → REST API 키 복사
  • Android 플랫폼 등록 → 패키지명 + 키 해시 입력 (중요!)

1.2. Android 권한 설정

AndroidManifest.xml에 다음 권한을 추가하세요.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

위치 권한은 런타임 요청이 필요합니다 (Activity나 Composable에서).

---

✅ 2. Gradle 설정

build.gradle (Module) 파일에 다음을 추가하세요.

dependencies {
    implementation "com.squareup.retrofit2:retrofit:2.9.0"
    implementation "com.squareup.retrofit2:converter-gson:2.9.0"
    implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
}

---

✅ 3. Retrofit 구성

3.1. 데이터 클래스

data class KakaoAddressResponse(
    val documents: List<Document>,
    val meta: Meta
)

data class Meta(
    val is_end: Boolean,
    val pageable_count: Int,
    val total_count: Int
)

data class Document(
    val address: Address,
    val address_name: String,
    val address_type: String,
    val road_address: RoadAddress,
    val x: String,
    val y: String
)

data class Address(
    val address_name: String,
    val b_code: String,
    val h_code: String,
    val main_address_no: String,
    val mountain_yn: String,
    val region_1depth_name: String,
    val region_2depth_name: String,
    val region_3depth_h_name: String,
    val region_3depth_name: String,
    val sub_address_no: String,
    val x: String,
    val y: String
)

data class RoadAddress(
    val address_name: String,
    val building_name: String,
    val main_building_no: String,
    val region_1depth_name: String,
    val region_2depth_name: String,
    val region_3depth_name: String,
    val road_name: String,
    val sub_building_no: String,
    val underground_yn: String,
    val x: String,
    val y: String,
    val zone_no: String
)

3.2. Retrofit 인터페이스

interface KakaoApiService {
    @GET("v2/local/geo/coord2address.json")
    suspend fun getAddressFromCoords(
        @Header("Authorization") authorization: String,
        @Query("x") longitude: Double,
        @Query("y") latitude: Double
    ): KakaoAddressResponse

    @GET("v2/local/search/address.json")
    suspend fun getCoordsFromAddress(
        @Header("Authorization") authorization: String,
        @Query("query") query: String
    ): KakaoAddressResponse
}

3.3. Retrofit 클라이언트

object KakaoApiClient {
    private const val BASE_URL = "https://dapi.kakao.com/"

    private val logging = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }

    private val client = OkHttpClient.Builder()
        .addInterceptor(logging)
        .build()

    val apiService: KakaoApiService by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(KakaoApiService::class.java)
    }
}

---

✅ 4. ViewModel + Coroutine 통합

Coroutine을 사용하여 API를 호출하고, StateFlow로 결과를 UI에 전달합니다.

class LocationViewModel : ViewModel() {

    private val _address = MutableStateFlow<String?>(null)
    val address: StateFlow<String?> = _address

    private val apiKey = "KakaoAK YOUR_REST_API_KEY" // <-- 실제 키로 교체하세요

    fun fetchAddress(lat: Double, lng: Double) {
        viewModelScope.launch {
            try {
                val response = KakaoApiClient.apiService.getAddressFromCoords(
                    authorization = apiKey,
                    longitude = lng,
                    latitude = lat
                )
                val addressName = response.documents.firstOrNull()?.address?.address_name
                _address.value = addressName ?: "주소 없음"
            } catch (e: Exception) {
                _address.value = "에러 발생: ${e.localizedMessage}"
            }
        }
    }
}

---

✅ 5. Jetpack Compose에서 주소 출력

@Composable
fun AddressScreen(viewModel: LocationViewModel = viewModel()) {
    val address by viewModel.address.collectAsState()

    Column(modifier = Modifier.padding(16.dp)) {
        Text(text = "현재 주소: ${address ?: "불러오는 중..."}")

        Spacer(modifier = Modifier.height(8.dp))

        Button(onClick = {
            viewModel.fetchAddress(37.5665, 126.9780) // 서울시청 예시
        }) {
            Text("주소 가져오기")
        }
    }
}

---

🔚 마무리 정리

  • ✔️ Retrofit + Coroutine을 통해 네트워크 처리를 안전하고 깔끔하게 구성
  • ✔️ ViewModel과 StateFlow를 통해 UI와 데이터 연결
  • ✔️ 권한과 REST API 키 보안을 고려해 실제 배포 환경에서는 백엔드 연동 또는 키 보호 필요

이제 Kakao Local API를 통해 GPS 좌표와 주소를 자유롭게 변환할 수 있습니다!

 

결과 이미지는 다음과 같이 설정이 가능 합니다. 

위치 설정 결과 지표에 표시 하기

 


📘 도움이 되었나요? 댓글이나 공유로 응원해 주세요 😊

반응형