# 웹 애플리케이션의 성능을 200% 끌어올리기 위한 코드 점검 및 개선 방법
###### tags: `냥하` `강의`
## 프론트엔드 성능
### 코드 바깥의 성능
:시간과 리소스 :clock1: :inbox_tray:
- 시간: 초기 구동시간(파일 다운로드, 컨텐츠 렌더링, 인터랙션 가능), 계산 시간, 반응 시간
- 리소스: 자원 소모(CPU점유율, 메모리 스토리지, 네트워크 트래픽)
1. 시간
- 파일 다운로드:
1. (HTTP/1.1 기준) 최신 브라우저는 대체로 도메인 당 6개까지만 동시 처리
- 이미지, 동영상은 느린 업로드에 익숙하지만. 레이아웃이나 css가 느려지면 안좋게 보임
- 별도 도메인이나 CDN등으로 분산하는 것도 방법
2. 이미지는 최신 포멧 사용시 용량 절약
- WebP는 JPEG 파일의 평균 약 70% 정도 크기
- 레진 기술 블로그 참고
- 
3. 화면 크기와 해상도에 따라 적절한 이미지 로딩
4. 웹 폰트 최적화
- 구글 폰트
- WOFF2는 WOFF, TTF에 비해 30% 용량이 작다.
- 필요한 글자만 골라서 글꼴을 만들 수도 있다.
5. 화면 크기 등에 따라 필요한 스타일 시트만 로딩
6. `Link` 태그만으로도 접속 시간 절약
```
link rel="dns-prefetch"
link rel="preconnect"
link rel="prefetch"
```
- 컨텐츠 렌더링, 인터랙션 가능
: 점진적으로 로딩되는 사이트가 훨씬 좋은 UX로 느껴짐
1. 로딩 속도 개선
- 필수 컨텐츠가 아니라면 비동기 로딩을 고려해보자(광고, 댓글, 헤더/푸더 등)
- SPA는 덩치가 넘 크니까 비동기로 불러오는 경우가 좋다.
- 이미지/아이프레임/스크립트 등은 필요할 때까지는 읽지 않는 게으른 로딩(Lazy loading) 기법을 고려해보자
```
<img src="" loading="lazy">
```
- 서버에서 불러올 때, 시간이 많이 걸린다면 플레이스 홀더 등으로 대체(로딩이 되고 있는 자리를 표시)
- 계산 시간: 웹 워커, 느긋한 계산, 메모이제이션(계산 결과를 기억해두고 반복사용)
- 1. 웹 워커: JS는 싱글 스레드이다. 하지만 멀티 스레드는 가능하다. HTML5의 워커 스레드
- 워커 스레드
- UI를 조작할 수 없다
- 워커 스레드 전용으로 분리된 파일이 필요하다
- postMessage()로 데이터를 전송하고, onmessage이벤트를 통해 받는 방식으로 통신한다.
- 2. 느긋한 계산
- 3. 메모이제이션(계산 결과를 기억해두고 반복사용)
- ex. 피보나치 계산, 순수함수임 항상 같은 값이 나오므로 기억해두고 사용하기 용이함
### 애니메이션 성능
: 지나치게 느린 애니메이션 및 응답 속도는 사용자 경험을 저해한다.
#### 반응 시간
1. 도허티 임계
2. 사용자는 UI가 100ms 이하로 반응해야 자신이 UI를 다루고있다고 느낀다.
3. 애니메이션은 60FPS를 기준으로 한다.
애니메이션 성능을 위해서는 가능하면 메인쓰레드에서 사용되는 것을 줄이고 컴포지터 쓰레드에서 진행될 수 있도록 한다.

*고성능 애니메이션을 위한 몇 가지 팁
1. 가능하면 JS보다는 CSS 애니메이션을 최대한 활용
2. 다음 CSS 속성위주로 애니메이션:: GPU 가속 적용(`transform`, `opacity`는 GPU가속이 자동 적용됨)
```
transform: translate or scale or rotate
opacity
```
3. 레이아웃 변경이나 리페인팅을 유발하는 CSS 속성은 비용이 많이 든다.
- 레이아웃: width, height, padding, margin, display 등
- 페인트: color, background, outline, box-shadow 등
4. setTimeout보다는 requestAnivationFrame, Web Animations API 등 활용
- requestAnimationFrame: 브라우저가 최적화. 비활성 탭에서는 동작 안함
- Web Animations API: CSS애니메이션과 같은 애니메이션 엔진 사용
5. three.js, velocity.js와 같은 고성능 애니메이션 라이브러리 사용
6. will-change 속성(css속성)을 통해 브라우저가 최적화 할 속성 명시
- 남용하면 리소스 낭비, MDN에서는 최후의 수단으로 사용하라고 권고함
7. DOM 접근과 업데이트는 가능한 적게, 한 번에 몰아서 처리
- 엘리먼트 추가는 DocumentFragment 활용 -> 성능에 좋음
- before:: 그냥 바로 DOM 접근

- after:: fragment만들어서 접근 -> fragment를 씌워서 추가해도 이 전 엘리먼트에 바로 추가됨.GOOD (cf, React fragment)

## Javascript 코드의 성능
: 자원소모, 리소스
리소스: CPU 점유율, 전력 소비량, 스토리지 용량, 메모리 누수, 네트워크 트래픽
사실 스크립트 언어는 자체적으로 관리해주는 것이 많아서 CPU(무한루프만 고려), 전력은 크게 신경 안써도 됨
1. 메모리 누수
: 프로그램이 필요하지 않은 메모리를 계속 점유하는 현상
C, C++ 언어와 달리 JS 엔진이 메모리 필요/불필요를 "추정"하여 해제(GC: Garbage Collection) -> 참조 카운팅 방식 사용
```
// 참조 카운팅: 이 메모리에 있는 값을 몇 개의 변수(함수)가 참조하고있는지를 카운팅
// 값을 참조하고 있는 것이 없다면, 참고하고있는 것을 지움
var person ={ age:20 }; //age변수를 참조함
var other = person;
person = null;
other = null;
```
참고: https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management
- 메모리 생명주기:
- **할당**(:사용할 메모리를 확보) -> **사용**(: 메모리 사용, 읽기, 쓰기) -> **해제**(불필요한 메모리 반환)
### 네트워크 트래픽
: 파일 용량을 줄이거나 필요할 때만 불러와서 트래픽 낭비를 줄인다.
1. 최소화한 JS, CSS 파일 사용
2. 프레임워크는 한 개 이하만 사용
3. 파일 주소의 파라미터는 주의해서 사용
- 의도하지 않은 캐시버스터(cache buster)가 될 수 있다.
- 브라우저가 데이터의 변화가 없는데도 또 불러오는 일이 없도록 하자.
- 
4. 이미지나 미디어는 필요할 때 불러오는 lazy loading을 활용하자
## 요약
1. 브라우저가 읽어들일 용량을 줄여야한다
- 캐시, 게으른 로딩
2. JS 코드 실행이 느리면 로직 개선 및 최적화 기법을 도입해 볼 수 있다.
- 게으른 계산, 메모이제이션
3. 자바스크립트도 멀티 스레드 프로그래밍이 가능하다.
- 웹 워커
4. 사용자의 행동에는 100ms안에 반응을 보여야한다.
5. 애니메이션 성능의 기준은 60fps이다.
6. 너무 모든 걸 다 적용하려고 집착할 필요는 없다.