flashlist

1 개의 포스트

discord

강력해진 디스 (새 탭에서 열림)

Discord는 React Native 기반 모바일 앱의 성능을 높이기 위해 사용 빈도가 높은 화면과 컴포넌트를 집중적으로 최적화했다. 서버 목록 가상화, 채팅 리스트 재활용, Android 이모지 피커 네이티브 전환, 이미지 포맷 변경 등을 통해 메모리 사용량과 시작 시간, 스크롤 성능을 개선했다. 특히 저사양 Android 기기에서 발생하던 빈 프레임과 앱 충돌을 줄이는 데 초점을 맞췄으며, 일부 기능은 플랫폼별로 다른 구현을 유지하는 비용까지 감수했다. ## React Native 전환과 성능 최적화 방향 - Discord는 데스크톱에 React, 모바일에 React Native를 사용해 여러 플랫폼에서 기능을 빠르게 출시해 왔다. - Android에서는 초기 성능 우려 때문에 React Native 도입을 주저했지만, Android 기기 성능 향상과 Hermes 엔진 등장으로 2022년 React Native 기반으로 전환했다. - 전환 후 특히 저사양 기기의 시작 시간이 문제였으나, 2023년에 중앙값 기준 시작 시간을 절반으로 줄였다. - 이후에는 일반 사용자보다 서버와 메시지, 이모지를 많이 사용하는 ‘파워 유저’를 중심으로 최적화를 진행했다. ## 서버 목록 가상화 - 기존 서버 목록은 화면에 보이지 않는 서버의 뷰와 아이콘까지 모두 메모리에 유지했다. - Discord는 무료 사용자 최대 100개, Nitro 사용자 최대 200개의 서버 가입을 지원하기 때문에 서버가 많은 사용자의 메모리 부담이 컸다. - 새 가상화 구현은 현재 화면에 표시되는 서버 정보만 메모리에 유지한다. - 남은 리소스를 드래그 앤 드롭 애니메이션 개선에도 활용했다. - 서버가 100개 이상인 사용자는: - 시작 시 메모리 사용량 14% 감소 - 전체 시작 시간 10% 감소 ## 네이티브 채팅 리스트 최적화 - 채팅 리스트는 이미 네이티브로 구현되어 있었지만, 프로파일링을 통해 로딩과 스크롤 과정의 병목을 추가로 발견했다. - 주요 개선 사항: - 버튼 같은 Application Component와 이미지 격자형 Media Mosaic 재활용 - 스포일러, 업로드 오버레이처럼 자주 사용되지 않는 요소의 지연 생성 - Media Mosaic 바인딩 성능 개선 - 메시지 컨테이너와 리액션 측정 속도 개선 - 채팅을 열기 전에 자주 사용되는 요소를 재활용 풀에 미리 생성 - 결과적으로: - 느린 프레임이 최대 60% 감소 - 구형 기기에서 렌더링 프레임 수 증가 - 채팅 리스트 메모리 사용량 약 12% 감소 ## Android 이모지 피커의 네이티브 전환 - 서버 하나당 최대 250개의 커스텀 이모지를 지원하며, 여러 서버를 사용하는 경우 수백 개의 이모지가 한 화면에 표시될 수 있다. - 저사양 Android 기기에서는 이모지를 스크롤할 때 placeholder조차 표시되지 않는 빈 프레임 문제가 발생했다. - 단순한 점진적 최적화만으로는 해결하기 어렵다고 판단해 Android 이모지 피커를 네이티브로 다시 작성했다. - 200개 서버의 이모지를 사용하는 극단적인 테스트에서도: - 빈 프레임이 완전히 제거됨 - 저가형 기기에서도 일관되게 부드러운 스크롤 제공 - 메모리 부족으로 인한 충돌 방지 - Android는 네이티브, iOS는 React Native로 유지하게 되어 코드베이스와 유지보수 복잡성이 증가했다. - 향후 React Native New Architecture와 Android 기기 성능 향상에 따라 이 구조를 재검토할 예정이다. ## GIF에서 WebP로 전환 - 미디어 프록시에 애니메이션 WebP 지원을 추가했다. - 애니메이션 이모지 포맷을 GIF에서 WebP로 변경해 저사양 기기에서도 최대 60FPS 렌더링이 가능해졌다. - 이미지 포맷 선택만으로도 디코딩과 렌더링 성능을 개선할 수 있음을 보여주는 사례다. ## ChannelList의 빈 화면 문제 제거 - Discord는 자체 React Native 리스트 구현인 FastList를 사용해 왔다. - 모바일 앱 재설계 과정에서 Shopify의 FlashList를 도입했으며, 정확한 요소 크기를 미리 지정하지 않아도 되는 점과 빠른 개발 속도를 장점으로 평가했다. - 그러나 실제로는 저사양 Android 기기에서 FlashList가 더 자주 빈 화면을 표시하는 문제가 나타났다. - Discord는 다시 FastList를 리팩터링해 ChannelList에 적용했고, 50달러 수준의 저가형 기기에서도 빈 화면 문제를 제거했다. ## 적용할 수 있는 성능 개선 원칙 - 화면에 보이지 않는 요소는 가상화해 메모리에 보관하지 않는다. - 반복적으로 생성되는 UI는 재활용 풀과 recycling을 활용한다. - 자주 사용되지 않는 UI는 lazy inflation으로 늦게 생성한다. - 성능 문제가 심각한 경우 기존 프레임워크를 무리하게 유지하기보다 특정 화면을 네이티브로 재작성할 수 있다. - 평균적인 기기뿐 아니라 저사양 기기와 파워 유저의 극단적인 사용 시나리오를 기준으로 테스트해야 한다. - 범용 라이브러리가 항상 최선은 아니므로 실제 기기에서 blanking, 프레임 저하, 메모리 부족 여부를 검증해야 한다. Discord의 사례는 React Native를 전면적으로 포기하거나 모든 기능을 네이티브로 바꾸기보다, 병목이 명확한 부분만 가상화·재활용·지연 로딩·네이티브 구현으로 보완하는 접근을 보여준다. 특히 저사양 기기에서의 실제 사용자 경험을 기준으로 성능을 측정하고, 필요하다면 플랫폼별 구현 차이를 유지하는 것이 실용적인 전략이다.