준영
도은
13.1 애플리케이션에서 확인하기
13.1.1 create-react-app
// reportWebVitals.ts
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEnty instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
// index.tsx
reportWebVitals();
- reportWebVitals 함수는 웹에서 성능을 측정하기 위한 함수
web-vitals
라이브러리 덕분에 측정- 라이브러리가 브라우저의 웹페이지 성능을 측정할 수 있는 이유는
performanceObserver
라는 API를 사용하기 때문- 웹페이지에서 다양한 성능을 측정할 수 있도록 도와주는 API, 브라우저에서 성능을 측정하기 위해 사용
function sendToAnalytics(metric: ReportHandler) {
const body = JSON.stringify(metric);
const url = '/api/analytics'; // 지표 정보를 보낼 위치
fetch(url, { body, method: 'POST', keepalive: true });
/**
* @NOTE keepalive
* 사용자가 웹 페이지를 닫거나 이동해도 요청이 중단되지 않도록 하고 싶을 때 설정
* 페이지가 종료되는 상황에서도 요청을 완료할 수 있도록 보장
*/
}
reportWebVitals(sendToAnalytics);
function sendToAnalytics({ id, name, value }: ReportHandler) {
ga('send', 'event', {
eventCategory: 'Web Vitals',
eventAction: name,
eventValue: Math.round(name === 'CLS' ? value * 1000 : value), // 정수로 보낸닽
eventLabel: id,
nonInteraction: true,
});
}
reportWebVitals(sendToAnalytics);
13.1.2 create-next-app
import { AppProps, NextWebVitalsMetric } from 'next/app';
export function reportWebVitals(metric: NextWebVitalsMetric) {
console.log(metric);
}
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
위와 같이 예약어로 지정된 함수인 reportWebVitals
를 생성하면 지표를 얻을 수 있다.
Next.js-hydration
: 페이지가 서버 사이드에서 렌더링되어 하이드레이션하는 데 걸린 시간Next.js-route-change-to-render
: 페이지가 경로를 변경한 후 페이지를 렌더링을 시작하는 데 걸리는 시간Next.js-render
: 경로 변경이 완료된 후 페이지를 렌더링하는 데 걸린 시간
13.2 구글 라이트하우스
13.2.1 구글 라이트하우스 - 탐색 모드
- 페이지에 접속했을 때부터 페이지 로딩이 완료될 때까지의 성능을 측정하는 모드
- 페이지를 처음부터 다시 불러와서 페이지 로딩이 끝날 때까지 각각의 지표를 수집
- 수집이 완료되면 리포트 확인 가능
성능
- 핵심 웹 지표인 최초 콘텐츠풀 페인트(FCP), 최대 콘텐츠풀 페인트(LCP), 누적 레이아웃 이동(CLS) 외에도 3가지 추가적인 지표가 있다
- Time to Interactive
- 페이지에서 사용자가 완저니 상호작용할 수 있을 때까지 걸리는 시간
- 최초 콘텐츠풀 페인트로 측정되는 페이지 내 콘텐츠가 표시되는 시점
- 보여지는 페이지 요소의 대부분의 이벤트 핸들러가 부착되는 시점
- 페이지가 유저의 상호작용에 50ms 내로 응답하는 시점
- 구글에선, 이 TTI 지표가
3.8초 이내
면 좋다고 본다. - 최대한 빠르게 상호작용이 되도록 준비하려면
- 메인 스레드가 하는 자바스크립트 작업을 최소화
- 전체적인 자바스크립트 실행 속도 또한 높일 필요
- Speed Index
- 페이지가 로드되는 동안 콘텐츠가 얼마나 빨리 시각적으로 표시되는지를 계산
- 라이트하우스는 브라우저에서 로드되는 페이지를 실시간으로 캡쳐하고
speedline
라이브러리를 사용해 캡처된 이미지를 분석해 계산- 구글에서는 이 지표가
3.4초 이내
면 좋다고 본다.
- Total Blocking Time
- 메인 스레드에서 특정 시간 이상 실행되는 작업
- 즉, 긴 작업이 수행될 때마다 메인 스레드가 차단된 것으로 간주
- 메인 스레드가 차단됐다고 표현하는 이유는 브라우저가 이렇게 길게 실행되는 작업 때문에 무언가 다른 작업을 수행할 수 없기 때문
- 메인 스레드에서 실행하는 작업이
50ms 이상
걸리면 이를 긴 작업을 간주 - 이렇게 실행되는 긴 작업을 모아서 Total Blocking Time(총 차단 시간)이라고 한다
- 모두 합해서 계산
- Time to Interactive
접근성
- 웹 접근성
- 접근성 점수가 낮거나 미비한 부분이 있으면 확인 가능
- 어떻게 수정해야 하는지도 알려준다.
권장사항
- 보안, 표준 모드, 최신 라이브러리, 소스 맵 등 다양한 요소들이 포함
- CSP가 XSS 공격에 효과적인지 확인
- XSS란, Cross Site Scripting의 약자로, 스크립트를 통해 공격하는 기법
- CSP란, Content Security Policy의 약자로, 웹 사이트에서 호출할 수 있는 컨텐츠를 제한하는 정책
- 감지된 JS 라이브러리
- 페이지에서 감지된 자바스크립트 라이브러리
- HTTPS 사용
- HTTP 대신 보안이 더 강력한 HTTPS를 사용하는지 확인
- 페이지 로드 시 위치정보 권한 요청 방지하기
- 사용자의 동의 없이 페이지 로드 시 사용자의 물리적 위치를 메서드를 통해 알 수 있다.
- 물론, 이 두 함수가 호출된다고 해서 바로 위치 정보를 가져올 수 있는 것은 아니지만
- 다짜고짜 페이지 로드 시 요청하는 것은 사용자의 특별한 액션 없이 가져오는 것이므로
- 사용자의 액션 이후에 실행되어야 한다
- 페이지 로드 시 알림 권한 요청 방지하기
- 페이지 로드 시 웹 페이지 알림을 요청하는 메서드를 실행하는지 검사
- 사용자 액션이 있을 때만 호출하는 것이 좋다
- 알려진 보안 취약점이 있는 라이브러리를 사용하지 않음
- 보안 취약점이 존재하는 라이브러리를 사용하는지 확인
- 사용자가 비밀번호 입력란에 붙여넣을 수 있도록 허용
- 일부 사용자는 비밀번호를 관리하지 않고 복붙하여 입력
- 이는 보안 관점에서 타양한 접근 방식
- 웹에서 막지 않도록 하자
- 이미지를 올바른 가로세로 비율로 표시
- 실제 크기와 표시되는 크기 사이의 비율이 일치하는지를 확인
- 이미지가 적절한 해상도로 제공됨
- 선명하게 보일 수 있도록 크기에 맞는 해상도의 이미지를 제공하는지 확인
- 지원 중단된 API 사용하지 않기
- 더 이상 지원하지 않는 API는 잠재적인 보안 취약점이 될 수 있으므로 사용하지 않는 것이 좋다
- 콘솔에 로그된 브라우저 오류 없음
- 콘솔에 에러가 기록되는 것은 사용자에게 영향을 미치지 않을 수 있지만
- 분명 웹페이지에 문제가 있다는 사실
- 따라서 기록되지 않도록 해야 한다
- CSP가 XSS 공격에 효과적인지 확인
검색 엔진 최적화
- 문서를 크롤링하기 쉽게 만들었는지 확인하는 것부터
robots.txt
가 유효한지- 이미지와 링크에 설명 문자가 존재하는지
<meta>
나<title>
등으로 페이지의 정보를 빠르게 확인할 수 있는지 등을 확인
13.2.2 구글 라이트하우스 - 기간 모드
- 실제 웹페이지를 탐색하는 동안 지표를 측정하는 것
기간 모드 시작
을 누른 뒤 성능 측정을 원하는 작업을 수행한 다음 종료하면 그 사이에 일어난 작업들에 대한 지표를 확인 가능
흔적
- 웹 성능을 추적한 기간을 성능 탭에서 보여준다
- 상세하게 시간의 흐름에 따라 어떻게 웹사이트가 로딩되었는지를 보여준다
트리맵
- 페이지를 불러올 때 함께 로딩한 모든 리소스를 함게 모아서 볼 수 있는 곳
- 웹페이지의 전체 자바스크립트 리소스 중 어떠한 파일이 전체 데이터 로딩 중 어느정도를 차지했는지를 비율로 확인 가능 (실제 불러온 데이터의 크기도 확인 가능)
💡 로딩한 리소스에서 사용하지 않은 바이트의 크기 확인 가능
→ 실제로 불러왔지만 사용되지 않은 리소스
- 과도하게 큰 리소스나 혹은 사용하지 않은 바이트의 비중이 큰 리소스는 한 번쯤 눈여겨보는 것이 좋다
13.3 WebPageTest
- 무료도 있고 유료도 있어서 심도 있는 기능이 많다
- 제공하는 분석 도구는 크게 다섯 가지
- Site Performance: 웹사이트의 성능을 분석하기 위한 도구
- Core Web Vitals: 웹사이트의 핵심 웹 지표를 확인하기 위한 도구
- Lighthouse: 구글 라이트하우스 도구
- Visual Comparison: 2개 이상의 사이트를 동시에 실행해 시간의 흐름에 따른 로딩 과정을 비교하는 도구
- Traceroute: 네트워크 경로를 확인하는 도구
- 한국과 어느 정도 거리가 먼 서버를 기준으로 테스트하기 때문에
- 비교적 성능 지표가 좋지 않을 가능성이 매우 높다
13.4 크롬 개발자 도구
13.4.1 성능 통계
- 개발자 도구에서
Performance Insights
는 웹사이트의 성능을 자세하게 확인할 수 있는 도구 Throttling
기능을 사용하여 네트워크와 GPU 속도를 지연시켜 테스트해볼 수 있다.
Insights
- 성능을 측정하는 기간 동안 발생한 이벤트 중 눈여겨봐야 할 내용을 시간의 흐름에 따라 모아서 보여준다
- 핵심 웹 지표: FCP, LCP, Dom Content Loaded가 언제 일어났는지 보여준다
- Performance Measure: User Timing API로 측정한 지표들을 확인 가능
- Long Task: 메인 스레드에서 실행되는데 오랜 시간으로 분류된 긴 작업을 의미
- 코드도 확인할 수 있어 어떤 작업이 가장 긴 작업을 차지하는지 확인 가능
- Render blocking CSS: 렌더링을 막는 CSS. 해당 메시지를 클릭해서 무엇이 렌더링을 막는지 확인 가능
- Forced Style recalculation: 이미 스타일이 한번 계산된 이후로 어떠한 이유로 다시 계산되는 작업이 발생했음을 의미
- 가급적 유저가 어떠한 액션을 취하지 않은 이상 최초 로딩 시에는 일어나지 않는 것이 좋다.
메인 메뉴
- 메인 영역에서는 성능을 측정하는 기간 동안 무슨 일이 일어나는지 확인할 수 있는 다양한 기능 제공
- 크키가 조금 큰 작업이 있다면 클릭해보자
- 그 작업은 렌더러가 실행하기 위해 많은 시간을 보냈다는 뜻으로
- Long Task일 가능성이 큼. 성능 개선의 여지가 있음