반디북
모던 리액트 Deep Dive
Ch7
준영
도은
  • 애플리케이션에서 발생하는 버그와 디버깅 이슈는 리액트 밖에서 일어날 수도 있다.
  • 자바스크립트 메모리, 네트워크, 소스, 실제 HTML 및 CSS 등 리액트가 아닌 일반적인 디버깅을 수행하려면
  • 리액트 개발 도구가 아닌 좀 더 범용적인 도구를 활용해야 한다.
  • 일반적인 브라우저 환경에서 디버깅 하는 도구 : 브라우저 개발자 도구

7.1 크롬 개발자 도구란?

  • 개발자 도구에서 웹 사이트를 제대로 디버깅하고 싶다면, 시크릿 모드로 여는 것을 권장
    • 브라우저 확장 프로그램은 다른 정보를 추가할 수 있으므로
    • 시크릿 모드를 통해, 순수하게 웹페이지와 관련된 정보만 확인

7.2 Element 탭

  • 현재 웹페이지를 구성하고 있는 HTML, CSS 등의 정보 확인
  • 직접 코드를 수정해서 웹 페이지에서 어떻게 보이는지 빠르게 확인 가능
  • 핫 리로딩도 필요없어서, 빠른 작업이 가능

7.3 Source 탭

  • 웹 애플리케이션을 불러오기 위해 실행하거나 참조된 파일을 확인 가능
  • 자바스크립트 파일부터, CSS, HTML, 폰트까지 다양한 파일 정보를 확인 가능
  • 디버깅하고 싶은 파일을 직접 열어 확인이 가능
  • 프로덕션 모드의 경우, 파일이 모두 압축되어 있어서 개발 모드에서는 유용하게 사용 가능
  • 소스 코드를 열어서, useEffect 내부 코드에 중단점을 만들어 살펴볼 수도 있다.

7.4 Network 탭

  • 웹 페이지를 접속하는 순간부터 발생하는 모든 네트워크 관련 작동이 기록
  • HTTP 요청부터 웹 소켓 등 웹페이지가 외부 데이터와 통신하는 정보를 확인

7.5 Memory 탭

  • 현재 웹페이지가 차지하고 있는 메모리 관련 정보 확인
  • 애플리케이션에서 발생하는 메모리 누수, 속도 저하, 웹페이지 프리징 현상을 확인 가능
  • 프로파일링 작업을 거쳐야 원하는 정보 확인 가능
  • 프로파일링 유형은 크게 3가지
    1. 힙 스냅샷: 현재 메모리 상황 스냅샷
    2. 타임라인의 할당 계측: 현재 시점의 메모리 상황이 아닌, 시간의 흐름에 따라 메모리의 변화 확인
    3. 할당 샘플링: 메모리 공간을 차지하고 있는 자바스크립트 함수 확인 가능

7.5.1 자바스크립트 인스턴스 VM 선택

  • 페이지가 자바스크립트 힙을 얼마나 점유하고 있는지를 나타낸다.
  • 크키만큼 사용자의 브라우저에 부담

🤔 메모리 점유에 영향을 미치는 요인들

실행 중 웹페이지와 관련된 다양한 데이터를 저장하고 처리하는 데 사용

  • 컨텐츠의 양
  • 스크립트와 라이브러리
  • DOM 요소의 수
  • 캐싱
  • 메모리 누수

🤔 FE 개발자가 할 수 있는 메모리 점유 절약 전략

전체적인 다이어트

  • 이미지 최적화
  • 코드 스플리팅 (초기 로딩 시 메모리 사용량 절약)
  • 불필요한 DOM 요소 제거 (→ 리액트가 1:1 구조로 생성하는 FiberNode가 해당 배열을 담아야 하는 array 크기가 늘어남)
  • 이벤트 리스너 관리 (사용하지 않는다면 제거)
  • 등등 불필요하게 저장되어야 하는 부분을 다이어트

7.5.2 힙 스냅샷

  • 현재 페이지의 메모리 상태를 확인해 볼 수 있는 메모리 프로파일 도구
  • 촬영하는 시점을 기준으로 메모리 현황 확인
  • 의심이 되는 지점을 먼저 추측하고, 두 개 이상의 스냅샷을 찍어서 확인해보는 것을 추천

7.5.3 타임라인 할당 계측

  • 시간의 흐름에 따라 메모리 변화를 확인할 수 있는 기능
  • 메모리 변화를 일으킨 변수가 무엇인지, 해당 변수가 어느 정도의 크기를 차지하고 있는지 확인 가능

참고하면 좋은 자료

메모리 누수가 있으면 뭐가 문제일까?

  • GC 활동이 늘어나면, CPU 사용량이 늘어남
  • CPU가 활발하게 동작해야 하는 작업이 늘어나면, 이벤트 루프가 블로킹되어서 연산이 느려짐

CPU와 이벤트 루프틑 어떤 관계일까?

  • JavaScript는 싱글 스레드 언어 (= 한 번에 하나의 작업만 가능)
  • 브라우저는 JavaScript 엔진을 사용하여 JavaScript 코드를 해석하고 실행
  • 이 JavaScript 코드는 CPU에 의해 실제로 작업을 수행
  • 브라우저에서 JavaScript 코드가 실행되려면, 반드시 CPU가 그 명령을 처리해야 하므로, CPU는 JavaScript 코드의 실행에 필수적인 역할
  • 따라서, CPU가 바쁘면 이벤트 루프에 블로킹이 생기게 됨

어떻게 해결할까?

  • 힙메모리를 늘려주거나
  • 메모리 누수의 범인을 디버깅

V8의 GC

image

  • GC에서 살아남은 객체가 많다면, Old Generation 영역이 꽉 차게 됨 → 프로세스 종료

🤔 힙메모리만 늘려주면, 메모리 누수가 없어질까?

  • 보통 서치하면 해결책으로 --max-old-space-size 늘리라고.. → 본질적인 해결책이 아닐수도 (어차피 메모리 누수를 일으키는 코드라면)

대표적인 메모리 누수를 일으키는 요인들

  • 전역변수
  • 해제되지 않은 타이머 (clearTimeout 등)
  • 클로저