---
# System prepended metadata

title: 웹 애플리케이션의 성능을 200% 끌어올리기 위한 코드 점검 및 개선 방법
tags: [강의, 냥하]

---

# 웹 애플리케이션의 성능을 200% 끌어올리기 위한 코드 점검 및 개선 방법

###### tags: `냥하` `강의`

## 프론트엔드 성능
### 코드 바깥의 성능
:시간과 리소스 :clock1: :inbox_tray: 
    - 시간: 초기 구동시간(파일 다운로드, 컨텐츠 렌더링, 인터랙션 가능), 계산 시간, 반응 시간
    - 리소스: 자원 소모(CPU점유율, 메모리 스토리지, 네트워크 트래픽)



1. 시간
    - 파일 다운로드:
        1. (HTTP/1.1 기준) 최신 브라우저는 대체로 도메인 당 6개까지만 동시 처리
            - 이미지, 동영상은 느린 업로드에 익숙하지만. 레이아웃이나 css가 느려지면 안좋게 보임
            - 별도 도메인이나 CDN등으로 분산하는 것도 방법 
        2. 이미지는 최신 포멧 사용시 용량 절약
            - WebP는 JPEG 파일의 평균 약 70% 정도 크기
            - 레진 기술 블로그 참고
            - ![image](https://user-images.githubusercontent.com/48500209/160038739-b2560c11-6ce4-47e6-9120-80d02180886a.png)
        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를 기준으로 한다.

애니메이션 성능을 위해서는 가능하면 메인쓰레드에서 사용되는 것을 줄이고 컴포지터 쓰레드에서 진행될 수 있도록 한다.
![image](https://user-images.githubusercontent.com/48500209/160325768-0b3744b4-eb0f-4657-9cb9-d185f768bb61.png)

*고성능 애니메이션을 위한 몇 가지 팁
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 접근
    ![image](https://user-images.githubusercontent.com/48500209/160347914-78671219-bc5c-4590-a7b8-440810b3499d.png)
    
    - after:: fragment만들어서 접근 -> fragment를 씌워서 추가해도 이 전 엘리먼트에 바로 추가됨.GOOD (cf, React fragment)
    ![image](https://user-images.githubusercontent.com/48500209/160348260-9e2f3723-a653-4242-92a8-2288dd789faf.png)

    



## 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)가 될 수 있다.
    - 브라우저가 데이터의 변화가 없는데도 또 불러오는 일이 없도록 하자.
    - ![image](https://user-images.githubusercontent.com/48500209/160354793-86cf50e0-49d0-4e1a-b182-eb1119aef82f.png)
4. 이미지나 미디어는 필요할 때 불러오는 lazy loading을 활용하자


## 요약
1. 브라우저가 읽어들일 용량을 줄여야한다 
    - 캐시, 게으른 로딩
2. JS 코드 실행이 느리면 로직 개선 및 최적화 기법을 도입해 볼 수 있다.
    - 게으른 계산, 메모이제이션
3. 자바스크립트도 멀티 스레드 프로그래밍이 가능하다.
    - 웹 워커
4. 사용자의 행동에는 100ms안에 반응을 보여야한다.
5. 애니메이션 성능의 기준은 60fps이다.
6. 너무 모든 걸 다 적용하려고 집착할 필요는 없다.