FE 성능 최적화
패스트캠퍼스 the red를 듣고 정리해보았다.
파일 다운로드
최신 브라우저는 대체로 도메인 당 6개의 접속만 동시에 처리한다(HTTP 프로토콜 /1.1기준)
http2에서는 하나의 연결로 계속 파일을 주고받아서 괜찮다.
하지만 아직은 1.1기준으로 작동하는 사이트가 많다.
한 도메인에서 6개의 파일만 동시에 다운로드 할 수 있다.
6개 이상부터는 큐에 넣어두고 하나씩 다운로드 하게 된다.
이미지와 같은 파일들은 사용자가 기다리는것에 익숙하지만
js나 cs파일들의 다운로드가 느려지면 페이지에 변화가 없고 인터액션이 늦어지게 된다.
개선방안
- 파일 갯수와 용량을 작게한다. 
- 별도 도메인이나 CDN등으로 분산하여 해결할 수 있다. 
- 적절한 포맷을 사용한다. 이미지의 경우 webp파일을 사용하여 크기를 줄일 수 있다. 
 ex) 레진코믹스
| 1 | <!-- 지원 타입에 따라 다른 이미지 로딩 --> | 
- 화면 크기와 해상도에 따라 적절한 이미지 로딩
| 1 | <!-- 화면 크기에 따라 적절한 이미지 로딩 --> | 
- 웹 폰트 최적화
- 구글폰트: 나눔 고딕 등 한국어 폰트 26종 제공
- WOFF2는 WOFF,TTF등에 비해 30% 용량이 작다.
- 필요한 글자만 골라서 글꼴을 만들 수도 있다.(메뉴용 글꼴 등)
- 화면 크기 등에 따라 필요한 스타일 시트만 로딩
- 하지만 실제 이렇게 사용하는 경우는 없다. css는 크기가 작고 파일 개수를 늘리는 것은 좋지 않다.
- 부트스트랩이 차지하는 용량이 20kb쯤
| 1 | <link href="mobile.css" rel="stylesheet" media="all" /> | 
- link 태그 만으로 접속 시간 절약
| 1 | <link rel="dns-prefetch" media="https://taegon.kim" /> | 
Preconnect를 사용할 경우 외부 도메인을 미리 검색하여 소켓을 연결해둔다. 서드파티 자원 연결에 적합하다.
Prefetch를 사용할 경우 외부 도메인을 미리 검색하여 소켓을 연결 후 다운로드까지 해둔다.
하지만 남용하면 안되고 꼭 필요하거나 다음 경로가 명확하게 예상이 될 경우에만 사용해야 한다.
로딩 속도 개선
- 필수 컨텐츠가 아니라면 비동기 로딩을 고려해보자(광고,댓글,헤더/푸터 등) 
- 이미지/아이프레임/스크립트 등은 필요할 때까지는 읽지 않는 게으른 로딩(lazy loading)기법을 고려해보자. 코드를 분할한 후 필요할 때 읽어오는 방식이다. 웹팩에서 자동으로 해주기도 한다. 
| 1 | <img src="image.jpg" loading="lazy" /> | 
- 시간이 많이 걸린다면 플레이스 홀더 등으로 대체한다.
-스켈레톤 ui
계산 시간
- 웹 워커
자바스크립트는 싱글스레드이다. 하지만 워커스레드를 이용하여 멀티스레드가 가능하다.
워커스레드
- UI를 조작할 수 없다.
- 워커 스레드 전용으로 분리된 파일이 필요하다.
- postMessage()로 데이터를 전송하고, onMessage 이벤트를 통해 받는 방식으로 통신한다.
- 느긋한 계산
값이 필요해질 때 까지 계산을 미뤄두는 기법이다.
게으른 평가, 지연 평가라고도 한다.
- 메모이제이션
계산 결과를 기억해두고 반복 사용하는 기법.
루프, 재귀 호출 등 최적화.
반응시간
지나치게 느린 애니메이션 및 응답 속도는 사용자 경험을 저해한다.
- 시스템의응답이 40ms보다 느리면 주의력 분산이 발생함
- ui가 100ms 이하로 반응해야 ui를 다루고 있다고 느낀다.
- 애니메이션은 60fps를 기준으로 한다.
애니메이션의 렌더링 순서
js-> 스타일-> 레이아웃 ->페인트 -> 합성
페인트까지는 메인스레드에서 진행한다. 합성만 컴포지터 스레드에서 진행한다.
메인스레드는 자바스크립트가 동작하기 때문에 메인스레드의 작업이 많아지면 자바스크립트의 속도도 느려진다.
개선 방법
메인스레드에서 이루어지는 과정은 가능한 한 피하고 컴포지터 스레드에서 일어나도록 하면 된다.
즉 레이아웃이나 페인트는 피하고 합성단계를 유발하는 css 속성들을 주로 사용한다.
각 단계의 동작을 유발하는 css 속성은 https://csstriggers.com/에서 확인할 수 있다.
정리
- 가능하면 js보다는 css 애니메이션을 최대한 활용한다.
- 다음 css 속성 위주로 애니메이션 -gpu 가속을 적용한다.(자동으로 적용된다.)
- transform:translate or scale or rotate
- opacity
- 레이아웃 변경이나 리페인팅을 유발하는 css 속성은 비용이 많이 든다.
- 레이아웃 : width,height,padding, margin,display
- 페인트 : color,background,outline,box-shadow
- setTimeOut 보다는 requestAnimationFrame, Web Animations API 등 활용
- requestAnimationFrame: 브라우저가 최적화, 비활성 탭에서는 동작 안 함
- web Animation API: css애니메이션과 같은 애니메이션 엔진 사용
- three.js velocity.js와 같은 고성능 애니메이션 라이브러리 사용 
- will-change 속성을 통해 브라우저가 최적화 할 속성 명시 
- 남용하면 리소스 낭비,
- DOM 접근과 업데이트는 가능한 적게, 한 번에 몰아서 처리,
- 엘리먼트 추가는 DocumentFragment 활용
| 1 | const app = document.getElementById("app"); | 
리소스
cpu 점유율, 전력 소비량, 스토리지, 메모리 사용량, 네트워크 트래픽 중 메모리 누수와 네트워크 트래픽을 신경써야 한다.
메모리 누수
프로그램이 필요하지 않는 메모리를 계속 점유하는 현상
메모리 생명 주기
- 할당 : 사용할 메모리를 확보한다.
- 사용 : 메모리를 사용한다.
- 헤재 : 불필요한 메모리를 반환한다.
개선 방법
js는 가비지 컬렉션을 통해 메모리를 해제한다.
이 메모리를 몇개의 변수가 참조하는지 카운트하여 0개일 경우 지운다.
| 1 | var x = { | 
순환참조 문제
객체끼리 참조가 맞물려서 가비지 컬렉션이 동작하지 않는 문제
마크스위프 알고리즘을 통해 해결할 수 있게 되었다.
메모리 누수의 대표적 예시
| 1 | // case 1 : 큰 전역 변수는 계속 메모리에 존재한다. | 
개선방안
아래의 코드는 예시일 뿐이다.
실제로는 모듈이나 다른 함수로 분리해서 사용하는 것이 좋다.
| 1 | // case 1 : 큰 전역 변수는 계속 메모리에 존재한다. | 
네트워크 트래픽
파일 용량을 줄이거나 필요할 때만 불러와서 트래픽 낭비를 줄인다.
- 최소화된 js,css파일을 사용한다.
- 프레임워크는 한 개 이하만 사용한다.
- 파일 주소의 파라미터는 주의해서 사용, 의도하지 않은 캐시버스터가 될 수 있다.
- 브라우저는 전체 url 기반으로 캐시하기 때문에 업데이트가 되어도 받아오지 못할 수 있다.
- 일부러 랜덤한 숫자를 붙여 새로 캐시되도록 하는 것이 캐시버스터이다.
- 이미지, 미디어는 필요할 때 불러오는 게으른 로딩(lazy loading)기법을 사용한다.



















