본문 바로가기
생각정리

동시성 프로그래밍 공부하며, 앱 성능 개선하기

by iOS_woo 2023. 3. 11.

요즘 동시성 프로그래밍을 공부하고 있다. 

CPU, 쓰레드, Queue, GCD 등등

며칠 전만해도 블록와이드를 개발하며 동시성 프로그래밍이 뭔지 몰랐다. 
하지만 우연하게 동시성 프로그래밍에 대한 강의를 들으며 개념에 대해서 알게 되었고, 

앱 개발을 하며 필요가 점점 부각되어서 동시성 프로그래밍에 대해서 공부하고 있다. 

왜 공부하게 되었나

앱에서 Rest API로 정보를 가져올 때에는 내가 굳이 다른 **Queue로 작업을 보내지 않아도 충분한 성능이 나왔다.

웬만한 네트워크 작업은 URLSession등의 기본 기능으로 Queue로 보내 다른 쓰레드에서 연산하게 해준다.
또한 데이터를 가공하는 연산 작업도 가끔씩 한순간만 발생하다보니 굳이 작업을 다른 쓰레드로 보내지 않아도 앱이 버벅이지 않았다.

하지만 코인 데이터를 1초마다 갱신해주는 것을 목표로 한 순간 상황이 달라졌다. 
다운로드 받는 것은 다른 쓰레드에서 동작하니 문제가 되진 않았지만, 기존의 방식데로 데이터를 메인쓰레드에서 전부 처리하면 앱이 1초마다 버벅이는 현상이 발생한다. 

버벅인다는 것은 예를 들어 앱에서 스크롤을 했을 때 툭툭 끊기면서 보여지는 것이다. 
왜 이런 현상이 발생한 것일까? 
아이폰은 60fps로 랜더링 되기 때문에 약 16ms(밀리초)가 화면의 리프레시 주기이다. 
이런 리프레시에 관련된 연산은 메인쓰레드에서 진행되는데, 열심히 화면 업데이트 작업을 하는 메인쓰레드에 갑자기 많은 연산을 요구하는 작업을 주게되면 어떤 현상이 발생할까?
무거운 연산 작업으로 인해 리프레시를 위한 연산이 밀리게 되고 결과적으로 화면이 버벅이며 보이게 되는 것이다. 

나 역시 어제까지도 작업들을 적극적으로  Queue로 보내주기 전까지는 1초마다 코인 데이터를 갱신하는 연산이 메인쓰레드에서 진행되느라 앱이 1초마다 툭툭 끊기는 증상이 있었다. 
처음에는 RestAPI의 문제인줄 알고 며칠에 걸쳐서 웹소켓으로 바꿔보았다.

한번에 모든 응답을 받고 한번에 전부 처리해야하는 RestAPI와 다르게 웹소켓은 조금씩 꾸준히 진행하는 연산이라 그런지 버벅임은 줄었다. 
하지만 여전히 앱이 버벅인다는 근본적인 문제는 해결되지 않았다. 

문제를 찾기 위해서 코드의 작업들을 하나씩 없애가면서 앱을 동작시켜보았고, 문제가 있었던 코드를 발견할 수 있었다. 
딕셔너리끼리 머지를 하고, 탐색하는 등의 많은 연산을 필요로 하는 작업이 메인쓰레드에서 돌아가는 것이 버벅이는 문제의 가장 핵심이었다. 
이런 식으로 문제를 인식하고 해결방법을 찾아가던 중에 우연하게도 동시성 프로그래밍에 대한 강의를 듣게 되었고,
작업을 Queue로 보내 메인쓰레드에 너무 많은 연산을 시키지 않도록 하는 방법들을 앱에 적용하기 시작했다. 

그 결과, 웹소켓으로 100여개의 코인을 끊임없이 업데이트 받고 화면에 가격, 거래량, 변동률 등을 실시간으로 업데이트 해줘도 전혀 버벅임이 없다. 
정말 행복한 순간이다. 

 

앞으로 어떻게 할 것인가?


문제를 해결하기 위해서 바이낸스, 업비트, 빗썸, 코인원, 코빗, 트레이딩뷰 등은 어떻게 데이터를 처리하는지 끊임없이 살펴보았다. 
바이낸스는 앱이 정말 쾌적했고, 수많은 코인 데이터가 화면에서 업데이트되지만 앱은 버벅이지 않았다. 
업비트는 유저가 스크롤을 하면 모든 코인 데이터가 화면에 갱신되는 것을 막아서 앱이 버벅일 확률을 없앤 듯 했다. 
빗썸과 코빗은 바이낸스처럼 깔끔했다. 

코인원은 나와 같은 증상이 있었다. 주기적으로 앱이 버벅인다. 

 

다른 사람들은 웹소켓을 사용할 때 실시간 데이터를 어떻게 처리하는지 깃허브에서 탐색도 많이 해보고, GPT에게도 많이 물어보았다.
여담이지만 GPT는 이럴 때 가끔 멍청하다. 

그런 과정을 겪고 실제로 앱이 바이낸스처럼 부드럽게 작동하게 되니 너무 행복하고 뿌듯했다. 
무거운 작업을 Queue로 보내는 작업을 해줄 때 @Published로 선언한 변수가 가끔씩 나를 괴롭게 해서 Combine의 Subject라는 개념도 공부해서 적용해보았다. 

이렇게 앱의 성능을 더 높이고 최적화할 수 있는 공부가 바로 동시성 프로그래밍 공부이다. 
앞으로도 더 많은 활용사례들을 살펴보고 내것으로 만들고 싶다. 
결과적으로 내 앱이 더 부드러워지고 훌륭한 유저 경험을 제공할 수 있지 않을까?

작업을 취소할 수 있는 Operation에 대해서도 공부해봐야 한다. 

할게 너무 많지만 뭐가 문제인지, 뭘 공부해야 하는지 몰랐을 때보다 지금이 몇 배는 더 좋다. 



--------
** Queue로 보낸다는 것이 무엇일까?
일반적으로 우리가 작성하는 코드와 화면 업데이트는 메인쓰레드에서 동작한다. 
하지만 메인쓰레드에 너무나 많은 연산이 몰리게 되면 여러 문제가 발생하게 되기 때문에 다른 쓰레드에 작업을 보내 처리해주는게 좋다.
이 때 iOS는 Queue(선입선출 대기열)에 개발자가 작업을 보내기만 하면 자동으로 여러 쓰레드로 분산시켜준다. 

댓글