이 글은 압축해제 시리즈의 일환으로 작성되었습니다.

이 글의 소재는 얼마전 영화 써니의 급식실 장면을 보다가 번뜩 떠올랐다.

그래서 스크린샷을 하나 넣었는데 문제가 되면 지우겠다.


글을 시작하며

오늘도 플레이스토어에서는 수많은 앱들이 별점 테러를 당하고 있다. 내용을 읽어보면 '앱을 왜 이따구로 만들었냐'는 요지의 리뷰들이 달려있다. 여기서 '이따구'에 내재된 원인으로는

  1. 사용자가 삽질하게 되는 앱 디자인
  2. 납득할 수 없는 서비스 정책
  3. 앱이 느리고 버벅임
  4. 치명적인 버그가 있음

등등... 여러 가지가 있는데 1, 2, 4는 그 사례가 워낙 가지각색이라 제끼고 3번에 대해 얘기해보려 한다. 사실 개발자들이 고의로 그렇게 만든 건 아닌데, 많은 앱들이 욕을 먹고 있고, 앞으로도 먹을 예정이다. 오늘은 앱 개발을 공부하는 입장에서, 소위 말하는 답답한 앱들이 왜 그러는 건지 프로그래밍을 모르더라도 이유를 이해할 수 있게써보려고 한다.

어쩌면 아무도 안 궁금할 이야기 스타트 🏁

한 줄 읽고 바로 스크롤 내려가는 건 아닐까

안드로이드의 정체

스마트폰을 구분할 때 사람들은 보통 안드로이드폰/아이폰 두 가지 종류로 이분법적 사고를 하고 있다. 그래서 안드로이드가 뭔지 처음 들어보는 사람은 없을 것이다. 안드로이드의 실체는 무엇인지 간단하게 짚고 넘어가자.

 

컴퓨터는 사람이 직접 처리하기엔 오래 걸리는 각종 작업을 빠르게 처리해 주는 일종의 슈퍼 계산기다. 이 계산기에 휴대성과 함께 온갖 기능이 추가되어 고도화된 형태가 지금의 스마트폰이다. 따라서 스마트폰은 컴퓨터의 일종인데, 사람들이 컴퓨터의 동작 원리를 잘 몰라도 손꾸락 터치만 하면 쉽게 사용할 수 있도록 안드로이드 같은 운영체제 프로그램이 탑재되어 있다.

 

사실 운영체제가 눈에 안 보이는 영역에서 무슨 일을 하고 있는지는 컴퓨터 전공생들이 한 학기 내내 배워도 잘 모를 정도로 방대하고 복잡하다. 우리가 쓰는 스마트폰의 메모리, CPU 등은 소프트웨어 관점에서 할당받을 수 있는 '자원'으로 보고 있다. 이 자원은 아무리 고급 폰을 쓰더라도 결국 한계치가 존재한다. 안드로이드 운영체제는 여러분의 스마트폰이 켜져 있는 동안 한정된 자원으로 최대한 뽕을 뽑기 위해 열일 하는 존재 정도로 생각하면 된다.

하는 일이 많습니다.

안드로이드의 속사정

안드로이드는 사용자가 하나의 앱을 실행한 순간, 그 앱의 동작을 전담해서 처리해 주는 일꾼을 하나 생성한다. 비유하자면... 네이버 블로그 앱을 실행한 순간 안드로이드에 네이버 블로그 담당 부서가 신설되고, 그 부서에서 최소한의 일을 처리할 수 있도록 한 명의 직원이 투입된다.

 

컴퓨터 학자들은 여기서 담당 부서 역할을 하는 것을 '프로세스', 일꾼 역할을 하는 것을 '쓰레드'라고 이름을 붙여놨다. 앱을 실행한 순간 최초로 생성된 일꾼은 '메인 쓰레드'라고 불린다. 갑자기 외국식 이름이 등장해서 뭔가 거부감도 들고 어려워지려고 한다. 그냥 저런 이름의 무언가가 있구나 하면 된다.

 

쓰레드라 불리우는 일꾼은 앱의 UI를 화면에 그리는 화가 역할을 하기도 하고, 인터넷으로 통신하는 역할을 하기도 하고, 여러분이 입력한 정보를 폰에 저장하는 등 앱을 사용하는 도중 일어나는 온갖 잡다구리한 일을 다 처리해야 한다.

 

모두 속고 있는 거다

아래의 짤방처럼 움직이는 앱을 보면 우리는 앱이 스무스하게 잘 동작한다는 인식을 하게 된다. 이때 앱이 부드럽게 움직인다는 인식은 착시현상에서 비롯되는 것이다.

동영상이 많은 양의 연속된 이미지를 빠르게 재생하는 형태로 만들어졌다는 것은 많이들 알고 있을 것이다. 이는 망막의 잔상 현상을 이용한 것이다. 스마트폰 앱도 똑같은 원리다.

 

스크린에서 정적인 프레임을 아주 빠르게, 연속적으로 이어지게 보여주면 인간의 뇌는 그것이 '움직인다'고 인식하게 된다. 이때 프레임이 얼마나 빠르게 교체되느냐가 움직임이 얼마나 매끄러운가를 결정하게 된다.

프레임의 교체 속도가 순간적으로 느려져서 '이거 움직여야 하는데?'라 생각하는 타이밍에 정지된 화면이 노출되는 시간이 길어지면 사람들의 뇌에 딱! 걸리게 된다. 숫자로만 놓고 보면 0.1~0.5초 정도의 짧은 시간이더라도 사용자 경험을 크게 저하시킨다.

이거 왜 이래;;

앱이 매끄럽게 동작한다는 인식을 주기 위해서는 초당 60 프레임을 유지하는 것이 중요하다. 즉 1초에 최소 60장의 이미지를 연속으로 보여줘야 인간의 뇌를 완벽하게 속일 수 있는 것이다. 이 60이란 숫자는 내가 임의로 정한 게 아니고, 사람의 인체 구조상 그렇게 정해져 있다.

위에서 화면에 UI를 그리는 화가 역할을 쓰레드라는 일꾼이 한다고 언급했다. 1초(1000ms)를 60 프레임으로 나누면 16.6ms인데, 16ms내로 입력, 처리, 통신 작업과 더불어 그림 한 장을 완성해서 납품해야 하는 셈이니 쓰레드는 기본적으로 바쁘게 움직이고 있다는 것이 느껴질 것이다.

물론 안드로이드의 일꾼들은 인간과 비교도 안되게 일처리 속도가 빠르지만, 그럼에도 16ms를 넘겨버릴 만한 일거리는 차고 넘친다. 와이파이에 연결해서 웹 서핑을 하거나, 친구가 카톡으로 보낸 사진을 저장하는 등의 일은 우리가 앱을 쓸 때마다 밥 먹듯이 일어나지만, 사실 얘네들은 쓰레드가 혼자서 순식간에 처리하기엔 무거운 작업에 속한다. 메인 쓰레드 한 명에게 이 모든 일을 맡겨버리면 당연히 일거리가 터지게 된다.🤯 작업이 갑자기 몰리는 순간 그림 그리는 일은 뒷전이 되고, 이로인해 프레임 교체 속도가 저하되는 현상이 발생한다. (이걸 프레임 드랍이라고 부른다)

물론 성능 좋은 폰을 쓸수록 야물딱지게 일을 처리하지만, 시간당 처리량엔 한계가 있다. 즉 여러분이 쓰고 있는 앱이 버벅대는 순간 메인 쓰레드는 대략 아래 사진 속 매점 직원 같은 상황에 처한 것이다.

영화 써니의 한 장면

사용자가 이 앱이 잘 돌아가고 있구나를 판단하는 기준은 결국 UI의 반응 속도다. '이 앱은 빠릿빠릿하게 움직이네'를 느끼게 해주려면 화면에다 최대한 16ms 안에 보여줘야 할 화면을 잘 보여주는 게 중요하다.

해결 방법은 간단하다. 부서에 일꾼을 더 추가하면 된다. 개발자는 복잡한 계산이나 통신 작업을 지원해 줄 일꾼을 적절하게 추가로 생성해서, 일꾼 하나는 그림 그리는 역할에 전념할 수 있도록 하면 된다. 그래서 안드로이드는 메인 쓰레드가 화가🎨 역할에만 충실하도록 앱을 만드는 것을 공식적으로 권장하고 있다.

서브로 생긴 일꾼들이 하는 일이 좀 오래 걸릴 것 같다? 그럼 메인쓰레드가 대충 이런 걸 그리게 시키면 된다.

어디서 많이 봤을거다

이 동글뱅이의 정식 명칭은 ProgressBar다. 수많은 소프트웨어를 경험하면서 사람들은 이런 원이 가운데에 뿅 하고 등장한 순간 잠깐 대기해야한다는 사실을 무의식적으로 학습했다.

얘가 빙글빙글 잘 돌고 있으면 어쨌든 화면이 멈춘 것은 아니기 때문에, (물론 이것도 너무 길어지면 분노를 유발하지만) 사람들이 인내하는 시간이 적어도 16ms보다는 길어진다.

잠깐! 그럼 일꾼은 많이 만들수록 이득 아닌가요? 🤔

그건 아니다. 5명이서 하는 팀플 10명이 한다고 2배로 빨리 끝나지 않는다. 실제 회사에서도 사람을 무작정 많이 뽑지 않는 이유를 다들 알 거다. 채용하는 과정에서도 돈이 들고, 사무실에 수용 가능한 인원은 한정되어 있고, 월급도 줘야 하기 때문이다. 쓰레드도 똑같다. 동시에 일하는 쓰레드의 수는 한정되어 있어야 오히려 효율적이다. 뭐든 적당히가 중요하다.

이렇게 개발자는 여러 명의 일꾼을 적절하게 늘려서 일 시키는 작업을 해줘야 하는데, 이것을 멀티 쓰레드 프로그래밍이라 부른다.

그럼 메인 쓰레드가 그림만 그리게 일꾼 여럿 뽑아놓으면 끝이냐? 아니다. 화면을 그리는 시간 자체가 또 오래 걸릴 수도 있다. 앱을 만들 땐 화면의 각종 구성 요소들을 배치하기 위해 '이 버튼은 여기다 놓고... 아이콘은 화살표 모양으로... 배경 색깔은 빨강으로 하자~'라고 시키는 명세서 같은 것을 코드로 만들게 된다. 신속하게 화면을 그리려면 '이렇게 그려'라는 명령이 가급적 단순해지도록 해야 한다. 여기에도 또 여러 가지가 신경 쓸 포인트가 있지만...

이미 TMI가 넘쳤다

개발자가 프로그래밍할 때 위와 같은 것들이 고려되지 않으면 앱은 신나게 버벅거리게 된다. 그리고 안드로이드는 이런 일시적으로 화면이 멈추는 현상이 5초 이상 지속되면 그 앱을 강제 종료 시켜버리는 강려크한 정책까지 가지고 있다.

이런 사정으로 느린 앱이 최악의 경우 강제 종료까지 되면, 분노의 1점 리뷰를 장전한 사람들이 몰려온다.😠

맺음말

여기까지 앱이 렉 걸리는 원인을 알아보았다.

길고 구구절절하게 쓰긴 했지만, 어떤 앱의 사용 경험이 구린 이유를 사용자가 양해해 줄 필요는 없다. 별로인건 별로인 거고, 나도 다운받은 앱이 느리거나 쓰기 불편하면 바로 지워버린다. 앱이 반응속도가 별로면 힘들게 확보한 사용자들에게 어서 우리 서비스를 버리고 이탈해주세요!! 라고 나가는 문을 활짝 열어놓는 거나 다름없다. 따릉이처럼 나라에서 독점하는 사업이라 대체제가 없다면 욕하면서도 그냥 쓰겠지만, 경쟁 서비스가 존재한다면 이는 치명적이다. 그래서 실제 앱 개발자 채용 공고에는 이런 문구가 있기도 하다.

앱에서 최적화 대상에는 반응속도뿐만 아니라 배터리 사용량, 데이터 사용량 등도 포함된다. 글에서는 이러쿵저러쿵 써놓긴 했지만, 사실 성능 최적화는 쉽지 않다. 나도 쪼렙이라 잘 모른다. 이건 그냥 영원한 숙제(?) 같은 것이다.

 

나는 사용자가 얼마 없는 개인 앱만 만들어봐서 심한 말을 들어본 적은 없지만, 아주 가끔 리뷰에 1점이 남겨져있으면 좀 신경 쓰인다. 기업에서 만든 앱은 기업의 이름 뒤에 직원들의 존재가 숨겨져있어서 그런지, 거의 악담처럼 느껴지는 강렬한 리뷰도 달려있다. 플레이스토어 리뷰에 달리는 답글들이 매크로라 생각하는 사람들이 많던데, 관리자 페이지에 그런 자동화 설정을 하는 기능은 없다. 심장이 뛰고있는 살아있는 사람이 직접 다는 거다. 아무리 월급 받고 하는 일이라 해도 험한 말을 보면 기분이 좋진 않을 것이다. 1점을 주는 건 자유지만 리뷰는 살살 쓰자.

- 끝 -