Kotlin을 사용하면 안드로이드에서 주소(지명) 문자열만 입력해도 해당 위치의 위도와 경도 좌표를 손쉽게 얻을 수 있습니다. 이 글에서는 안드로이드에 내장된 Geocoder 클래스를 활용해 지오코딩(Geocoding)을 구현하는 과정을 단계별로 살펴봅니다.
1단계 — 새 프로젝트 생성
Android Studio에서 File ⇒ New Project를 선택하고, 새 프로젝트 생성에 필요한 모든 정보를 입력해 프로젝트를 만듭니다.
2단계 — 레이아웃 작성 (activity_main.xml)
res/layout/activity_main.xml 파일에 아래 코드를 추가합니다. 화면은 주소를 입력받는 EditText, 조회를 실행하는 Button, 결과를 표시할 TextView로 구성됩니다.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="8dp" tools:context=".MainActivity"> <TextView android:id="@+id/textViewAddress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:text="Enter Address: " android:textAppearance="?android:attr/textAppearanceMedium" android:textStyle="bold" /> <EditText android:id="@+id/editTextAddress" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toEndOf="@+id/textViewAddress" android:singleLine="true" android:text="" /> <Button android:id="@+id/addressButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textViewAddress" android:layout_marginTop="50dp" android:layout_toEndOf="@+id/textViewAddress" android:text="Show Lat/Long" /> <TextView android:id="@+id/latLongTV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toEndOf="@+id/textViewAddress" android:text="" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@android:color/background_dark" /> </RelativeLayout>
3단계 — MainActivity.kt 작성
src/MainActivity.kt에 다음 코드를 추가합니다. 버튼을 클릭하면 입력된 주소를 읽어 지오코딩 작업을 요청하고, Handler를 통해 전달된 결과를 화면에 표시합니다.
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var addressButton: Button
private lateinit var textViewAddress: TextView
lateinit var textViewLatLong: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
title = "KotlinApp"
textViewAddress = findViewById(R.id.textViewAddress)
textViewLatLong = findViewById(R.id.latLongTV)
addressButton = findViewById(R.id.addressButton)
addressButton.setOnClickListener {
val editText = findViewById<EditText>(R.id.editTextAddress)
val address = editText.text.toString()
val locationAddress = GeoCodingLocation()
locationAddress.getAddressFromLocation(address, applicationContext,
GeoCoderHandler(this))
}
}
companion object {
private class GeoCoderHandler(private val mainActivity: MainActivity) : Handler() {
override fun handleMessage(message: Message) {
val locationAddress: String?
locationAddress = when (message.what) {
1 -> {
val bundle = message.data
bundle.getString("address")
}
else -> null
}
mainActivity.textViewLatLong.text = locationAddress
}
}
}
}
4단계 — GeoCodingLocation.kt 클래스 추가
새 Kotlin 클래스를 생성한 뒤 GeoCodingLocation.kt 파일에 아래 코드를 추가합니다. 이 클래스는 백그라운드 스레드에서 Geocoder의 getFromLocationName() 메서드를 호출해 주소를 좌표로 변환하고, 그 결과를 Handler로 되돌려 줍니다.
import android.content.Context
import android.location.Address
import android.location.Geocoder
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.Log
import java.io.IOException
import java.util.*
class GeoCodingLocation {
private val TAG = "GeoCodeLocation"
fun getAddressFromLocation(
locationAddress: String,
context: Context, handler: Handler
) {
val thread = object : Thread() {
override fun run() {
val geoCoder = Geocoder(
context,
Locale.getDefault()
)
var result: String? = null
try {
val addressList = geoCoder.getFromLocationName(locationAddress, 1)
if (addressList != null && addressList.size > 0) {
val address = addressList.get(0) as Address
val sb = StringBuilder()
sb.append(address.latitude).append("\n")
sb.append(address.longitude).append("\n")
result = sb.toString()
}
} catch (e: IOException) {
Log.e(TAG, "Unable to connect to GeoCoder", e)
} finally {
val message = Message.obtain()
message.target = handler
message.what = 1
val bundle = Bundle()
result = ("Address: $locationAddress" +
"\n\nLatitude and Longitude: \n" + result)
bundle.putString("address", result)
message.data = bundle
message.sendToTarget()
}
}
}
thread.start()
}
}
5단계 — 매니페스트 권한 설정 (AndroidManifest.xml)
androidManifest.xml에 다음 코드를 추가합니다. 위치 정보 접근 권한인 ACCESS_FINE_LOCATION을 반드시 선언해야 지오코딩이 정상적으로 동작합니다.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="app.com.q11"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
앱 실행 및 결과 확인
이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤 툴바의 실행(Run) 아이콘을 클릭하고, 목록에서 자신의 모바일 기기를 선택하세요. 그러면 기기에 앱이 설치·실행되며 기본 화면이 나타납니다.


주소를 입력한 뒤 Show Lat/Long 버튼을 누르면, 해당 위치의 위도(latitude)와 경도(longitude) 값이 화면에 출력됩니다.
참고 사항
- Geocoder는 내부적으로 네트워크를 사용하므로 인터넷 연결이 필요하며, 백엔드 서비스를 사용할 수 없는 환경에서는 IOException이 발생할 수 있습니다.
- 지오코딩은 시간이 걸리는 네트워크 작업이므로, 메인 스레드가 아닌 별도의 스레드에서 실행해야 ANR(앱 응답 없음) 오류를 피할 수 있습니다.
- API 33 이상에서는 리스너 기반의 비동기
getFromLocationName()메서드도 제공되므로, 최신 프로젝트에서는 Coroutine이나 이 비동기 API를 함께 고려해 보세요.