티스토리 뷰

1월 2주차, 원티드 프리온보딩 프론트엔드 챌린지 요약

 

성능 측정


Lighthouse

웹 성능을 분석하는 오픈소스이다.

주요기능은 다음과 같다.

 

  • 성능분석
  • 접근성 검사
  • SEO 평가
  • PWA 기준 평가

 

이 툴을 사용하고 싶다면, 'Chrome extension'을 활용하면 가능하다.

성능을 평가하고 나서 점수를 확인할 수 있는데, 각 평가 내용은 다음과 같다.

 

  1. Performance → 성능
  2. Accessibility → 접근성
  3. Best Practices → 보안
  4. SEO → 검색 최적화
  5. PWA → PWA 기준 확인

 

Web Vital

사용자 경험을 측정하는 수치이다.

 

Web Core Vitals - LCP(Largest Contentful Paint)

페이지의 '주요 콘텐츠'가 얼마나 빠르게 로드되는지 측정한다.

 

여기서 '주요 콘텐츠'라는 기준이 애매하지만, 실제로는 가장 큰 텍스트나 이미지를 나타낸다.

쉽게 말해, "빈칸이 언제 없어지는가"에 대한 평가를 내린다고 생각하면 된다.

 

  • 2.5 sec 이하 → Good
  • 2.5 sec 초과 ~ 4.0 sec 이하 → Needs Improvement
  • 4.0 sec 초과 → Poor

 

Web Core Vitals - FID(First Input Delay)

첫 이벤트 핸들링에 소요되는 시간을 말한다.

사용자가 버튼을 클릭하면, 해당 버튼의 이벤트가 언제 발생하는지에 대해 평가한다고 생각하면 된다. 

 

  • 100ms 이하 → Good
  • 100ms 초과 ~ 300ms 이하 → Needs Improvement
  • 300ms 초과 → Poor

 

Web Core Vitals - CLS(Cumulative Layout Shift)

설계 이슈로 UI가 변경되는 것을 말한다.

이해하기 쉽게 아래의 영상을 시청해보자.

 

 

Cumulative Layout Shift (CLS)  |  Articles  |  web.dev

이 게시물에서는 레이아웃 변경 횟수 (CLS) 측정항목을 소개하고 이를 측정하는 방법을 설명합니다.

web.dev

 

  • 0.1 이하 → Good
  • 0.1 초과 ~ 0.25 이하 → Needs Improvement
  • 0.25 초과 → Poor

 

기타 Web Vitals

 

 

Lighthouse 주의사항

'Production build'에서 테스트해야 한다. 그리고 가급적이면 'Incognito'에서 테스트하는 게 좋다.

 

'node_modules' 내에서 발생하는 에러들은 무시해도 괜찮다. 우리가 해결할 수 없는 문제라고 생각하는 게 편하다.

만약, 이 문제를 해결하고 싶다면 해당 패키지를 제거하는 게 낫다.

 

Performance Tab

Runtime 성능 측정

  • 렌더링 성능
  • 자바스크립트 성능
  • 메모리 관리
  • 반응성(First Input Delay)
  • 네트워크 성능

 

주요 정보

  • Loading
  • Scripting
  • Rendering
  • Painting

 

Profiler

강사 기준으로 가장 좋아하는 도구이다. React 내장 기능올, 컴포넌트 별 렌더링 시간을 측정할 수 있다.

이 도구도 'Chrome extension'에서 활용할 수 있다.

 

만약, 특정 컴포넌트에서 병목이 발생한다면 해결하면 된다.

 

또한, 코드로 직접 작성해 측정할 수도 있다. 코드로 직접 작성해 확인한다면, 세부사항을 자세히 확인할 수 있다.

function onRender(id, phase, actualDuration, baseDuration, startTime, commitTime) {
  // 렌더링 시간 집계 혹은 로그...
  console.log(id);
  console.log(phase);
  console.log(actualDuration);
  console.log(baseDuration);
  console.log(startTime);
  console.log(commitTime);
}

<Profiler id="App" onRender={onRender}>
  <App />
</Profiler>

 

  • phase
    • mount → 페이지에 처음 접근하고 마운트됐을 때
    • update → 페이지의 상태가 변경되었을 때
  • committime
    • mount가 되고 나서 화면에 그림이 그려진 시간
  • baseDuration
    • 로드가 됐을 때 컴포넌트가 걸린. 즉, 그려진 예상 시간
  • actualDuration
    • 실제로 로드되고 나서 컴포넌트가 그려진 시간

 

Lighthouse 사용 방법

'Lighthouse''Production build'에서 확인이 가능하다.

' Production build' 시 나름의 최적화가 진행되어 'Web Vital'이 상당 부분 개선된다.

  • Minification
  • Tree shaking

 

 

 

Minification

빈칸, 줄바꿈 등을 제거한다.

Vite 기준 'dist/asset/.js'이 해당된다.

 

Tree shaking

'dev'에서는 불필요한 내용이 많이 보인다.

예를 들어, 설치한 라이브러리에서 특정 부분 수정하는 것처럼 말이다.

이것을 반경하기 위해서 모든 라이브러리를 'fork'해서 수정해야 한다.


최적화 - Code Splitting

'Bundle size'를 줄이는 방법이 해당된다.

이는, 전체 용량이 줄어드는 것이 아닌 하나의 번들을 여러 개로 잘게 쪼개는 것을 의미한다.

 

'React lazy + Suspense'의 조합을 보통 사용하고 있다.

 

React.lazy 및 Suspense를 사용한 코드 분할  |  Articles  |  web.dev

React.lazy 메서드를 사용하면 동적 가져오기를 사용하여 구성 요소 수준에서 React 애플리케이션을 쉽게 코드 분할할 수 있습니다. Suspense와 함께 사용하여 사용자에게 적절한 로드 상태를 표시합

web.dev

 

lazy – React

The library for web and native user interfaces

react.dev

 

<Suspense> – React

The library for web and native user interfaces

react.dev

 

그리고, 최초 로딩 시간이 단축되는 이점이 있다.

이를 통해, FCP, LCP, FID 개선이 가능하다.

 

리액트 빌드 최적화 (feat. ChatGPT) - Byeongjin Jason Kang

회사에서 lazy loading을 통해서 web vital을 개선했었는데, 조금 더 최적화를 진행해보고 싶었습니다. 최적화가 필요하겠다고 생각했던 이유는 Amplify에서 측정해준 빌드시간이 9분을 넘기는 경우가

jasonkang14.github.io

 

또한, 브라우저 Cache를 사용하여 최적화가 가능하다.

 

Lazy Loading

'Lighthouse' 만점이라고 최적화가 끝난 것이 아니다. 'IntersectionObserver' 등을 이용해 불필요한 렌더링을 줄이는 것이 필요하다.

 

최적화에서 중요한 것

어떤 최적화를 했느냐는 중요하지 않다.

 

  • Code-splitting 적용
  • Lazy loading 적용

 

위 항목들 자체로는 무의미하고, '왜' 해당 방식으로 최적화를 했는지를 설명할 수 있어야 한다.

 

즉, 최적화의 의미코드의 문제점을 파악하고 해결하는 것을 말한다.

이를 통해, 문제해결 능력을 어필하는 식으로 이력서를 작성할 수 있다.

 

예를 들어, 아래의 내용처럼 말이다.

'react-router-dom'의 'routerConfig'에 'Lazy loading'을 적용하여 'index.js'의 'Bundle size' 감소로 'FCP' 60% 개선하였다처럼 말이다.

 

+ 추가 - Performance Tab

'Chorme extension''Performance(성능)'에서 페이지 로드가 얼마나 걸렸는지 자세히 확인해볼 수 있다.

 

프레임에서 초록색 바를 통해 로드되는 시간이 양호한 상태를, 아닐 경우에는 시간이 더 소요됐다는 것을 알 수 있다.


Code Splitting

말 그대로 '코드 분할'을 말한다.

전체 코드를 작은 조각들로 나누는 것을 의미하며, 처음에 불러올 코드가 줄어드니 사용자가 빈 화면을 보는 시간이 줄어든다.

 

특징은 다음과 같다.

 

  • 지연 로딩(Lazy Loading)
    • 애플리케이션의 특정 부분이 사용자에 의해 필요할 때, 로드한다.
    • 어떤 페이지나 컴포넌트가 사용자의 특정 액션을 통해 나타난다면, 그 액션이 발생하기 전까지 그 페이지나 컴포넌트를 로로드하지 않는다.
  • 캐싱 최적화
    • 코드를 작은 단위로 나누면, 변경이 필요한 부분만 업데이트가 가능하다.
    • 전체 애플리케이션을 새로고침하지 않아도, 특정 부분만 쉽게 업데이트할 수 있다.

 

예시는 다음과 같다.

 

Index.js 사이즈 감소

 

 

FCP, LCP 비교

 

포트폴리오 관리 시 주의사항

'Default branch'에서 빌드를 확인한다. 'npm install'이 되지 않는 경우가 발생할 수 있다.

 

'lock 파일'은 하나만 사용해야 한다. 그렇지 않을 경우, 'Dependency' 파악이 어렵다.

그리고 패키지는 하나만 사용해야 한다. 팀 프로젝트라면 맞춰야 하며, 패키지 매니저는 별 차이가 존재하지 않는다. 체감할만큼의 프로젝트를 개인적으로 하기 어려운 경우가 많다.

 

최적화 주의사항

프로젝트에 최적화가 꼭 필요한 것인지 확인해볼 필요가 있다.

'Lighthouse' 점수는 올라갔지만, 화면은 오히려 느릴 수도 있다.

 

이미지 최적화

용량이 너무 크면 로드하는 데 오래 걸리게 된다. 이럴 경우, 로딩도 오래 걸리고, 브라우저에 과부하가 걸리게 된다.

체감될 정도는 아니지만, 최적화 관점에서 볼 때 좋지 않다. 만약에, 화면에 이미지가 10,000개 이상이 보이는데 모두 오버 사이즈라면 문제가 발생할 것이다.

 

권장하는 크기는 이미지를 사용할 요소의 크기에 '2배'이다.

윈도우는 굳이 2배일 필요가 없지만, 맥에서 Retina Display에서 이미지가 깔끔하게 보이기 위해서는 2배를 넣어주어야 한다.

 

크기를 줄이는 방법은 만약, 디자이너가 있다면 이미지를 새로 받아서 사용하는 게 낫다.

서버에서 스토리지에 이미지를 저장할 때, 화면 보고 크기에 맞는 사이즈로 저장해야 한다.

그리고 각 확장자들을 알고 있어야 하며, 사용할 때 '.webp' 확장자를 고려해야 한다.

 

이미지 최적화를 제대로 하기 위해서는 스토리지에 화면에서 필요한 사이즈 별로 이미지를 들고 있어야 한다. 같은 이미지가 여러 화면에 사용되면 해당 영역에 맞는 크기의 'Presigned-Url'을 넘겨주어야 한다.

 

이미지 최적화 - 파일 포맷

상황에 따라 다른 포맷을 사용해야 한다.

 

  • svg → 아이콘, 작은 이미지
    • 강사 개인적으로 64 x 64보다 작으면 svg를 사용하며, 임의의 기준으로 꼭 따를 필요 없다.
  • png → 스크린 샷처럼 세부사항이 잘 보여야 하는 경우
    • jpeg과 png의 차이점을 이해하고 있어야 한다.
    • jpeg은 용량이 작은 대신 품질이 손상된다.
    • 가끔 백엔드에서 비용 문제를 제시하는 경우가 있지만, 스토리지 비용의 차이는 크지 않다.
  • webp → 최근 구글에서 밀고 있는 파일 포맷
    • 확실하게 용량 측면에서 유리하다.
    • 로드가 빠르다.

 

폰트 최적화

브라우저 호환성을 고려해서 'woff', 'woff2'로 설장한다.

그러나, 둘 다 필요 없으며, 'woff2'만 설정해도 충분하다. 요즘에는 왠만하면 크롬이나 엣지를 사용하고 있기 때문에 괜찮다.

 

좋은 방법으로 'npm'으로 폰트를 설치해서 사용하는 게 낫다.

 

가급적, '웹 폰트'를 추천하며, CDN을 직접 관리 안 하는 것 자체만으로도 일단은 관리 포인트가 줄어든다.

웹 폰트 호스팅을 도저히 믿지 못하겠으면, 직접 하는 것도 방법이다.

 

'@fontsource' 라이브러리를 사용하는 것을 추천하며, 원하는 폰트를 찾아서 사용하면 된다.

용량이 훨씬 가볍고, 'import'하면 사용되는 스타일의 폰트만 추가하면 된다.

 

@fontsource/noto-sans-kr

Self-host the Noto Sans KR font in a neatly bundled NPM package.. Latest version: 5.0.17, last published: a month ago. Start using @fontsource/noto-sans-kr in your project by running `npm i @fontsource/noto-sans-kr`. There are 2 other projects in the npm r

www.npmjs.com

 

'Next.js'에서 추천하는 폰트 최적화 방식이 있다. 성능 상 우위에 있는지 'Lighthouse'에서 측정은 되지 않지만, 한 번 시도해보는 것도 나쁘지 않다.

 

추상화

복잡한 내용을 단순화하는 과정이다.

복잡한 코드의 세부 사항을 걱정하지 않고도 프로그램의 핵심적인 부분에 집중할 수 있게 만들어 준다.

 

추상화의 목적코드의 복잡성을 관리하고 재사용성을 높이는 것이다.

객체지향에서 나왔기 때문에 원칙 상 재사용성도 고려해야 한다. 프론트엔드에서 컴포넌트를 쪼갤 때는 코드 복잡성 관리와 가독성 향상에 가깝다.

 

이 때, 컴포넌트를 잘 쪼개줘야 한다.

변수명만 보고도 그 컴포넌트의 역할을 알 수 있도록 만들어야 한다.

만약, 컴포넌트 하나의 'return' 구간이 너무 길어지면 로직도 많아지고, 'jsx'도 많아지기 때문에 가독성이 떨어지게 된다.

 

추가적으로 작업해야 할 것은 불필요한 요청을 제거하고, 함수형 프로그래밍 원칙을 준수하며, 불필요한 'state'를 제거하는 것이다.

 

Q&A

부트캠프를 추천한다면 어디를 추천하는가?

→ 네이버 부트캠프(네부캠), 우아한테크코스(우테코, 참가자 의견)을 추천한다.

그렇지만, 강사 의견으로는 부트캠프는 필수가 아니다. 추천이냐 비추천이냐에 대한 질문이 있다면 추천하지 않는다고 할 수 있다.

 

이미지, 동영상 파일은 프로젝트에서 사용이 어려운 것 같은데, 어떻게 사용해야 하는가?

이미지는 프로젝트에서 사용이 가능하나, 동영상은 어렵다.

스토리지에 저장해서 사용해야 한다. 무료가 아닌 유료이다.