모바일앱의 필수개념, 프로세스와 쓰레드

2020. 4. 16. 10:35Development/[Dev] 개발일반

728x90

프로세스와 쓰레드

 

모바일 개발을 위해서 꼭 거쳐야 하는 작은 관문이 하나있다.

어려운 개념은 아니지만 이를 이해하지 못한 상태에서 앱을 개발하다보면

크래시 현상으로 원인을 찾지 못하는 경우도 있고 (물론 크래시가 날때 로그창에서 로그로 원인을 알려주지만) 하여

간단히 "프로세스"와 "쓰레드"의 개념을 잡고 가야한다.

 

프로세스

컴퓨터를 살때 CPU에 듀얼코어, 헥사코어라며 성능이 좋아요~ 따봉을 많이 받은 리뷰를 본적이 있을 것이다.

그 코어가 프로세스라고 생각하면 된다.

 

프로세스는 독립적으로 행동을 보장받는 "공간"이기때문에 보통은 앱들을 동시에 사용하는 멀티태스킹(스마트폰 초기에 아주 획기적인 기능이었다..)이 가능하게 되고, 멀티 태스킹이라는 말 자체가 멀티 프로세스로 여러개의 앱이 서로의 독립적인 구동을 보장받으면서 실행될 수 있게 해준다는 뜻이된다.

 

앱 하나 만드는데 다른 앱들 동시에 보장받는 것까지 신경써야 하나요?

프로세스단까지 신경을 쓸필요는 없지만, 이제 이야기할 쓰레드는 꼭 잘 읽어내려가야 한다.

(사실 멀티프로세스 환경으로 서로에게 영향을 줄 영향이 있는 안드로이드는 조심할 필요가 있다... 하지만.. 그정도의 일을 하는 회사에 입사를 하게 되면 그떄가서 고민하자..)

 

쓰레드

결론부터 이야기하면 안드로이드든, 아이폰이든 쓰레드 종류는 크게 2개로 나뉜다.

 

1. 메인 쓰레드인가? 2. 아닌가?

 

그런데 그 메인 쓰레드는 보통 "UI 쓰레드"라고 불린다.

 

쓰레드는 하나의 프로세스에서 보장받는 "하나의 동작의 흐름"이다.

 

이때 멀티태스킹을 이야기한 멀티프로세스 환경처럼

하나의 프로세스에서 쓰레드를 여러개 돌리면 여러개의 "동작의 흐름"을 가지고 있다는 말이고

이를 멀티쓰레드라고 한다.

 

안드로이드 스튜디오에서 확인 가능한 구동중인 앱의 쓰레드 현황. 읭? 54개 실화임?
xcode에서 확인 가능한 구동중인 앱의 쓰레드 현황

 

*. 논외로 보통 멀티 쓰레드 환경에서 변수를 동시에 접근할때 그 원자성을 어떻게 보장할 것인가에 대한 고민이 여기서 시작된다..

 

 

모바일 앱은 특히나 유저와의 소통에 그 목적을 두고 있고, 

그 소통의 창구가 바로 화면, "UI"이다.

 

화면에 그려진 버튼이나 텍스트가 없다면 이거 무슨앱임? 해킹앱임? 하면서 앱을 삭제하게 될테니까

기본적으로 앱은 유려한 UI와 UX를 유저에게 보여줌으로서 "이 버튼 눌러" "이 문구 읽어" 라고 말하게 된다.

 

그래서 앱은 유저와의 소통을 위해 1개의 메인쓰레드(UI 쓰레드)를 독립적으로 보장받으면서 유저에게 혼동이 없는 일관된 흐름의 화면갱신을 제공해야한다. 

술취한 사람 또는 친구에게 댓뱀을 때린 뒤, 놀리듯 이 숫자가 몇개로 보여? 하는 손가락 흔들기와 같은 화면 갱신은 위험하다는 뜻이다..

 

( 특히 안드로이드의 경우 60fps 수준의 화면갱신을 목표로하라고 하고 있는데 초로 환산하면 1초는 1000ms 이니까 1000/60으로 계산하여 16ms 의 속도로 무조건 화면이 갱신되어야 한다)

 

"파란색 배경색에 흰색 글씨로 '로그인'" 이라는 버튼을 보여주기로 했다면

그 메인 쓰레드가 그 버튼을 그리고 있는 그 동작은 절대 다른 쩌리 Sub 쓰레드에게 침해받아서는 안된다는 의미이다. 

 

그래서 안드로이드, 아이폰은 UI와 관련한 동작이나 제어를 하는 코드를 작성했다면 이 코드는

단독인 메인쓰레드 (UI쓰레드) 로 자동으로 보장받아 동작하게 된다.

 

그렇기때문에 시간이 오래걸려서 정보를 가져와서 화면에 표시해야하는 동작이 수반되는 경우

이를 메인 쓰레드로 동작시키게되면 앱은 ANR (유저로 하여금 뭐야 동작은 하고 있는거야? 라고 생각하게 만드는 반응이 없어 보이는 고착상태) 에 빠지게 되므로, 네트워크 동작등은 메인 쓰레드에서 할 수 없게 되어 있다.

 

따라서 네트워크로 정보를 받아오거나, 앱 자체에서 무언가 시간이 오래걸리는 분석등을 해서 이를 화면을 갱신하는 코드의 경우

반드시 그런 시간이 오래 걸리는 동작은 별도의 쓰레드 (보통은 백그라운드 쓰레드)로 동작시키도록 강제하고 있다.

 

그렇게 하지 않고 그냥 메인쓰레드로 동작하시오! 하고 코드를 작성하면

런타임시에 오류가 발생한다.

 

보통 안드로이드의 경우 고전적으로 AsyncTask (지금은 deprecated)로 시간이 오래 걸리는 작업을 끝내고 난 결과 콜백함수에서 화면을 갱신하고, 아이폰은 DispatchQueue.main 과 같은 곳에서 화면을 갱신한다.

 

대충 개념은 이러한데..

안드로이드와 아이폰의 특정 동작시 반드시 메인 쓰레드에서 동작하시오! 라는 그 특정 "동작" 의 종류들이 약간은 노하우로 알게되는 것들도 꽤 많아서 사실 나도 전부 열거하기는 힘들다. 푸시 메세지와 관련한 핸들링에서도 발생하는 경우가 있다.. 지저스

 

 

참고할 만한 공식 레퍼런스

안드로이드 https://developer.android.com/guide/components/processes-and-threads?hl=ko

 

프로세스 및 스레드 개요  |  Android 개발자  |  Android Developers

애플리케이션 구성 요소가 시작되고 애플리케이션에 실행 중인 다른 구성 요소가 없으면 Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux 프로세스를 시작합니다. 기본적으로 같은 애플리케이션의 모든 구성 요소는 같은 프로세스와 스레드에서 실행됩니다("기본" 스레드라고 합니다). 애플리케이션 구성 요소가 시작되었는데 (애플리케이션의 다른 구성 요소가 존재하기 때문에) 해당 애플리케이션의 프로세스가 이미 존재할 경우, 해당 구성 요소는 프로세스

developer.android.com

 아이폰

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/AboutThreads/AboutThreads.html#//apple_ref/doc/uid/10000057i-CH6-SW2

 

About Threaded Programming

About Threaded Programming For many years, maximum computer performance was limited largely by the speed of a single microprocessor at the heart of the computer. As the speed of individual processors started reaching their practical limits, however, chip m

developer.apple.com

 

728x90