Tech Log

[Android] Handler 개념 본문

Android/etc

[Android] Handler 개념

yuhee kim 2022. 6. 7. 18:39

안드로이드를 공부하면서 안드로이드 내의 스레드 개념을 알게되고, 이때 Handler 라는 것이 있다는 것을 알게 되었다.

근데 당시에는 글을 읽어봐도 Handler에 대한 감이 잡히지 않았다. 그래서 다시 공부하며 직접 글을 쓰면서 정리하고자 한다.

 

1. 배경

어쩌다가 Handler라는 것이 만들어지게 된 것일까? 그리고 Handler라는 것은 어디에 쓰는 것일까?

앞에서 스레드를 공부하면서 Handler를 알게 되었다고 했다.

여기서 유추할 수 있듯이, Handler는 스레드와 관련된 일을 한다.

 

안드로이드에는 메인 스레드와 워커 스레드가 있다.

메인 스레드에서는 대게 UI 관련된 작업을 하고,

시간이 오래 걸리는 작업들은 워커 스레드에서 진행한다.

 

만약, 워커 스레드에서 UI를 처리하는 작업을 하거나

메인 스레드에서 하는 일을 하려고 한다면 어떻게 될까?

 

특정 task나 UI를 그리려는 View에 동시 접근하면 오류가 나게 된다.

해당 task(혹은 View)가 어디서 일을 진행해야 할지 모르기 때문이다.

여기서 Handler가 힘을 발휘한다(?)

어떻게 Handler가 제 역할을 하는지 계속 읽어보도록 하자.

 

2. 역할

1.에서 얘기했던 메인 스레드와 워커 스레드를 이용해서 Handler의 역할을 설명할 것이다.

Handler의 역할을 한 마디로 정의하자면 스레드 통신(메인 스레드, 워커 스레드와 같은 여러 스레드의)을 도와준다고 할 수 있겠다.

 

1.에서 메인 스레드와 워커 스레드가 한 가지 task에 동시에 접근하면 문제가 된다고 언급했다.

 

출처 : 안드로이드 노트(https://brunch.co.kr/@mystoryg/84)

위 사진처럼, 메인 스레드에서도 setText()를 하려고 하고 

동시에 워커 스레드도 한 가지 textView에 setText()를 하려고 한다고 가정하자.

 

setText()가 어디서 시행되어야 하는지 문제가 생길 것이다.

이러한 문제를 해결하기 위해서 Handler가 등장한다.

 

출처 : 안드로이드 노트(https://brunch.co.kr/@mystoryg/84)

아까 말했던 setText() 예시와 같이 워커 스레드에서 UI 처리나 메인 스레드에서 해야 할 일을 처리하는 경우가 생겼다면,

워커 스레드와 메인 스레드가 동시에 task에 접근하는 것이 아니다.

그림과 같이 워커 스레드와 메인 스레드 간 해야할 일을 Handler를 통해 공유한다.

Handler가 해야 할 일을 전달하는 메시지 전달 역할을 한다.

 

그림에 따르면, 워커 스레드에서 메인 스레드에 UI 처리를 요청해야 할 일이 생긴 것이다.

따라서 Handler라는 메시지 도구를 사용해서 메인 스레드에 할 일을 전달한 것이다.

 

3. 요소

Handler에 사용되는 요소는 총 4가지가 있다.

 

출처 : Tutorial by eyehunts(https://tutorial.eyehunts.com/android/android-handler-background-thread-communicate-ui-thread/)

 

1) Message

 

  • 전달할 데이터를 한 곳에 저장하는 클래스
  • 하나의 데이터를 보내기 위해서는 한 개의 Message 인스턴스가 필요
  • 데이터가 있는 Message 객체를 Handler로 보내면, 해당 객체는 Message Queue에 쌓이게 된다.

 

2) Message Queue

 

  • Message 객체를 Queue 형태로 관리하는 자료 구조
  • Queue 형태이므로 FIFO(First In First Out) 방식으로 동작
  • Message는 Message Queue에 들어온 순서에 따라 차례대로 저장(First In)
  • 가장 먼저 들어온 Message 객체부터 순서대로 처리(First Out)
  • 앱의 메인 스레드에서 기본적으로 사용
  • 개발자가 MessageQueue 객체를 직접 참조하여 Message를 전달하거나 가져와서 처리하지 않는다.
  • Message 전달은 Message Queue에 연결된 Handler를 통해서 이루어지기 때문이다.
  • Message Queue로부터 Message를 가져와서 처리하는 역할은 Looper가 한다.
  • 단순히 Message 객체 리스트만 관리한다.

 

3) Looper

 

  • Message Queue로부터 Message를 가져와 해당 Message와 연결된 Handler를 호출
  • Looper라는 이름은, Message 처리를 위해 Message Loop를 실행한다고 해서 지어진 이름
  • 안드로이드 앱의 메인 스레드에는 Looper 객체를 사용하여 Message Loop를 실행하는 코드가 이미 구현되어 있다.
  • 다시 말해, 개발자가 메인 스레드에서 Message Loop와 관련된 코드를 작성할 필요 없다.
  • 개발자는 메인 스레도로 전달할 Message 객체를 구성하고, 스레드의 Message Queue에 연결된 Handler를 통해 해당 메시지를 보내기만 하면 된다.

 

4) Handler

 

  • Message Queue로 메시지를 보내고 처리할 수 있게 만들어준다.
  • 메인 스레드에서 개발자가 메시지 전달과 처리를 할 수 있게 Message Queue에 접근하게 해주는 창구 역할을 한다.
  • 스레드와 관련된 Handler를 얻으려면, Handler 클래스 인스턴스를 생성하기만 하면 된다.
  • 만들어진 Handler 인스턴스는 자동으로 해당 스레드와 Message Queue에 연결(bound)된다.

 

4. Handler 참고 사항

  • 스레드 통신을 위해서는 다른 스레드 뿐만 아니라 자기 자신인 스레드에도 Message를 보낼 수 있다.
    • 외부 스레드에서 전달되는 Message 처리를 위해 구현한 기능을 그대로 사용하는 경우가 해당
    • 순차적으로 실행돼야 하는 코드들 사이에 시스템 이벤트가 고려되어야 하는 경우가 해당 
  • Handler는 여러 개 만들 수 있다.
    • 오히려 하나의 Handler에서 모든 메시지를 처리하는 것은 좋지 않다.
    • Message 종류 및 기능에 따라 여러 개의 Handler로 나누어 처리하는 것이 낫다.
    • 단, 스레드에서 적절한 Handler를 사용하는 것에 유의 

 

 

Handler가 뭐하는 것인지 몰랐는데 배경을 이해하고 나니 역할도 이해가 잘된다.

정말 간단하게 구현된 앱이 아니라면, 필수적으로 사용돼야 할 것 같은 클래스다.

 

번외로, 왜 스레드 통신이 되어야 하는지

그리고 메인 스레드에서 모든 일을 해결하지 않는 지에 대한 얘기를 하고 마치도록 하겠다.

 

메인 스레드에서 시간이 오래걸리고 무거운 task를 하지 않는 이유는 UI 처리에 있다.

메인 스레드에서 UI를 관리하고 이 task는 사용자에게 바로 보여지게 된다.

 

메인 스레드에서 UI task가 아니라, 시간이 오래 걸리는 다른 task를 시행했다고 가정해보자.

앱에서는 UI를 처리해야 할 시간에 다른 task를 하게 되어 UI 처리가 늦어지게 된다.

앱 화면에서 아무 반응이 없다면 사용자는 답답함을 느끼게 될 것이다.

 

따라서 메인 스레드에서는 반응성을 높일 수 있게 UI 처리를 대게 하는 것이다.

그리고 시간이 오래 걸리는 task들은 워커 스레드에게 맡기게 된다.

 

이후에는 Handler를 안드로이드 스튜디오에서 직접 활용하는 포스팅도 작성해볼 것이다.

 

참조

'Android > etc' 카테고리의 다른 글

[Android] Jetpack  (0) 2022.06.21
[Android] SharedPreferences  (0) 2022.06.15
[Android] Glide 라이브러리의 사용  (0) 2022.06.11
[Android] Fragment  (0) 2022.06.01
Retrofit 2  (0) 2021.12.28
Comments