쓰레드가 뭔지 얼추 알게 됐는데, 어떤 동작으로 돌아가는지는 몰랐다. 근데 앱개발에 있어서 여러 쓰레드로 비동기적으로 소스를 다루는 것은 필수라는 것을 어렴풋이 알고 있었기 때문에, 조금 더 자세히 알아 보게 됐다. 사실은 아주 복잡한데, 지금 나의 수준에 있어서 또 내가 이해한 수준으로만 간단하게 정리하는 시간을 가지도록 하겠다.
# 왜 사용해야할까? : 스레드의 필요성
## 사용자가 불만족할 경우 앱을 종료 할 수 있습니다.
놀랍게도 안드로이드 공식문서에 이렇게 적혀있다... 앱을 만들어서 돈을 벌어야하는데, 사용자가 불만족해 앱을 종료시키면.. 힘들게 만든게 의미가 없어질 것 이다.
## 유저는 왜 불만족 할까 ?
그렇다면 사용자는 왜 불만을 가지게 될까? 오래걸리는 작업을 수행해야할 경우를 예를 들어보면 간단하다. 1기가의 파일을 다운받아야 하는데, 단일스레드로 구성하게 된다면 동기적으로 처리가 될 것이고, 파일을 다운받는 동안 다른 작업을 할 수가 없게 된다. 그래서 그러한 작업을 별도의 스레드로 분리시켜 해당 스레드에서 다운로드를 하게 되고, 다운이 완료되면 메인스레드에게 작업이 완료됐다는 알림을 주도록 하는 것이다.
또한 메인 UI쓰레드에서만 UI에 관련된 것을 변경시켜줄 수 있다. 이점을 잘 기억해야 한다. 다운로드를 위해 만든 새로운 쓰레드에서 다운로드가 완료된 것을 다이얼로그로 띄어주는 작업을 하고싶지만, 할 수 없다. 왜냐하면 UI를 조작하기 때문인데, UI는 메인 UI쓰레드에서만 조작할 수 있다. 그렇게 하는 이유는 간단한데, 여기저기 여러 쓰레드에서 UI를 조작하게 된다면 당연히 UI구성이 뒤죽박죽 꼬일 것이다.
그렇다면 쓰레드가 어떤 것이고, 어떻게 구성 돼 있으며 쓰레드끼리는 어떤 방식으로 통신을 해야하는지 간단하게 알아보도록 하자.
# 쓰레드(Thread)
하나의 앱을 프로세스라고 생각하고, 그 프로세스 안에는 여러개의 쓰레드가 구성 될 수 있다. 보통 main()을 가지는 곳에서 하나의 메인쓰레드가 생성되어 작성한 코드가 실행 순서대로 흐름을 따라서 실행되는데 오래걸리는 동작들에 대해서 이 흐름을 새로 만들어서 별개로 작동하게끔 하는 것이다. 그래서 단일쓰레드 - 멀티쓰레드 와 같은 용어로 구분할 수 있다.
## 쓰레드의 구성
쓰레드는 Looper(루퍼), Message Queue(First In First Out), Handler, Message( 또는 Runnable 객체)로 이루어져 있다.
Message Queue는 자료구조로써 Message를 담는다. 큐이기 때문에 선입선출이 원칙이지만, 상황에따라 delay를 주거나 큐의 맨앞에 위치시키게 메시지를 보낼 수도 있다.
Looper는 메시지 큐를 감시하고 새로운 메시지가 도착하면 알맞은 Handler에게 보내준다
Handler는 수신받은 Message를 처리하는 작업을 한다. 또 메시지를 메시지큐에 보내는 역할을 하기도 한다.
Message( Runnalbe 객체 )는 run() 메서드를 재정의(override)하여 어떤 일을 할지를 정의 해준다. 보통 Runnable인터페이스를 implement하여 run() 메서드를 재정의하고 안에 실행한 코드를 적어 보내면 큐에 들어간다. 사용방법이 간단하여 Runnable방법이 꽤 많이 쓰인다고 한다.
## 쓰레드 작동 순서
- 다른 쓰레드 또는 현재 쓰레드에서 Send Message를 보낸다.
- Message가 Queue에 저장된다. Queue는 FIFO구조로 선입선출의 형태를 가지고 있다.
- Looper가 큐를 확인해가면서 해당 메시지를 알맞은 Handler에 전달시켜 작업을 수행한다.
## 주의할점 : UI는 메인 UI 쓰레드에서만 수정 할 수 있음
맨 처음 언급했던거와 같이, 메인 UI 쓰레드에서만 수정할 수 있다.
위 그림과 같이, 내가 원하는 순서는 A -> B -> C 순서로 UI가 그려서 버튼이 최 상단에 와야하지만, 여러쓰레드에서 UI를 담당하게 되면 이러한 순서가 꼬이게 되면서 예상과 다르게 UI가 꾸려질 수 있기 때문이다.
# 마치며
쓰레드와 쓰레드 구성요소에 대해서 간단하게 알아봤다. 내가 참고한 블로그에서는 시계를 예제로 들어서 설명해주었는데, 다음 포스팅에서는 그 시계를 한번 구현해보면서, 왜 쓰레드를 사용해야 했고 사용하면서 얻었던 장점에 대해서 알아보도록 하겠다. 또한 그냥 메시지와 Runnable을 두개다 보내보도록 하겠다.
보통 쓰레드를 설명하면서 많이 사용하는 예제가 로딩바를 만드는 것인데 그것도 한번 만들어 보도록 하겠다.
막연했던거에 대해서 조금 알게 되서 궁금증이 풀린거 같다. 내가 참고한 블로그가 있는데 포스팅이 몇개로 나누어져 있다. 순서에 맞게 볼 수 있도록 올려놓겠다. 엄청 설명 잘 해 주신다.
++1
++2
++3
++4
++5