2023. 10. 9. 17:42ㆍIT용어 아는척 하기
프론트엔드의 성능 최적화
사용자가 필요한 UI를 지연과 불편함 없이 제공할 수 있는가가 프론트엔드의 성능을 점검하는 주요 목적이다.
기술적 영역에서의 프론트엔드 성능 최적화는 두 가지 영역으로 나눠 볼 수 있다.
- 로딩 성능
- 파일크기를 최소화 혹은 최적화 해야 함, (특히 이미지와 글꼴!)
- 컴포넌트, 이미지 등의 지연로딩과 사전로딩을 적절히 활용해야 함
- minifi를 통해 번들크기 최소화. (대부분의 번들러가 production 상태에서 제공함)
- 캐시를 활용해야 함, 서버에서 설정함. e.g cache-control header 활성화
- 서버에서 텍스트 압축을 활성화 해야 함. e.g. gzip 활성화
- 렌더링 성능
- 최근의 보편적인 화면주사율(화면갱신의 단위, 모니터에 따라 다름)인 60FPS 안에 화면 처리가 완료 되어야 안전함
- reflow와 repaint를 발생시키는 element의 크기, 넓이 그리고 위치의 변경은 최소화 해야 함
이어지는 내용들은 리액트 중심으로 정리함, 다른 라이브러리나 프레임워크에서도 비슷한 기능들을 제공하므로 큰 차이는 없음 또한 일반적인 JS에서도 사용가능한 기능들도 포함되어 있음
코드 분할
webpack-bundle-analyzer 와 같은 자바스크립트 번들 크기 분석도구를 이용해 최초화면에서 사용하지 않는 모듈 중 용량이 큰 모듈을 식별하고 이를 사용하는 컴포넌트나 페이지를 분할해서 번들 크기를 줄이는 것이 필요함
자체 번들 사이즈 줄이기
적절하게 번들을 잘 분할 했다면 번들 자체의 사이즈를 줄이는 것도 시도해 봐야한다. 사용하지 않는 모듈들에 대한 import를 줄이고 필요 없는 코드는 삭제 해야한다. https://bundlephobia.com/ 나 VS Code의 import cost 플러그인을 활용하여 사용한 라이브러리의 번들 사이즈를 확인하고 더 효율적인 사이즈의 라이브러리 교체 등을 고민해 봐야합니다.
React Server Component
번들크기 줄이는데 활용 가능, 동일한 api를 컴포넌트 트리에서 여러분 부르게 되는 api waterfall 현상을 막아줌
컴포넌트 및 모듈 지연로딩
컴포넌트 분할이 적용되면 동적로딩을 이용해 분할된 컴포넌트를 최초화면 로딩 이후 필요시 로드해서 사용해야 함.
동적로딩은 promise 기반으로 작성되어있고 react에서 제공하는 lazy와 suspense를 이용해 손쉽게 구현이 가능함,
지연로딩은 페이지 기반으로 구현하는 게 가장 손쉬우며, 컴포넌트나 모듈 단위로 적용하는 것도 가능함
컴포넌트 및 모듈 사전로딩
지연로딩이 적용되어 있을 경우, 최초로딩 후 해당 컴포넌트나 모듈을 필요시 로드하는 시간이 소요되므로 js 로드에 따른 불필요한 UI 지연을 막기 위해 사전로딩을 적용해서 보완할 필요성이 있음
- 분할된 번들의 크기가 충분히 작아서 번들로드에 소요시간이 짧을 경우, 특정 이벤트 발생을 예측하고 사전로딩을 적용하면 효율적임.
- 버튼의 마우스 오버의 경우, 높은 확률로 마우스 클릭을 예측할 수 있으므로 마우스 오버 이벤트 발생시 마우스 클릭시 호출할 컴포넌트를 미리 호드하는 것이 효율적인 방안.
- 분할된 번들의 크기가 클 경우, 최초 화면 로드 후에 해당 번들을 로드하는 것이 좋음
- react의 경우 useEffect를 사용해서 최초로드 후에 동적로드 되도록 구현 가능
이미지 크기 최적화
네트워크로 로드되는 실제 이미지 크기가 디스플레이되는 이미지 크기보다 과도하게 클 경우 이미지 크기 조절 필요
- 이미지 크기를 직접 줄이는 방법, 프론트엔드 번들에 포함되는 이미지라면 상황에 맞는 이미지로 크기나 확장자를 최적화 함.
- CDN을 활용하는 방법, CDN이 콘텐츠 전진배치를 통해 네트워크 속도도 향상시키지만 파일확장자나 이미지 크기를 조절하는 용도로 사용이 가능함.
- 서버를 직접 사용해야 하는 경우, 서버에서 파일 확장자나 크기를 요청에 따라 변환해 줄 수 있는 기능을 서버에 추가 해야 함
비트맵 이미지의 경우, 압축률이 뛰어난 WebP 방식을 사용하는 것을 권장함.
브라우저에서 WebP 확장자를 지원하지 않은 경우를 대비해서 (하방지원 필요시) jpg 확장자의 이미지를 로드할 수 있도록 화면을 구현해서 브라우저 하방호환성을 지킬 필요가 있음
이미지 지연로딩
프론트엔드에서 이미지는 네트워크 자원을 가장 많이 소모하는 요소이다. 때문에 이미지의 크기가 화면의 성능에 영향을 줄 경우, 사용자가 인식하는 범위의 이미지를 먼저 로드하고 그 외의 이미지들의 불러오기는 지연시켜 네트워크 자원을 효율적으로 사용해야 한다. 단, UI요소는 지연로딩의 대상으로 삼지 않는 것이 일반적이다.
web API인 intersection Observer 사용을 권장하며, 브라우저 버전이 낮아서 intersection Observer 를 사용하지 못할 경우에는 뷰포트와 객체의 위치를 검토해서 지연로딩을 구현하는 방식을 채택해야 함
이미지 사전로딩
컴포넌트 지연로딩을 적용했을 때 (특히 모듈단위로 적용시) 컴포넌트 로드 전 UI용 이미지는 사전로딩을 통해 먼저 불러온 뒤 컴포넌트를 활성화 해야 UI에 어색함이 발생하지 않음 e.g. 모달창의 닫기 버튼이 모달창이 뜬 뒤에 나타나는 현상 방지
폰트 최적화
폰트의 로드 시점 관련
폰트가 로드되기 전까지 텍스트를 보여줄 지 여부에 따라 FOUT(flash of unstyled text) 방식과 FOIT(flash of invisible text) 방식으로 구분됨. 엣지 브라우저는 FOUT, 크롬은 FOIT이나 3초안에 로드되지 않으면 FOUT를 따름. 중요한 문자열은 FOUT 방식을 따르는 것이 사용자 경험에 좋을 수 있음. @font-face 의 font-display 속성으로 조절이 가능함
폰트의 파일 크기 관련
- WOFF2, WOFF, TTF 의 순으로 용량이 커지므로 웹폰트를 사용하는 것이 효율적임, 단 브라우저의 종류와 버전에 따라 지원여부가 달라지므로 @font-face 의 src 속성을 이용해서 확장자 사용여부에 따라 적용될 수 있도록 구현 필요
- 특정 문자열에만 사용하는 폰트의 경우 서브셋으로 폰트를 추출해서 용량을 줄일 수 있음
CSS 애니메이션 최적화
크롬 개발자 도구의 performance 등을 이용해서 화면의 갱신주기 안에 애니메이션이 정상적으로 완료 되는지 확인해야 함. 렌더링 비용이 비싼 reflow나 repaint가 과도하게 발생해서 애니메이션이 지연되고 있다면, reflow나 repaint 를 발생시키지 않는 transform 이나 opacity 속성을 이용해서 애니메이션을 구현하는 것을 검토해 해야 함
CSS 최적화
불필요한 CSS 가 있는지 확인하고 제거해야 함. 사용하지 않는 CSS의 경우, purgeCSS와 같은 분석도구를 이용해서 제거할 수 있음. 중복된 CSS도 확인 후 제거해야 함
캐시
캐시관리는 서버에서 제공하는 응답 헤더의 cach-control을 통해 관리해야 함, 아래와 같이 관리하는 것이 일반적이며, 프로젝트 상황에 맞게 변경해서 사용해야 함
- html => no-cache
- js, css, image => public, max-age 1년
- 그 외 => no-store
캐시 사용 심화
- 검증 헤더와 조건부 요청
응답해더 : last
• 캐시 유효 시간이 초과해도, 서버의 데이터가 갱신되지 않으면
• 304 Not Modified + 헤더 메타 정보만 응답(바디X)
• 클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신
• 클라이언트는 캐시에 저장되어 있는 데이터 재활용
• 결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드
• 매우 실용적인 해결책
• Cache-Control: max-age
캐시 유효 시간, 초 단위
• Cache-Control: no-cache
데이터는 캐시해도 되지만, 항상 원(origin) 서버에 검증하고 사용
• Cache-Control: no-store
데이터에 민감한 정보가 있으므로 저장하면 안됨
(메모리에서 사용하고 최대한 빨리 삭제)
• 검증 헤더 (Validator)
ETag: "v1.0", ETag: "asid93jkrh2l"
Last-Modified: Thu, 04 Jun 2020 07:19:24 GMT
• 조건부 요청 헤더
If-Match, If-None-Match: ETag 값 사용
If-Modified-Since, If-Unmodified-Since: Last-Modified 값 사용
프록시 캐시 관련 ( CDN )
프록시 서버에 저장되는 캐시를 public, 사용자 개인을 위한 브라우저에 저장되는 캐시를 private로 구분함.
• Cache-Control: public
응답이 public 캐시에 저장되어도 됨
• Cache-Control: private
응답이 해당 사용자만을 위한 것임, private 캐시에 저장해야 함(기본값)
N클라이언트 N서버 문제 - 서비스가 커지면 커질수록 발생할 수 밖에 없음
BFF (Back-end for Front-end)
프론트엔드만을 위한 백엔드 서비스를 만드는 기법 - 클라이언트 중심 메시지 처리 전략
grapql을 활용하여 underfetching과 overfetching 문제까지 해결
Endpoint를 일원화 하고 규격을 통일하여 불필요한 코드를 줄이고 유지보수성을 늘릴 수 있음
CROS문제를 해결하면서 BFF만 퍼블릭 네트워크에 나오면 되기 때문에 보안문제까지 해결 가능
'IT용어 아는척 하기' 카테고리의 다른 글
쿠버네틱스로 가는 발판② - GCP에서 Docker(도커) 활용기 (0) | 2022.06.04 |
---|---|
쿠버네틱스로 가는 발판① - Docker(도커) 기본 개념 (0) | 2022.05.31 |
프로그래밍의 근본, 알고리즘 (feat. 코딩테스트) (0) | 2021.12.27 |
Atomic Design Pattern (feat. React, Vue, Flutter) (0) | 2021.12.26 |
개발자가 이해하는 북극성 지표(North Star Metric) (0) | 2021.12.26 |