SlideShare a Scribd company logo
Chrome DevTools로
JS 메모리 누수(Memory Leak) 디버깅하기
교육솔루션팀 Daniel
daniel@grepp.co
세션에서 다루는 내용
메모리 이슈의 3가지 증상
메모리 관련 Chrome DevTools 기능
라이브 클래스룸 메모리릭 디버깅 / 해결 과정
라이브 클래스룸 3
발생한 문제점 4
“브라우저에서 이 페이지가 메모리 많이 먹는다고 경고해요”
“이거 왜 안나가지죠?”
“새로고침해도 한참 기다려야 새 페이지가 로드 돼요”
“저만 멈췄나요?”
음.. 왜 그럴까요? ㅎㅎ..
발생한 문제점 5
메모리 문제가 있는게 아닐까?!
발생한 문제점 6
메모리 디버깅
해본 적 없음
발생한 문제점 7
메모리 이슈를 디버깅하면서 배운 내용과 해결 과정을
압축해서 공유해드립니다.
메모리 이슈의 3가지 증상
메모리 이슈의 3가지 증상 9
1. 페이지가 시간이 지남에 따라 느려진다
시간이 지남에 따라 느리다고 느껴지는 경우 메모리 누수, 즉 메모리릭(Memory Leak)이 발생한다고 볼 수 있다.
2. 페이지가 일관되게 느리다
페이지가 처음부터 느리다고 느껴진다면, 이는 Memory bloat으로 볼 수 있다.
기본적으로 필요한 메모리보다 더 많은 메모리를 사용하는 것을 말한다.
3. 페이지가 뚝 뚝 끊긴다
가비지 콜렉션(Garbage Collection)이 너무 자주 일어날 때 발생한다.
GC가 돌면 모든 JS 스크립트의 실행이 중지되기 때문에 이 경우 잦은 GC를 의심해볼 수 있다.
메모리 이슈의 3가지 증상 1
0
1. 페이지가 시간이 지남에 따라 느려진다
시간이 지남에 따라 느리다고 느껴지는 경우 메모리 누수, 즉 메모리릭(Memory Leak)이 발생한다고 볼 수 있다.
라이브 클래스룸은 1번 증상이었고
메모리릭이 문제일 것으로 예상하고 접근함.
메모리 이슈의 3가지 증상 1
1
그래서 뭐가 문제가 되는지
어떻게 알 수 있는데?
메모리 관련 Chrome DevTools 기능
Task Manager
메모리 관련 Chrome DevTools 기능 – Task Manager 1
3
Chrome 우측 상단 메뉴 > More Tools > Task Manager
Task Manager는 열린 페이지의 실시간 메모리 사용량을 모니터링할 수 있는 도구이다.
중요한 곳은 Memory Footprint와 Javascript Memory 컬럼이다.
메모리 관련 Chrome DevTools 기능 – Task Manager 1
4
• Memory Footprint : native memory 사용량을 보여준다. DOM 노드는 네이티브 메모리에
저장되는데, 만약 이 컬럼 값이 증가한다면 DOM 노드가 증가한다는 의미다.
• Javascript Memory : JS Heap 사용량을 보여준다. `()`로 감싸진 부분은 live number로
현재 페이지에서 접근 가능한 객체들이 사용중인 메모리를 뜻한다. 이 부분이 증가한다는
것은 객체가 새로 생성되거나, 이미 존재한 객체가 더 커진 걸 의미한다.
1
5
Task Manager 띄워보고 카메라 영역을
페이지네이션 한 결과…
메모리 관련 Chrome DevTools 기능 – Task Manager
메모리 관련 Chrome DevTools 기능 – Task Manager 1
6
초기 상태
여러번 페이지네이션 후
56MB 증가 93,000K증가
일단 페이지네이션하면 메모리릭이 발생하는 것은 파악했는데,
좀 더 자세히 알아볼 수 없을까?
메모리 관련 Chrome DevTools 기능
Performance Profile
메모리 관련 Chrome DevTools 기능 – Performance Profile 1
8
Chrome DevTools > Performance > Memory 체크박스 선택(활성화) > Record
Performance profile을 수행하면 시간에 따른 메모리 사용량을 각 항목별(JS Heap,
Documents, Nodes, Listeners)로 그려준다.
메모리 관련 Chrome DevTools 기능 – Performance Profile 1
9
• 모든 항목에 대해서 그래프가 계단식으로 그려진 것을 확인했다.
• JS Heap에서 메모리릭이 발생하고 있고, 할당된 Listeners가 해제되지 않고 있다. 그리고
Documents, Nodes 가 쌓여간다.
페이지네이션 10회 시도 후 GC 시킨 과정을 기록한 performance profile
메모리 관련 Chrome DevTools 기능
Memory Allocation Timeline
메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2
1
Chrome DevTools > Memory > Profiles > Allocation instrumentation on timeline
Allocation Timeline은 시간에 따른 메모리 할당/해제를 막대 차트로 시각화해서 보여준다.
메모리 할당은 파란색 막대로, 메모리 해제는 회색 막대로 나타낸다.
메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2
2
• 페이지네이션 할 때마다 파란색 막대가 생성되는 것을 확인했다. 회색 막대는
거의 보이지 않는다.
• 0~5초 사이에 파란 막대를 선택해보고 Retained Size 기준으로 내림차순
정렬하니 AnimationItem 생성자가 system 다음으로 가장 많은 메모리
차지한다. 해당 생성자는 lottie에서 호출하고 있다.
페이지네이션 10회 시도 후 GC 시킨 과정을 기록한 Allocation Timeline
메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2
3
• 페이지네이션으로 인해 변경되는 컴포넌트를 살펴보니, 내부에서 Lottie.vue
를 사용하고 있었다.
• 해당 컴포넌트가 mount되면 lottie.loadAnimation() 함수를 호출해
애니메이션 인스턴스(AnimationItem)를 생성하고 ref에 저장하고 있었다.
• 그래서 해당 인스턴스를 unmount시에 destoy하는 로직을 추가했다. 결과는?
Lottie.vue 파일 내 setup 부분
메모리 관련 Chrome DevTools 기능 – Lottie.vue 수정 후 Performance Profile 2
4
• Lottie.vue 파일 수정 후 performance profile 측정한 결과 GC가 돌때마다
JS Heap이 뚝 뚝 떨어지는 것을 확인했다!
• Documents, Nodes, Listeners는 여전히 계단식을 띔.
• 할당 후 해제하지 않은 Listeners가 있는지 먼저 살펴보자!
Lottie.vue 파일 수정 후 측정한 performance profile
메모리 관련 Chrome DevTools 기능 – Listeners 디버깅 2
5
RepeatableLottie.vue 파일 setup 부분
• 컴포넌트들을 살펴보니 Lottie.vue를 wrapping한 RepeatableLottie.vue
컴포넌트를 사용하고 있었다.
• 해당 컴포넌트는 Lottie 애니메이션이 다음번 실행될
여부(playbackEnqueued)를 저장해뒀다가 애니메이션이
종료(complete)되었을 때 애니메이션을 다시 실행하도록 하기 위해
만들어진 것으로 보였다.
• 14번 라인에 ‘complete’ 이벤트 리스너를 추가하고 있지만 해제하는 라인은
보이지 않는다.
• 이벤트 리스너를 해제하는 로직을 추가하기로 했다. 또 로직을 좀 더 간단히
수정하기로 했다.
2
6
RepeatableLottie.vue를 대체한 ClapAnimation.vue 컴포넌트 setup 부분
• `v-if` directive를 사용하여 필요한 경우에만 lottie를 렌더링하도록 하고,
unmount 할 때 complete 이벤트 리스너를 제거하도록 수정해보았다.
• 결과는?
메모리 관련 Chrome DevTools 기능 – Listeners 디버깅
메모리 관련 Chrome DevTools 기능 – Lottie.vue 수정 후 Performance Profile 2
7
• RepeatableLottie.vue를 교체하고 이벤트 리스너를 제거해준 뒤
performance profile 측정한 결과 GC가 돌때 listeners가 감소했다!
• Documents, Nodes는 여전히 계단식을 띈다. Detached DOM이 있는지
살펴봐야 한다.
이벤트 리스너 제거 후 측정한 performance profile
메모리 관련 Chrome DevTools 기능 – Detached DOM 2
8
Detached DOM:
DOM tree에서 제거되었지만 JS에 의해
여전히 reference 되고 있는 element
메모리 관련 Chrome DevTools 기능 – Detached DOM 2
9
메모리 관련 Chrome DevTools 기능
Memory Heap Snapshots
3
1
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
Chrome DevTools > Memory > Profiles > Heap Snapshot
Heap Snapshot은 특정 순간의 JS 오브젝트와 DOM 노드 사이의 메모리 distribution을
보여준다.
이를 활용해서 Detached DOM을 찾아낼 수 있다.
3
2
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
• 첫 번째 스냅샷은 Major GC후 초기 메모리 상태를 기록한 스냅샷
• 두 번째 스냅샷은 페이지 전환 10회 시도 후 메모리 스냅샷이다.
• 첫 번째 스냅샷과 두 번째 스냅샷에서 detached 키워드로 필터링한
결과를 비교하면, detached DOM들의 retained size가 일제히 증가한
것을 확인됨.
• 대부분의 detached DOM들이 SVG 관련 element 들로 확인됨.
초기 상태 힙 스냅샷
페이지네이션 10회 시도 후 GC 한 스냅샷
3
3
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
SvgIcon.vue 컴포넌트를 사용하는 LiveClassProfile 컴포넌트
SvgIcon.vue
• SVG 관련 컴포넌트를 살펴보니 프로필 컴포넌트 내부에서 <SvgIcon />
컴포넌트를 사용하고 있었음
• <SvgIcon /> 컴포넌트는 svg definition을 불러와 image sprite 기법으로
svg를 사용하는 컴포넌트
• 이 컴포넌트를 제거하고 힙 스냅샷을 찍어보면?
3
4
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
• 대부분의 detached SVG element가 제거된 것을 확인!
SvgIcon 컴포넌트 제거 후 페이지네이션 시도한 뒤 기록한 Heap Snapshot
3
5
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
SvgIcon
3
6
메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots
• <SvgIcon /> 컴포넌트를 별도의 inline svg 컴포넌트로 교체 후 스냅샷
기록한 결과 detached DOM들이 다시 생기긴 했지만, 초기 상태와 거의
유사한 수준
• Svg를 아예 없앨 수도 있지만(img 태그 활용해서), CSS로 svg의 색상을
변경하기위해 어쩔 수 없이 이 방식을 채택
SvgIcon 컴포넌트를 inline svg 컴포넌트로 교체 후 기록한 Heap Snapshot
메모리릭 디버깅 전/후 개선 결과 비교
3
8
메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교
개선 전 개선 후
스냅샷 1 스냅샷 2 델타
124MB 169MB +45MB
스냅샷 1 스냅샷 2 델타
127MB 118MB -9MB
3
9
메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Allocation Timeline)
Memory Allocation
+31MB
Memory Allocation
+990KB
개선 전 개선 후
4
0
메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Performance Profile)
개선 전 개선 후
항목 First GC 페이지네이션 & Second GC 델타
JS Heap 112MB 132MB +20MB
Documents 4개 14개 +10개
Nodes 3307개 17243개 +13936개
Listeners 459개 499개 +40개
항목 First GC 페이지네이션 & Second GC 델타
JS Heap 94MB 91MB -3MB(-100%)
Documents 5개 5개 +0개(-100%)
Nodes 4507개 5041개 +534개(-96%)
Listeners 473개 473개 +0개(-100%)
4
1
메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Allocation Timeline)
아직 개선의 여지가 남아있습니다.
그렇지만, 당장 급한 불은 껐습니다.
정리 및 내가 배운 내용
정리 4
3
1. Lottie 애니메이션 인스턴스가 unmount시에 destroy 되도록 수정
2. Lottie 애니메이션 인스턴스에 추가한 이벤트 리스너가 unmount시에 remove 되도록 수정
3. <SvgIcon /> 컴포넌트를 별도 svg 컴포넌트로 교체
내가 배운 내용 4
4
1. 메모리릭이 의심되면 Task Manager로 메모리를 모니터링 해보자
2. 큰 그림을 보려면 Chrome Performance Profile을 활용하자
3. JS Heap 메모리릭은 Memory Allocation Timeline으로 진단할 수 있다
4. Detached DOM은 2개 이상의 Heap Snapshot을 찍어서 비교하면 진단할 수 있다
References 4
5
• Chrome Developers - Record heap snapshots
• Chrome Developers - Memory terminology
• 자바스크립트에서 메모리 누수의 4가지 형태
• Vue 컴포넌트 - 메모리 누수 분석하기
• Finding and debugging memory leaks in JavaScript with Chrome DevTools
• Vue cookbook - Avoiding Memory Leaks
• Toast UI - 당신이 모르는 자바스크립트의 메모리 누수의 비밀
Chrome DevTools로
JS 메모리 누수(Memory Leak) 디버깅하기
Thank you
교육솔루션팀 Daniel
daniel@grepp.co

More Related Content

PDF
프로그래머스 프론트엔드 아키텍처 변천사: 좋은 개발 경험을 찾아서
PDF
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
PPTX
게임 분산 서버 구조
PDF
Android Chromium Rendering Pipeline
PDF
게임사를 위한 Amazon GameLift 세션 - 이정훈, AWS 솔루션즈 아키텍트
PDF
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
PDF
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
PDF
Introduction to React JS
프로그래머스 프론트엔드 아키텍처 변천사: 좋은 개발 경험을 찾아서
[NDC17] Unreal.js - 자바스크립트로 쉽고 빠른 UE4 개발하기
게임 분산 서버 구조
Android Chromium Rendering Pipeline
게임사를 위한 Amazon GameLift 세션 - 이정훈, AWS 솔루션즈 아키텍트
[오픈소스컨설팅] 스카우터 사용자 가이드 2020
〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3
Introduction to React JS

What's hot (20)

PDF
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
PDF
An Overview of Spinnaker
PDF
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
PDF
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
PPTX
유니티 + Nodejs를 활용한 멀티플레이어 게임 개발하기
PDF
Windows IOCP vs Linux EPOLL Performance Comparison
PDF
Mobile Browser Internal (Blink Rendering Engine)
PDF
reference_guide_Kernel_Crash_Dump_Analysis
PDF
웨일브라우저 성능 및 메모리 최적화
PDF
Deep Dive async/await in Unity with UniTask(EN)
PDF
게임 서버 성능 분석하기
PDF
Puppeteer can automate that! - Frontmania
PDF
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
PPTX
d.ts 만들기
PDF
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
PPTX
Jenkins Pipeline Tutorial | Jenkins Build And Delivery Pipeline | Jenkins Tut...
PPTX
Leveraging Nexus Repository Manager at the Heart of DevOps
PDF
혼자서 만드는 MMO게임 서버
PPTX
Azure로 MMO게임 서비스하기
PDF
[KubeCon EU 2020] containerd Deep Dive
AWS 클라우드 기반 게임 아키텍처 사례 - AWS Summit Seoul 2017
An Overview of Spinnaker
[야생의 땅: 듀랑고] 서버 아키텍처 - SPOF 없는 분산 MMORPG 서버
카카오 광고 플랫폼 MSA 적용 사례 및 API Gateway와 인증 구현에 대한 소개
유니티 + Nodejs를 활용한 멀티플레이어 게임 개발하기
Windows IOCP vs Linux EPOLL Performance Comparison
Mobile Browser Internal (Blink Rendering Engine)
reference_guide_Kernel_Crash_Dump_Analysis
웨일브라우저 성능 및 메모리 최적화
Deep Dive async/await in Unity with UniTask(EN)
게임 서버 성능 분석하기
Puppeteer can automate that! - Frontmania
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
d.ts 만들기
Node.js Express Tutorial | Node.js Tutorial For Beginners | Node.js + Expres...
Jenkins Pipeline Tutorial | Jenkins Build And Delivery Pipeline | Jenkins Tut...
Leveraging Nexus Repository Manager at the Heart of DevOps
혼자서 만드는 MMO게임 서버
Azure로 MMO게임 서비스하기
[KubeCon EU 2020] containerd Deep Dive
Ad

Similar to Chrome DevTools로 JS 메모리릭 디버깅하기.pptx (8)

PDF
우리가 몰랐던 크롬 개발자 도구
PDF
JavaScript Memory Profiling
PPTX
Chrome Devtools
PPTX
Mem shrink
PDF
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
PPTX
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
PDF
현실적 PWA
PDF
크롬 개발자 도구 소개 및 사용법
우리가 몰랐던 크롬 개발자 도구
JavaScript Memory Profiling
Chrome Devtools
Mem shrink
프론트엔드 개발자를 위한 크롬 렌더링 성능인자 이해하기
[NDC 2018] 신입 개발자가 알아야 할 윈도우 메모리릭 디버깅
현실적 PWA
크롬 개발자 도구 소개 및 사용법
Ad

Chrome DevTools로 JS 메모리릭 디버깅하기.pptx

  • 1. Chrome DevTools로 JS 메모리 누수(Memory Leak) 디버깅하기 교육솔루션팀 Daniel daniel@grepp.co
  • 2. 세션에서 다루는 내용 메모리 이슈의 3가지 증상 메모리 관련 Chrome DevTools 기능 라이브 클래스룸 메모리릭 디버깅 / 해결 과정
  • 4. 발생한 문제점 4 “브라우저에서 이 페이지가 메모리 많이 먹는다고 경고해요” “이거 왜 안나가지죠?” “새로고침해도 한참 기다려야 새 페이지가 로드 돼요” “저만 멈췄나요?” 음.. 왜 그럴까요? ㅎㅎ..
  • 5. 발생한 문제점 5 메모리 문제가 있는게 아닐까?!
  • 6. 발생한 문제점 6 메모리 디버깅 해본 적 없음
  • 7. 발생한 문제점 7 메모리 이슈를 디버깅하면서 배운 내용과 해결 과정을 압축해서 공유해드립니다.
  • 9. 메모리 이슈의 3가지 증상 9 1. 페이지가 시간이 지남에 따라 느려진다 시간이 지남에 따라 느리다고 느껴지는 경우 메모리 누수, 즉 메모리릭(Memory Leak)이 발생한다고 볼 수 있다. 2. 페이지가 일관되게 느리다 페이지가 처음부터 느리다고 느껴진다면, 이는 Memory bloat으로 볼 수 있다. 기본적으로 필요한 메모리보다 더 많은 메모리를 사용하는 것을 말한다. 3. 페이지가 뚝 뚝 끊긴다 가비지 콜렉션(Garbage Collection)이 너무 자주 일어날 때 발생한다. GC가 돌면 모든 JS 스크립트의 실행이 중지되기 때문에 이 경우 잦은 GC를 의심해볼 수 있다.
  • 10. 메모리 이슈의 3가지 증상 1 0 1. 페이지가 시간이 지남에 따라 느려진다 시간이 지남에 따라 느리다고 느껴지는 경우 메모리 누수, 즉 메모리릭(Memory Leak)이 발생한다고 볼 수 있다. 라이브 클래스룸은 1번 증상이었고 메모리릭이 문제일 것으로 예상하고 접근함.
  • 11. 메모리 이슈의 3가지 증상 1 1 그래서 뭐가 문제가 되는지 어떻게 알 수 있는데?
  • 12. 메모리 관련 Chrome DevTools 기능 Task Manager
  • 13. 메모리 관련 Chrome DevTools 기능 – Task Manager 1 3 Chrome 우측 상단 메뉴 > More Tools > Task Manager Task Manager는 열린 페이지의 실시간 메모리 사용량을 모니터링할 수 있는 도구이다. 중요한 곳은 Memory Footprint와 Javascript Memory 컬럼이다.
  • 14. 메모리 관련 Chrome DevTools 기능 – Task Manager 1 4 • Memory Footprint : native memory 사용량을 보여준다. DOM 노드는 네이티브 메모리에 저장되는데, 만약 이 컬럼 값이 증가한다면 DOM 노드가 증가한다는 의미다. • Javascript Memory : JS Heap 사용량을 보여준다. `()`로 감싸진 부분은 live number로 현재 페이지에서 접근 가능한 객체들이 사용중인 메모리를 뜻한다. 이 부분이 증가한다는 것은 객체가 새로 생성되거나, 이미 존재한 객체가 더 커진 걸 의미한다.
  • 15. 1 5 Task Manager 띄워보고 카메라 영역을 페이지네이션 한 결과… 메모리 관련 Chrome DevTools 기능 – Task Manager
  • 16. 메모리 관련 Chrome DevTools 기능 – Task Manager 1 6 초기 상태 여러번 페이지네이션 후 56MB 증가 93,000K증가 일단 페이지네이션하면 메모리릭이 발생하는 것은 파악했는데, 좀 더 자세히 알아볼 수 없을까?
  • 17. 메모리 관련 Chrome DevTools 기능 Performance Profile
  • 18. 메모리 관련 Chrome DevTools 기능 – Performance Profile 1 8 Chrome DevTools > Performance > Memory 체크박스 선택(활성화) > Record Performance profile을 수행하면 시간에 따른 메모리 사용량을 각 항목별(JS Heap, Documents, Nodes, Listeners)로 그려준다.
  • 19. 메모리 관련 Chrome DevTools 기능 – Performance Profile 1 9 • 모든 항목에 대해서 그래프가 계단식으로 그려진 것을 확인했다. • JS Heap에서 메모리릭이 발생하고 있고, 할당된 Listeners가 해제되지 않고 있다. 그리고 Documents, Nodes 가 쌓여간다. 페이지네이션 10회 시도 후 GC 시킨 과정을 기록한 performance profile
  • 20. 메모리 관련 Chrome DevTools 기능 Memory Allocation Timeline
  • 21. 메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2 1 Chrome DevTools > Memory > Profiles > Allocation instrumentation on timeline Allocation Timeline은 시간에 따른 메모리 할당/해제를 막대 차트로 시각화해서 보여준다. 메모리 할당은 파란색 막대로, 메모리 해제는 회색 막대로 나타낸다.
  • 22. 메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2 2 • 페이지네이션 할 때마다 파란색 막대가 생성되는 것을 확인했다. 회색 막대는 거의 보이지 않는다. • 0~5초 사이에 파란 막대를 선택해보고 Retained Size 기준으로 내림차순 정렬하니 AnimationItem 생성자가 system 다음으로 가장 많은 메모리 차지한다. 해당 생성자는 lottie에서 호출하고 있다. 페이지네이션 10회 시도 후 GC 시킨 과정을 기록한 Allocation Timeline
  • 23. 메모리 관련 Chrome DevTools 기능 – Memory Allocation Timeline 2 3 • 페이지네이션으로 인해 변경되는 컴포넌트를 살펴보니, 내부에서 Lottie.vue 를 사용하고 있었다. • 해당 컴포넌트가 mount되면 lottie.loadAnimation() 함수를 호출해 애니메이션 인스턴스(AnimationItem)를 생성하고 ref에 저장하고 있었다. • 그래서 해당 인스턴스를 unmount시에 destoy하는 로직을 추가했다. 결과는? Lottie.vue 파일 내 setup 부분
  • 24. 메모리 관련 Chrome DevTools 기능 – Lottie.vue 수정 후 Performance Profile 2 4 • Lottie.vue 파일 수정 후 performance profile 측정한 결과 GC가 돌때마다 JS Heap이 뚝 뚝 떨어지는 것을 확인했다! • Documents, Nodes, Listeners는 여전히 계단식을 띔. • 할당 후 해제하지 않은 Listeners가 있는지 먼저 살펴보자! Lottie.vue 파일 수정 후 측정한 performance profile
  • 25. 메모리 관련 Chrome DevTools 기능 – Listeners 디버깅 2 5 RepeatableLottie.vue 파일 setup 부분 • 컴포넌트들을 살펴보니 Lottie.vue를 wrapping한 RepeatableLottie.vue 컴포넌트를 사용하고 있었다. • 해당 컴포넌트는 Lottie 애니메이션이 다음번 실행될 여부(playbackEnqueued)를 저장해뒀다가 애니메이션이 종료(complete)되었을 때 애니메이션을 다시 실행하도록 하기 위해 만들어진 것으로 보였다. • 14번 라인에 ‘complete’ 이벤트 리스너를 추가하고 있지만 해제하는 라인은 보이지 않는다. • 이벤트 리스너를 해제하는 로직을 추가하기로 했다. 또 로직을 좀 더 간단히 수정하기로 했다.
  • 26. 2 6 RepeatableLottie.vue를 대체한 ClapAnimation.vue 컴포넌트 setup 부분 • `v-if` directive를 사용하여 필요한 경우에만 lottie를 렌더링하도록 하고, unmount 할 때 complete 이벤트 리스너를 제거하도록 수정해보았다. • 결과는? 메모리 관련 Chrome DevTools 기능 – Listeners 디버깅
  • 27. 메모리 관련 Chrome DevTools 기능 – Lottie.vue 수정 후 Performance Profile 2 7 • RepeatableLottie.vue를 교체하고 이벤트 리스너를 제거해준 뒤 performance profile 측정한 결과 GC가 돌때 listeners가 감소했다! • Documents, Nodes는 여전히 계단식을 띈다. Detached DOM이 있는지 살펴봐야 한다. 이벤트 리스너 제거 후 측정한 performance profile
  • 28. 메모리 관련 Chrome DevTools 기능 – Detached DOM 2 8 Detached DOM: DOM tree에서 제거되었지만 JS에 의해 여전히 reference 되고 있는 element
  • 29. 메모리 관련 Chrome DevTools 기능 – Detached DOM 2 9
  • 30. 메모리 관련 Chrome DevTools 기능 Memory Heap Snapshots
  • 31. 3 1 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots Chrome DevTools > Memory > Profiles > Heap Snapshot Heap Snapshot은 특정 순간의 JS 오브젝트와 DOM 노드 사이의 메모리 distribution을 보여준다. 이를 활용해서 Detached DOM을 찾아낼 수 있다.
  • 32. 3 2 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots • 첫 번째 스냅샷은 Major GC후 초기 메모리 상태를 기록한 스냅샷 • 두 번째 스냅샷은 페이지 전환 10회 시도 후 메모리 스냅샷이다. • 첫 번째 스냅샷과 두 번째 스냅샷에서 detached 키워드로 필터링한 결과를 비교하면, detached DOM들의 retained size가 일제히 증가한 것을 확인됨. • 대부분의 detached DOM들이 SVG 관련 element 들로 확인됨. 초기 상태 힙 스냅샷 페이지네이션 10회 시도 후 GC 한 스냅샷
  • 33. 3 3 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots SvgIcon.vue 컴포넌트를 사용하는 LiveClassProfile 컴포넌트 SvgIcon.vue • SVG 관련 컴포넌트를 살펴보니 프로필 컴포넌트 내부에서 <SvgIcon /> 컴포넌트를 사용하고 있었음 • <SvgIcon /> 컴포넌트는 svg definition을 불러와 image sprite 기법으로 svg를 사용하는 컴포넌트 • 이 컴포넌트를 제거하고 힙 스냅샷을 찍어보면?
  • 34. 3 4 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots • 대부분의 detached SVG element가 제거된 것을 확인! SvgIcon 컴포넌트 제거 후 페이지네이션 시도한 뒤 기록한 Heap Snapshot
  • 35. 3 5 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots SvgIcon
  • 36. 3 6 메모리 관련 Chrome DevTools 기능 – Memory Heap Snapshots • <SvgIcon /> 컴포넌트를 별도의 inline svg 컴포넌트로 교체 후 스냅샷 기록한 결과 detached DOM들이 다시 생기긴 했지만, 초기 상태와 거의 유사한 수준 • Svg를 아예 없앨 수도 있지만(img 태그 활용해서), CSS로 svg의 색상을 변경하기위해 어쩔 수 없이 이 방식을 채택 SvgIcon 컴포넌트를 inline svg 컴포넌트로 교체 후 기록한 Heap Snapshot
  • 37. 메모리릭 디버깅 전/후 개선 결과 비교
  • 38. 3 8 메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교 개선 전 개선 후 스냅샷 1 스냅샷 2 델타 124MB 169MB +45MB 스냅샷 1 스냅샷 2 델타 127MB 118MB -9MB
  • 39. 3 9 메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Allocation Timeline) Memory Allocation +31MB Memory Allocation +990KB 개선 전 개선 후
  • 40. 4 0 메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Performance Profile) 개선 전 개선 후 항목 First GC 페이지네이션 & Second GC 델타 JS Heap 112MB 132MB +20MB Documents 4개 14개 +10개 Nodes 3307개 17243개 +13936개 Listeners 459개 499개 +40개 항목 First GC 페이지네이션 & Second GC 델타 JS Heap 94MB 91MB -3MB(-100%) Documents 5개 5개 +0개(-100%) Nodes 4507개 5041개 +534개(-96%) Listeners 473개 473개 +0개(-100%)
  • 41. 4 1 메모리 관련 Chrome DevTools 기능 – 디버깅 전/후 개선 결과 비교(Allocation Timeline) 아직 개선의 여지가 남아있습니다. 그렇지만, 당장 급한 불은 껐습니다.
  • 42. 정리 및 내가 배운 내용
  • 43. 정리 4 3 1. Lottie 애니메이션 인스턴스가 unmount시에 destroy 되도록 수정 2. Lottie 애니메이션 인스턴스에 추가한 이벤트 리스너가 unmount시에 remove 되도록 수정 3. <SvgIcon /> 컴포넌트를 별도 svg 컴포넌트로 교체
  • 44. 내가 배운 내용 4 4 1. 메모리릭이 의심되면 Task Manager로 메모리를 모니터링 해보자 2. 큰 그림을 보려면 Chrome Performance Profile을 활용하자 3. JS Heap 메모리릭은 Memory Allocation Timeline으로 진단할 수 있다 4. Detached DOM은 2개 이상의 Heap Snapshot을 찍어서 비교하면 진단할 수 있다
  • 45. References 4 5 • Chrome Developers - Record heap snapshots • Chrome Developers - Memory terminology • 자바스크립트에서 메모리 누수의 4가지 형태 • Vue 컴포넌트 - 메모리 누수 분석하기 • Finding and debugging memory leaks in JavaScript with Chrome DevTools • Vue cookbook - Avoiding Memory Leaks • Toast UI - 당신이 모르는 자바스크립트의 메모리 누수의 비밀
  • 46. Chrome DevTools로 JS 메모리 누수(Memory Leak) 디버깅하기 Thank you 교육솔루션팀 Daniel daniel@grepp.co