프로세스 및 스레드 개요 | App quality | Android Developers
프로세스 및 스레드 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 애플리케이션 구성 요소가 시작되고 애플리케이션에 실행 중인 다른 구성 요소가
developer.android.com
메인 스레드 기본 동작
메인 스레드는 프로세스가 시작되어 프로세스의 시작점인 main() 함수에서 실행됩니다. 즉, 메인 스레드가 생성되고 시작되는 곳을 main() 함수라고 부릅니다. 메인 스레드는 다른 스레드를 생성하고 관리하는 역할을 수행합니다.
안드로이드 메인 스레드
- 안드로이드의 어플리케이션을 실행하면 어플리케이션에 실행 중인 다른 구성 요소가 없다면 안드로이드 시스템은 하나의 실행 스레드로 Linux 프로세스를 시작합니다. 시스템은 메인 액티비티를 메모리로 로드하고 이 액티비티가 실행되면 메인 스레드가 자동으로 생성됩니다.
- 메인 스레드는 안드로이드의 컴포넌트와 액티비티의 생명주기들을 관리합니다. 또한 사용자와의 상호작용으로 UI를 그리거나 다양한 이벤트를 처리하는 유일한 프로세스로 UI 스레드라고도 불립니다.
- 메인 스레드는 앱의 생명 주기(lifecycle)와는 별도로 동작하며, 앱이 실행 중일 때는 계속해서 실행됩니다.
- AndroidManifest.xml 에서 액티비티를 런처로 지정해 앱의 시작점, 즉 앱의 프로세스의 시작점을 지정할 수 있습니다.


📕 안드로이드의 main() 함수는 안드로이드 프레임 워크 내부에 존재합니다.
- main() 함수는 안드로이드 프레임워크 내부의 android.app.ActivityThread 클래스 내부에 위치한 main() 함수가 실행되며 앱 프로세스가 시작됩니다.
- ActivityThread는 Activity뿐만 아니라 모든 컴포넌트들이 다 관련되어 있습니다. main() 함수 안에서 메인 스레드가 준비되고 실행되며 메인 스레드가 실행될 때 앞서 런처로 지정한 액티비티를 실행합니다.
- 또한, 안드로이드 UI는 기본적으로 싱글 스레드 모델로 작동합니다.
public static void main(String[] args){
SamplingProfilerIntegration.start();
ClosedGuard.setEnabled(false);
Environment.initForCurrentUser();
EventLogger.setReporter(new EventLoggingReporter());
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper(); // main Looper를 준비한다.
// ActivityThread 객체를 생성하고 현재 프로세스에 연결합니다.
ActivityThread thread = new ActivityThread();
thread.attach(false);
// 메인 스레드의 핸들러를 가져와서 전역 변수에 저장합니다.
// 핸들러는 메시지 큐를 관리하고 UI 스레드에서 실행되는 작업을 처리
if(sMainThreadHandler == null){
sMainThreadHandler = thread.getHandler();
}
// AsyncTask를 초기화
AsyncTask.init();
//// UI Message를 처리한다. Looper.loop()
// 메서드에 무한 반복문이 있어 main() 메서드는 프로세스가 종료될 때 까지 끝나지 않는다.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
싱글 스레드 모델
UI를 구성하는 뷰나 뷰 그룹을 하나의 스레드에서만 담당하는 원칙을 싱글 스레드 모델이라고 합니다. 싱글 스레드 모델을 사용하는 이유는 UI 작업을 할 때 경합상태, 교착 상태 등의 상태를 방지해야 하기 때문입니다.
왜 안드로이드는 메인 스레드에서만 UI 작업이 가능하도록 제한할까요 ?
- 메인 스레드와 다른 스레드 두 개 이상의 스레드가 같은 텍스트뷰에 setText()를 시도한다면 둘 중 어떤 스레드의 setText()가 적용될지 알 수 없고 이렇게 되면 사용자는 둘 중 하나의 값만을 볼 수 있어 다른 한 스레드의 결과는 버려집니다.
- 또한 이 텍스트뷰에 그려지거나 업데이트되는 순서를 보장할 수 없습니다.
- 이런 두 개 이상의 스레드를 사용할 때 동기화 이슈를 방지하기 위해 Looper()와 Handler()를 사용합니다.
단일 스레드 모델은 자원 접근에 대한 동기화를 신경 쓰지 않아도 되며 작업 전환(Context Switch) 비용을 요구하지 않아 경합 상태와 교착 상태를 방지할 수 있습니다.

- 하지만 단일 스레드 모델인 만큼 UI 스레드에서 네트워크 액세스나 데이터 베이스 쿼리 등 시간이 오래 걸리는 작업을 하게 되면 이 요청을 처리하는 동안 사용자는 전체 UI 작업이 차단됩니다. UI 작업이 차단되면 사용자는 터치를 비롯한 이벤트들을 수행할 수 없고 어플리케이션이 중단된 것처럼 보입니다.
- 이 중단 시간이 일정 시간 차단되면(약 5초) ANR(Application Not Responding) 을 발생시킵니다.

- 따라서 안드로이드 공식 문서에서는 다음과 같은 규칙을 제시했습니다.
1. UI 스레드를 차단하지 마세요.
2. UI 스레드 외부에서 Android UI 도구 키트에 액세스 하지 마세요.
- UI 작업은 메인 스레드에서만 이루어져야 하며 메인(UI) 스레드는 UI 작업을 할 수 있는 유일한 스레드입니다.
- 오래 걸리는 작업은 메인 스레드와 분리해야 하고 메인 스레드와 다른 스레드가 통신하는 방법이 필요합니다.
- 이 방법으로 다른 스레드에서 메인 스레드로 접근하기 위해 Looper와 Handler, AsyncTask 등이 있습니다.
Looper와 Handler의 작동 원리
- android.app.ActivityThread 코드를 보면 메인 스레드는 내부적으로 Looper를 가집니다. 이 루프는 스레드가 종료될 때까지 연속적으로 사용자의 입력을 받거나 UI 이벤트를 처리합니다.
- Message란 스레드 간 통신할 내용을 담는 객체로 Handler를 통해 전달할 수 있습니다. Message가 필요할 때마다 새 Message 객체를 생성하면 성능 이슈가 발생할 수 있어 안드로이드가 시스템에 만들어 둔 Message Pool 객체를 재사용합니다.
- Looper 내부에는 Message Queue를 가지고 있는데 Message Queue란 스레드가 다른 스레드나 자기 자신으로부터 전달받은 Message를 FIFO(First in-FirstOut) 형식으로 보관하는 Queue입니다. Looper는 Message Queue에서 Message나 Runnable 객체를 순서대로 꺼내 Handler가 처리하도록 전달합니다.
- 메인 스레드는 루퍼가 기본 생성되지만 새로 만든 스레드는 Looper를 가지고 있지 않습니다. 따라서 메시지를 받을 수 없어 Looper를 생성해 주거나 내부적으로 Looper를 가지고 있는 HandlerThread 클래스를 사용해야 합니다.
- Handler는 Looper로부터 전달받은 Message를 실행하거나 처리하고 다른 스레드로부터 메시지를 전달받아 Message Queue로 전달하는 스레드 간의 통신자 역할입니다.

코루틴을 사용해 백그라운드 작업을 수행할 수 도 있습니다. 코루틴에 관한 글은 이 글을 참조해 주세요
[KOTLIN IN DEPTH] Kotlin Coroutine Concurrency
Kotlin in Dept의 내용 중 13장 코루틴 동시성에 대한 내용을 정리에 대한 첫번재 장입니다. 책을 첨부터 끝까지 정독하면 너무 좋겠지만 원론적인 이야기는 너무 지루해서 필요할 때 마다 정리하려
chanho-study.tistory.com
lifecycleScope.launch {
// 이 부분은 백그라운드 스레드에서 실행
val location = withContext(Dispatchers.IO) {
// TranslateGeo와 같은 시간이 많이 소요되는 작업 수행
TranslateGeo(addr)
}
}
- 이 코드는 제 프로젝트의 프래그먼트에서 코루틴을 실행하기 위한 코드로 lifecycleScope는 Activity 또는 Fragment의 생명주기를 따르는 코루틴으로 액티비티 또는 프래그먼트가 Destory 되면 코루틴도 종료됩니다.
- Dispatchers는 Kotlin Coroutine 라이브러리에서 사용되는 스레드 관리 도구이며Dispatchers.IO는 I/O 작업 같이 오래 걸리는 작업을 백그라운드 스레드에서 실행하게 해 줍니다.
Reference
메인 스레드와 Handler - (1)
UI 처리를 위한 메인 스레드
yunzai.dev
⚙️ 안드로이드 메인스레드
안녕하세요 :) 오늘은 메인스레드, main() 함수라는 것이 무엇인지 살펴보고, 안드로이드 환경에선 이 개념이 어떻게 적용되는지 알아보려합니다. 안드로이드 메인스레드의 역할, 생성, 특징에 대
velog.io
안드로이드 백그라운드 잘 다루기 Thread, Looper, Handler
안드로이드 UI는 기본적으로 싱글 스레드 모델로 작동하므로, 이 영향을 고려해 개발하지 않으면 애플리케이션의 성능이 저하될 수 있습니다. 따라서 메인 스레드에서 긴 작업을 하는 것을 피하
academy.realm.io
'Android' 카테고리의 다른 글
Android Activity Life Cycle (3) | 2023.12.26 |
---|---|
Android Platform Architecture (0) | 2023.12.25 |
Anroid REST API 연동기 [GET] (3) | 2023.12.22 |
Android Gallery Permission (0) | 2023.12.17 |
Android Runtime Permission (1) | 2023.12.17 |