코틀린(Kotlin) 핸들러(Handler) 사용법 정리 #1
개발/안드로이드1 2025. 11. 17. 08:33안드로이드 개발을 하다 보면 짧은 지연 작업을 처리하거나, 특정 코드를 일정 시간 뒤에 실행해야 하는 상황이 종종 생깁니다. 예를 들어, 화면 전환 전 300ms 정도의 딜레이를 주고 싶다거나, 반복적으로 어떤 작업을 실행해야 할 때가 있죠. 이런 경우 가장 간단하게 활용할 수 있는 도구가 바로 Kotlin의 Handler입니다.
물론 WorkManager나 Coroutine을 사용하는 경우가 더 많아졌지만, 여전히 UI 스레드에서 간단한 지연 작업을 처리할 때는 Handler가 편리합니다.
이번 글에서는 코틀린 환경에서 Handler를 어떻게 쓰는지, 어떤 방식으로 처리되는지 자연스럽게 정리해보겠습니다.
그리고 2편으로 나눠서 작성하고자 합니다.
1편 : post와 postDelayed 같은 기본적인 사용법
2편 : Handler가 원래 가지고 있는 가장 기본이자 핵심 기능인 메시지(Message) 처리 방식

Handler란 무엇일까?
Handler는 Looper가 동작하는 스레드(대부분 메인 스레드)에 메시지나 Runnable 작업을 전달해주는 역할을 합니다. 쉽게 말씀드리면 "정해진 시간 뒤에 이 코드를 실행해줘", "이 작업을 큐에 넣어줘" 같은 명령을 수행하는 도구입니다.
안드로이드의 메인 스레드는 Looper를 통해 계속 메시지를 처리하는 구조로 돌아가기 때문에, Handler는 그 Looper에 작업을 요청하는 방식으로 동작합니다.
기본 사용법: post
가장 간단한 예시는 아래처럼 바로 Runnable을 전달해 실행시키는 방식입니다.
val handler = Handler(Looper.getMainLooper())
handler.post {
// 바로 실행될 코드
println("즉시 실행되는 작업")
}
위 코드는 메인 스레드 메시지 큐에 Runnable을 넣고, Looper가 이를 확인하는 즉시 실행합니다.
일정 시간 뒤에 실행하기: postDelayed
딜레이를 주는 가장 흔한 사용 예입니다.
handler.postDelayed({
println("2초 뒤 실행됩니다")
}, 2000)
앱에서 스플래시 화면을 잠깐 보여주거나, 간단한 예약 실행에 종종 활용됩니다.
반복 실행하기
Handler를 쓰면 반복 작업도 간단하게 처리할 수 있습니다.
val handler = Handler(Looper.getMainLooper())
val runnable = object : Runnable {
override fun run() {
println("반복 실행 중")
handler.postDelayed(this, 1000)
}
}
handler.post(runnable)
이런 방식은 주기가 짧은 반복 작업에 자주 사용되지만, 너무 긴 작업이나 안정성이 필요한 반복 작업이라면 WorkManager나 Coroutine을 사용하는 편이 더 적합합니다.
실행 중인 작업 취소하기: removeCallbacks
postDelayed로 예약 실행된 작업을 취소할 수 있습니다.
handler.removeCallbacks(runnable)
특히 화면이 종료되거나 Lifecycle이 끝나는 시점에서는 반드시 취소하는 것이 좋습니다. 메모리 누수나 불필요한 실행을 방지할 수 있기 때문입니다.
Handler vs Coroutine: 요즘은 뭘 써야 할까?
최근에는 Coroutine, 특히 delay나 launch를 활용하는 경우가 많이 늘었습니다. 구조적으로는 Coroutines가 더 안전하고 유지보수 측면에서도 강점이 있습니다.
그래도 Handler는 다음과 같은 상황에서 여전히 유효합니다.
- 아주 짧은 UI 지연 작업이 필요한 경우
- 기존 코드에서 Handler 기반으로 작성되어 있는 부분을 빠르게 유지보수해야 할 때
- 특정 스레드의 Looper에 직접 메시지를 넣어야 하는 경우
즉, 일반적인 비동기 처리에는 Coroutine을 쓰되, UI 딜레이와 같은 단순 작업에는 Handler가 빠르고 편합니다.
스레드를 기반으로 한 Handler 사용
메인 스레드가 아닌, 별도의 스레드에서 Handler를 쓰는 방식도 있습니다.
val thread = HandlerThread("MyThread").apply { start() }
val handler = Handler(thread.looper)
handler.post {
println("백그라운드 스레드에서 실행됨")
}
이런 구조는 특정 스레드에서만 돌아가야 하는 작업이 있을 때 활용할 수 있습니다.
안드로이드 30 이후 변경사항은?
Android 30(API 30)부터는 Handler 생성 시 반드시 Looper를 명시하는 것을 권장하고 있습니다.
// 권장 방식
val handler = Handler(Looper.getMainLooper())
기존에 매개변수 없이 Handler()로 생성하는 방식은 deprecated 처리되었습니다.
정리하자면..
Kotlin에서 Handler는 여전히 간단한 지연 실행이나 메시지 처리에 매우 유용한 도구입니다.
post, postDelayed, removeCallbacks 같은 단순한 기능만으로도 여러 UI 처리나 작은 동작을 안전하게 제어할 수 있습니다.
다만 복잡한 비동기 처리나 백그라운드 작업의 경우에는 Coroutine, WorkManager 같은 현대적인 기술과 병행해서 선택하는 것이 좋습니다.




