[Android] Thread 생성/소멸로 인한 오버헤드 개선(HandlerThread)

HeyU·2025년 5월 25일

Android

목록 보기
2/2

📌 문제 상황

GPIO 상태를 읽어오는 Native 코드를 살펴보다가, 상태를 체크할 때마다 새로운 Thread를 빠르게 생성하고 바로 소멸하는 구조를 발견했다.
Thread 생성과 소멸은 시스템 자원을 소모하고, 빈번하게 반복될 경우 CPU 스케줄러가 Thread를 계속 교체(switching)해줘야 하므로 이 과정에서 불필요한 오버헤드가 발생하게 된다.

📌 레퍼런스 조사

Thread를 재생성 하지말고 재활용하자! 라는 생각에 처음에 알아본 방법은 Thread pool이었다. Thread Pool은 여러 개의 Thread를 미리 생성해두고, 작업 큐를 통해 병렬로 비동기 작업을 처리하는 방식이다.

처음 목적은 병렬 처리가 아닌 단일 스레드에서 순차적으로 상태를 읽어오는 것이었기 때문에, 단일 Thread Executor인 SingleThreadExecutor를 고려했다. 그러다 조사 중에 HandlerThread라는 Android SDK에서 제공하는 클래스가 있다는 걸 발견했다.

📌 SingleThreadExecutor vs HandlerThread

둘은 단일 스레드라를 생성하여 순차적으로 실행한다는 공통점이 있지만,

  • SingleThreadExecutor는 내부에 작업 큐를 두고 순차적으로 작업을 처리하는 Thread Pool의 일종이며,
  • HandlerThread는 Android에서 제공하는 Looper와 MessageQueue를 가진 백그라운드 Thread라는 차이점이 있었다.


📌 HandlerThread 선택

이 프로젝트에서 원하는 건 단일 스레드에서 순차적으로 GPIO 상태를 읽고,
필요시 JS Thread(React Native JS)와 통신하는 것이다.

  • 안드로이드 SDK에서 기본으로 제공하는 클래스이므로 안드로이드에 특화되어 있으며
  • UI 스레드(메인 스레드)가 통신하거나
  • 순차적인 백그라운드 작업을 관리하는데 유용하다는 장점이 있었기 때문이다.

그리고 HandlerThread의 작업 처리 구조가 JS Thread의 Event Loop와 유사한 점이 있다는 점도 긍정적으로 보았다. JS Thread도 task queue와 event loop를 사용해서 순차적으로 처리하는 구조다. 이러한 유사성은 다른 React Native 개발자들이 HandlerThread 처리 과정이 더 잡근성이 좋을 거라 판단했다. 참고로 ExecutorService를 이용하려면, Thread Pool 개념에 대한 사전 이해가 필요하기 때문이다.

📌 결과

  • 개선 전 : 최대 3초
  • 개선 후: 최대 1.7초

=> 최종적으로 JS 브릿지를 통해 넘어와서 상태값을 읽기까지 걸린 시간이 감소한 것을 볼 수 있다.

  • 기존 GPIO 상태 체크 로직은 반복적인 Thread 생성/소멸로 인한 오버헤드와 CPU 스케줄링 비용의 문제가 발생.
  • HandlerThread를 통한 단일 Thread 재활용 구조로 개선하여
    성능과 안정성을 확보.

💬 회고

이번에 마주했던 문제는 컴퓨터공학과에서 배웠던 내용을 다시 떠올리게 해 주었다. 신사업팀에서는 레거시를 볼 기회가 거의 없었기 때문에 이러한 문제를 마주할 일이 없었다. 네이티브를 건드린다고 하더라도 라이브러리를 커스텀 하는 정도였기 때문에 이번 문제 해결과정이 정말 즐거웠다.

레퍼런스들을 참고하면서 ThreadPool, ExecutorService 종류, Queue에서 작업을 처리하는 과정, Thread Context Switching 개념 등을 알게되었다.
뿐만 아니라, 새로운 개념을 바로 도입하는 게 아니라 처리 과정이 목적에 부합하는지, 단점이 크리티컬하지 않은지, 비슷한 처리 방식이 있다면 어떤 개념이 프로젝트에 더 적합한지 비교하면서 필요한 지식을 어떻게 받아들이고 적용해야할지에 대해서도 배울 수 있었다.

그리고 정확한 비동기 처리 과정과 작업의 딜레이 현상 개선을 위해 Thread에서 작업 처리 과정을 깊게 이해해야겠다는 필요성을 느끼게되었다.
평소에도 딜레이 현상을 개선해야 사용자의 편의성이 높아지고, 이탈률을 줄이며, 만족도가 증가할 거라고 생각했기 때문에 이 개념이 흥미롭게 다가왔다.
그래서 JS Thread에 관해서 더욱 자세히 알아보고 싶다는 생각이 들었다. 다음에는 JS thread가 어떻게 비동기 처리를 수행하고, 어떤 구조로 동작하는지 공부해보려고 한다.

문제를 만날 때마다 새로운 개념을 접하게 되고, 각 개념의 연관성을 파악해서 부분적인 개념을 확장시켜 나가는 과정이 즐겁다. 문제를 마주하면 처음에는 힘들겠지만, 새로운 재료들로 다양한 문제와 이제껏 지나쳐 왔던 문제들을 해결할 수 있게 된다는 게 개발의 매력인 거 같다. 앞으로도 많은 문제를 마주하고, 많은 해결 과정을 거치면서 동료들에게 든든한 조력자가 되었으면 좋겠다. 그리고 나의 목표대로 최대한 많은 사람들을 만족시킬 수 있을 서비스를 개발할 수 있게 되면 좋겠다.

profile
모든 사람에게 평등한 서비스 개발을 목표로 하는 병아리 개발자

0개의 댓글