react-virtualized로 대용량 리스트 렌더링 최적화하기

react-virtualized를 적용하며 성능 개선한 내용을 정리해보려고 한다. 단순히 가상화 리스트를 도입한 것에서 그치지 않고, Chrome 개발자 도구를 통해 메모리 구조와 GC 작동 방식까지 추적하며 성능 최적화가 실제로 어떤 효과를 가져오는지를 직접 비교해봤습니다. 대용량 리스트 렌더링, 문제는 성능과 메모리였다 프로젝트에서 최대 10만개에 이르는 오디오 스크립트 데이터를 한 번에 보여줘야 했습니다.. 레거시 프로젝트에선 단순히 .map()을 통해 리스트를 출력하는 방식으로 개발 되었었지만, 예상대로 다음과 같은 문제가 있었다. 스크롤 시 끊김 현상 발생 DevTools의 JavasScript Heap 메모리 지속 증가 사용자 경험(UX) 저하 이런 상황이 존재하여 성능 최적화 및 리스트 가상화 도입을 하게 되었다. ...

April 2, 2024

WebRTC에서 Agora로: 왜 Agora SDK를 선택했을까?

실시간 영상 통신을 안정적으로 서비스하는 것은 생각보다 복잡했습니다. 특히 네트워크 환경이 불안정한 해외 사용자를 대상으로 할 경우, 그 어려움은 더 커집니다. 이번 글에서는 기존 WebRTC 기반 1:1 연결 구조에서 Agora RTC SDK로 전환하게 된 계기와, 그 과정에서 네트워크 품질 측정과 Agora 구조를 소개하고자 합니다. 왜 Agora SDK 였을까? 기존 WebRTC 기반 연결 구조는 다음과 같은 문제점을 가지고 있었습니다. STUN/TURN 서버 인프라 구축 비용 증가 해외 네트워크 접속 불안정 연결 전 품질 측정의 어려움 👉 이전 글: 해외 사용자 대상 WebRTC 연결, 어떻게 진단했을까? ...

February 26, 2024

React Native에 CodePush 도입기

React Native 기반 앱 프로젝트를 운영하면서, Store 심사 지연으로 인해 Hotfix 배포나 간단한 UI 수정조차 수일 이상 소요되는 일이 잦았습니다. 특히, 사용자(근로자)에게 주일 마다 피드백을 받아오는 상황에서 잦은 빈도로 업데이트되던 서비스였기 때문에, 이런 병목은 전체 업데이트 일정에 큰 영향을 끼쳤습니다. 이러한 문제를 해결하기 위해 CodePush 기반의 무중단 배포 환경을 구축했습니다. 왜 CodePush를 도입했는가 Microsoft에서 제공하는 CodePush는 React Native 앱의 JS 번들만 OTA(Over-the-Air) 방식으로 배포할 수 있도록 해주는 서비스입니다. 앱을 재설치하거나 스토어 심사를 거치지 않고도 즉각적인 업데이트가 가능한 구조입니다. ...

January 20, 2024

Next.js에서의 styled-components SSR 이슈와 해결

Next.js 프로젝트(v12)에서 styled-components를 적용하며 발생한 스타일 FOUC(Flash of Unstyled Content) 문제와 이를 해결한 과정을 정리했습니다. 문제 상황: SSR 환경에서의 스타일 미적용 Next.js는 기본적으로 서버 사이드 렌더링(SSR) 을 지원하며, 초기 페이지 로드 시 HTML을 미리 생성해 클라이언트에 전달합니다. 프로젝트 초기에 아래와 같은 문제가 발생했습니다: 새로고침 시 스타일이 적용되지 않은 HTML이 먼저 렌더링됨 이후 JS가 로드되면서 styled-components 스타일이 적용됨 사용자 입장에서 순간적으로 깨진 UI가 보이는 경험을 하게 됨 이는 흔히 말하는 FOUC (Flash of Unstyled Content) 플리커 현상으로, SSR 환경에서 styled-components를 사용할 때 자주 발생하는 이슈입니다. ...

July 23, 2023

Context API -> Recoil 성능 개선 과정

이전 글에서 클라이언트 상태와 서버 상태를 분리하는 과정에서 Context API 대신 Recoil을 도입하게 된 이유를 정리한 바 있습니다. 이번 글에서는 해당 구조가 실제 프로젝트에서 어떻게 적용되었는지, 그리고 Recoil을 사용함으로써 성능 측면에서 어떤 개선 효과가 있었는지를 자세히 공유하려고 합니다. 왜 Recoil이 필요했는가 이전 글에서 언급했듯이 처음에는 Context API만으로도 충분해 보였습니다. 작은 단위의 상태들을 중앙에서 관리하고, 빠르게 구조화할 수 있었기 때문이다. 하지만 프로젝트가 커지고 기능이 쌓이면서, Context를 사용하는 컴포넌트가 많아지고, 하나의 값 변경에도 여러 곳에서 렌더링이 발생하기 시작했다. ...

May 28, 2023