메이쁘

[Android] Handler와 looper의 차이란 무엇이지 ?! (Feat. Android Thread) 본문

면접 대비 CS지식/Android

[Android] Handler와 looper의 차이란 무엇이지 ?! (Feat. Android Thread)

메이쁘 2020. 6. 13. 18:29

안녕하세요.

 

안드로이드 개발을 진행하다 보면

 

new Handler() 를 쓰시는 날이 있습니다.

 

 

이 핸들러에 대해서,

그리고 핸들러와 한 셋트로 거론되는 looper에 대해서

 

간략히 설명하는 시간을 갖겠습니다.

 

 

 

 

 

 

Handler 와 Looper 를 사용하는 이유?


  핸들러와 루퍼를 알기 전에 하나 짚고 넘어가야 할 부분이 있습니다.

 

 

  핸들러와 루퍼는 쓰레드에 사용됩니다.

 

 

 

  그렇다면 왜 쓰레드에 사용되냐? 라는 질문부터 들어가야 할 것 같습니다.

 

 

 

  안드로이드는 기본적으로 UI를 처리하는 메인 쓰레드를 가진 싱글 쓰레드 시스템으로 동작합니다.

 

  싱글 쓰레드 시스템은 두 가지 원칙이 있습니다.

 

 

    -  메인 쓰레드(UI Thread) 를 Block (중지) 하지 않는다.

    -  안드로이드 UI ToolKit (TextView, ImageView, LinearLayout 등) 들은 전부 메인 쓰레드에서만 접근 가능하다.

 

 

  그렇기 때문에, 긴 시간이 걸리는 작업을 메인 쓰레드에 넣어버리면

 

  UI 처리가 미뤄지게 되며,

 

  이것이 지속되면 ANR(Application Not Responding = 응답없음) 오류가 발생됩니다.

  *** 흔히 웹페이지 응답없음이 뜨고 멈춰버리는 것과 같다고 보시면 되요!

 

 

  그럼 어떻게 해요?!

 

  메인쓰레드에서 여분의 쓰레드를 가져와 여기에 긴 시간이 걸리는 작업을 처리합니다.

 

  즉, 서브 쓰레드를 만들어 여기에 DB 작업, REST(서버 통신) 작업 등 오래 걸릴 수 있는 작업들을 넣고 처리합니다.

 

 

  이렇게 멀티 쓰레드 방식으로 안드로이드를 돌리는데

 

  만약 메인 쓰레드에서만 UI 처리를 하는 것이 아닌 다른 쓰레드에서도 처리가 가능하다면 어떻게 될까요?

 

출처 : https://woovictory.github.io/2019/01/07

  *** 위 그림이 핵심적인 내용 표현이 잘 되어있어서 가져왔습니다.

  저렇게 하나의 TextView 에 두 쓰레드가 접근하면, 과연 누구 손을 들어줘야 할까요?

 

  뭐가 되었든, 사용자는 하나의 정보를 알 수 없게 됩니다. (개발자도 알 수 없게 되죠..)

 

 

  아무튼, 위 그림도 그렇고 이렇게 쓰레드가 많아지니까

 

  쓰레드끼리 데이터나 메세지를 주고받을 필요가 있습니다.

 

  그래서 쓰레드 간 통신을 위해 Handler 와 Looper 가 필요한 것입니다!! ㅎㅎ

 

  이 한마디를 하기 위해 말이 길어졌네요..

 

 

 

 

 

  지금까지의 내용을 정리하자면

  

 

    -  안드로이드는 싱글 쓰레드 시스템 이지만, 여분의 쓰레드를 활용하는 멀티 쓰레드 방식처럼 사용한다.

 

    -  쓰레드의 UI로의 동시 접근을 막기 위해 Main Thread 에서만 UI 접근이 가능하다.

 

    -  메인 쓰레드에서는 UI 처리와 쓰레드 역할 배분 등의 간단한 작업을 처리하며

       REST 통신, DB 작업시간이 오래 걸리는 작업들은 서브 쓰레드에서 처리한다.

 

    -  HandlerLooper쓰레드 간 통신에 사용된다.

 

 

 

Handler ? ?


  -  핸들러는 말 그대로 "손" 이라고 생각하면 됩니다.

 

  작업(Message, Runnable) 을 다른 쓰레드에 보내거나(= sendMessage(Message msg) 또는 post(new Runnable()))

 

  Looper 에게 전달받은 작업을 처리합니다. (= handleMessage())

 

  *** 여기서 sendMessage 나 post 함수를 보면 다른 쓰레드에 직접 선택해서 보내주는 것이 아니라

  보내고 싶은 쓰레드의 핸들러를 호출하여 저 함수를 직접 실행해서 넣는 방식입니다.

 

 

  즉, 메인 쓰레드에 보내고 싶으면

  

    -  mainThreadHandler.post(new Runnable()) 또는 mainThreadHandler.sendMessage(msg) 

 

  입니다.

 

  저 함수를 실행한 핸들러와 연결된 쓰레드의 Message Queue에 담기게 됩니다.

  *** Message Queue : Queue 방식으로 쓰레드 별 작업들을 저장하는 큐.

 

 

  그 외에도 일정 시간 후 작업을 보낼 수 도 있습니다.

 

  *** 참고로, 만약 기본 생성자를 통해 Handler를 생성하면, 생성되는 Handler는 이를 호출한 쓰레드의 MessageQueue와 Looper에 자동으로 연결됩니다.

 

 

 

Looper ?


  쓰레드 내에서 주기적으로 MessageQueue 를 탐색하며 작업이 생기면 이를 Handler로 전달하는 역할을 합니다.

 

  쓰레드 당 하나만 가질 수 있으며

 

  메인 쓰레드를 제외하고 새로 생성된 쓰레드들은 루퍼를 가지지 않습니다.

 

 

  그렇기 때문에 루퍼를 사용하기 위해서는 먼저 루퍼를 생성해줘야 합니다.

 

 

  -  관련 함수

 

 

    prepare() : Looper를 생성

 

    loop() : 무한히 주기적으로 돌며 Message Queue에 생긴 작업들을 Handler 로 전달

 

    quit() : Looper 즉시 종료

 

    quitSafely() : 현재 Message Queue에 쌓여있는 작업들을 전부 처리한 후 종료

 

 

 

 

 

감사합니다!

 

좋은 하루 보내세요!

 

 

 

 

 

 

 

 

 

참고 사이트
https://medium.com/@sunminlee89/looper%EC%99%80-handler%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-d05e28929d4d
https://itmining.tistory.com/5
https://brunch.co.kr/@mystoryg/84
https://jungwoon.github.io/android/2019/09/25/Handler-Looper/
Comments