안드로이드의 ANR은 메인스레드로 긴 작업이 지속될 경우에 다른 이벤트가 들어오면 처리되지 않는다는 문제를 가진다. 이를 해결하기 위해 프로그램을 멀티스레드(여러 개의 스레드)로 작성하는 방안이 존재한다.
→ 비동기적 처리 방식
비동기적 처리의 다른 방식으로는 AsyncTask, Coroutine이 존재한다.
※ Thread-Handler와 AsyncTask는 현재 공식 Deprecation 된 상태이므로 비동기적 처리를 구현할 때 Coroutine 사용을 권장한다.
메인스레드(Main Thread)
애플리케이션은 성능을 위해 멀티스레드를 많이 활용하지만, UI를 업데이트하는 데는 단일 스레드 모델이 적용된다. 멀티 스레드로 UI를 업데이트하면 동일한 UI 자원을 사용할 때 교착 상태(deadlock), 경합 상태(race condition) 등 여러 문제가 발생할 수 있기 때문이다. 따라서 메인 스레드에서만 UI 업데이트를 허용한다.
메인스레드는 앱 프로세스가 시작되면서 생성된다. 컴포넌트의 생명주기 메서드와 그 안의 메서드 호출은 기본적으로 메인스레드에서 실행된다.
메인스레드는 UI를 변경할 수 있는 유일한 스레드이기 때문에 메인스레드를 UI 스레드라고 부르기도 함
멀티스레딩(Multithreading)
화면 처리와 이벤트 처리를 수행하는 메인스레드 이외의 워커스레드를 두고 이 워커스레드에서 시간이 오래 걸리는 업무 로직을 처리를 수행하는 방식이다.
멀티스레드 프로그램을 작성하는 방법으로 ANR 문제를 해결할 수 있지만 만약 메인스레드와 워커스레드 각각에서 각자의 업무 로직을 수행하고 있는 도중, 워커스레드에서 화면 출력 요소인 뷰(View)에 접근을 하면 에러가 발행한다. 따라서 워커스레드에서는 화면 출력 요소인 뷰에 접근할 수 없게끔 프로그램을 작성해야 한다. 하지만 액티비티의 업무 대부분은 화면출력이 목적이기 때문에 워커스레드에서 뷰에 접근하지 않을 수 없다. 이에 메인스레드와 워커스레드 사이에 핸들러를 두어 메인스레드에 UI 작업을 의뢰를 하는 방식으로 뷰에 접근한다. (스레드-핸들러 구조)



Handler 클래스
Handler는 Message를 MessageQueue에 넣는 기능과 MessageQueue에서 꺼내 처리하는 기능을 함께 제공한다. Handler에서 메인스레드에 작업을 의뢰할 때 대표적으로 아래와 같은 함수를 사용한다.
Handler.sendMessage(Message msg)
Message 객체를 message queue에 전달하는 함수
Handler.sendEmptyMessage(int what)
Message의 what 필드(ID)를 전달하는 함수(데이터 전달 없이 메인스레드에 작업을 의뢰할 때 사용)
Message 객체
스레드 간의 데이터 전달을 돕는 객체
Message 객체의 속성
- what : int형 변수로 구분자로 개발자가 정한 임의의 숫자값으로 요청을 구분하기 위해 사용한다.
- obj : Object 타입의 변수로 UI Thread에게 넘길 데이터이다.
- arg1, arg2 : UI Thread에게 넘길 데이터로 int 타입으로 간단한 숫자값은 arg1, arg2 변수에 담아 전달한다.
워커스레드에서 핸들러를 통해 작업을 의뢰하는 예시


Deprecated 된 이유
Handler가 생성되는 동안, Looper가 암묵적으로 선택되면 여러 가지 버그가 발생할 수 있다고 한다.
이러한 가능성을 차단하기 위해서는 명시적으로 Looper를 선언해야 하므로, Handler()와 Handler(Handler.Callback)이 deprecated 된 것 같다.
해결 방법
Handler()를 Handler(Looper.getMainLooper())로 수정하면 deprecated 문제가 해결된다.
[Reference]
Deprecated 이유 https://velog.io/@kimbsu00/Android-4