[Android] 스레드란?

곽호택·2021년 11월 1일
0

안드로이드

목록 보기
11/16
post-thumbnail

1. 프로세스와 스레드

프로세스란?

운영체제에 의해 메모리에 올라가 실행 중인 프로그램

프로세스가 실행될 경우, 프로세스는 자신의 코드 시작점부터 시작하여 종료지점까지 순차적인 실행 흐름을 가진다.

일반적으로 하나의 프로세스는 하나의 스레드를 가지고 작업을 수행한다.

스레드란?

동시 작업을 위한 하나의 작업 단위이자 프로세스 내에서 순차적으로 실행되는 실행흐름의 최소 단위

Tip) 하나의 프로세스 내에서 두 개 이상의 스레드가 동작하도록 프로그래밍하는 것을 멀티스레드 프로그래밍이라한다.

Android는 앱 구성하는 여러 컴포넌트들이 각자의 프로세스를 생성할 수 있고, 어느 프로세스에서나 메인 스레드 외의 추가 스레드를 생성할 수 있다!

2. 메인 스레드(Main Thread)

프로세스의 시작과 동시에 무조건 실행되는, 앱의 기본 실행을 담당하는 스레드. 즉 프로세스의 최초 스레드라고 이해하면 된다.

UI 위젯들을 그리는 역할을 수행하기 때문에 UI스레드 라고도 불린다. 또한 UI와 상호작용할 때 사용된다.(편의를 위해 메인스레드라고 언급하겠다)

예를 들면, 앱 사용자가 화면 버튼 클릭시, 클릭 이벤트를 발생시키는 작업이 메인 스레드에서 실행 된다고 생각하면 된다.

가장 중요한점은 UI작업은 오직 메인스레드에서만 이루어져야 한다는 것이다.

그렇다면 왜 메인스레드에서만 UI 작업이 이루어져야 하냐!!

만약 우리가 뷰를 그릴 때

이미지를 그리는 스레드 A

버튼을 그리는 스레드 B

텍스트를 그리는 스레드 C

가 있을때, A-B-C의 스레드가 순차적으로 실행된다면 우리가 원하는 뷰를 그릴 수 있을 것이다.

하지만 상대적으로 작은 크기인 C가 먼저 실행되고, 큰 데이터인 A가 가장 나중에 실행될 경우 원하지 않는 뷰가 나타날 수 있다.

그러므로 UI작업은 메인스레드 단 하나에서만 진행되어야 한다!

추가로 동일한 프로세스 내에서 실행되는 모든 컴포넌트들은 메인스레드에서 인스턴스화 되며, 각 컴포넌트들에 대한 호출은 메인스레드에서 실행된다.

즉, 시스템 콜백에 응답하는 메소드들은 항상 프로세스의 메인스레드에서 실행된다.

3.작업자스레드(Worker Thread)

우리가 작업을 하면서 주의할점은 서버 통신이나 데이터베이스 쿼리 등의 긴 작업을 메인스레드에서 실행할 경우 전체 UI가 차단된다.

스레드가 차단되면 UI를 그리는 이벤트를 포함하여 모든 이벤트가 발송되지 않기 때문에 사용자에게 애플리케이션이 중단된 것처럼 보인다.

메인스레드가 5초 이상 차단되면 사용자에게 "애플리케이션이 응답하지 않습니다(ANR)"라는 다이얼로그가 나타나는 오류가 발생하게 된다.

위와 같은 오류를 발생시키지 않기 위해서 개발자는 UI작업이 차단되지 않도록 하는데 용을 써야한다! 그럼 도대체 어떻게?

위에서 말했다시피 하나의 프로세스 안에 추가 스레드를 생성하고 조작할 수 있다고 했다.

이 추가된 스레드를 작업자 스레드(Worker Thread)라고 한다.

이 작업자 스레드에서 우리는 ANR을 발생시킬 수 있는 네트워크, DB 쿼리 등의 작업을 하도록 조작해야 한다.

새로운 스레드를 생성하고 실행하는 방법은 Thread 클래스를 상속한 서브 클래스를 만든 뒤 Thread()클래스의 run()메서드를 오버라이드 하는 것과, Runnable 인터페이스를 구현한 클래스를 선언한 다음, run() 메서드를 작성하는 것이다.

그리고 Thread 클래스의 start() 메서드를 통해 위에서 생성한 클래스 객체의 run()메서드를 실행해주면 스레드의 생성 및 실행 과정이 완료된다!

-> 예시 작성 필요!

이렇게 하면 UI 작업이 블록되지 않고 네트워크, 데이터 쿼리 작업 스레드를 따로 생성해줄 수 있다.

하지만 우리는 워커스레드에서의 작업한 결과를 통해 UI를 업데이트 시켜줘야 하는 경우가 존재한다. 이때 UI 업데이트 작업은 위에서 계속 언급했듯 UI스레드에서 실행이 된다.

결과적으로 Worker 스레드에서 UI 스레드를 접근할 필요가 있다. 안드로이드 공식 문서에서 나온 방법은 post() 메소드를 이용하는 것이다.

fun onClick(v: View) {
    Thread(Runnable {
        // a potentially time consuming task
        val bitmap = processBitMap("image.png")
        imageView.post {
            imageView.setImageBitmap(bitmap)
        }
    }).start()
}

Thread클래스를 통한 Worker 스레드에서 네트워크 작업을 진행하면, View.post를 통해 여기서는 imageView의 경우 UI스레드에서 조작이 이루어진다.

그러나 더 복잡한 상호작용을 Worker 스레드로 처리하려면, 작업자 스레드에서 Handler라는 것을 이용해야하며, 최선의 해결책은 AsyncTask 클래스를 확장해야 하는 것이다.

이 부분에 경우는 추후에 따로 포스팅할 예정이다.

지금까지 스레드를 배운 이유는 코루틴을 제대로 활용하기 위함인데 코루틴에 대한 내용도 공부한 뒤 정리가 끝나고 포스팅할 예정이다.




참고블로그

https://recipes4dev.tistory.com/143
https://choheeis.github.io/newblog//articles/2020-12/android-process-thread
https://developer.android.com/guide/components/processes-and-threads?hl=ko

profile
잘하고싶다

0개의 댓글