Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[개인 미션 - 성능 오답노트] 루루(송지은) 미션 제출합니다. #77

Merged
merged 28 commits into from
Sep 11, 2023

Conversation

hafnium1923
Copy link

@hafnium1923 hafnium1923 commented Sep 6, 2023

🔥 결과

image image

✅ 개선 작업 목록

1 요청 크기 줄이기

  • 소스코드 크기 줄이기
    • js minify 설정을 true로 변경
    • css minify를 위해 MiniCssExtractPlugin를 설치 후 MiniCssExtractPlugin.loader사용, optimization의 minimizer에 CssMinimizerPlugin() 추가
    • compressionWebpackPlugin을 이용해 소스코드 압축
  • 이미지 크기 줄이기
    • 수동으로 hero 이미지 크기 축소. webp를 지원하는 경우 뷰의 크기에 따라 3가지 이미지 중 맞는 크기의 이미지가 나옴. webp를 지원하지 않는경우 축소된 기본 이미지(765KB)를 보이게함.
    • 수동으로 gif 이미지 최적화를 진행. 각 gif에 대해 mp4와 webm두가지 확장자의 파일을 준비. webm을 지원할경우 webm파일이, 아닌경우 mp4 파일이 보이도록 함
    • gif 를 보여주기 위해 사용한 태그 img에서 vedio태그로 변경

2 필요한 것만 요청하기

  • 페이지별 리소스 분리
    • react의 lazy를 이용해 필요한 리소스만 불러올 수 있도록 변경
  • 아이콘 패키지 Tree Shaking
    • commonJS에서는 tress Shaking을 하지 못하기 때문에package.json의 babel설정의 modules: false로 설정해 babel이 ES6을 comomJS로 변경하지 못하도록 함.
    • package.json에 sideEffects를 falas로 설정해 사용하지 않는 코드를 제거. css파일은 sideEffects 목록에 추가해 프로덕션 모드에서 실수로 삭제되는 것을 방지 함

3 같은 건 매번 새로 요청하지 않기

  • CloudFront 캐시 설정 (설정값, 해당 값을 설정한 이유 포함)
    • max-age=31536000(1년), 캐시 변경이 적고 기간이 길수록 캐시 적중률이 높아지기 때문에 설정
  • GIPHY의 trending API를 Search 페이지에 들어올 때마다 새로 요청하지 않아야 한다.
    • trending gif가 실시간 업데이트일 필요가 없는 것이지 업데이트 자체는 필요하다고 생각함. 따라서 홈페이지가 열려있는 동안은 같은 것을 볼 수 있고 닫고 다시 열 경우는 당시의 tranding gif를 보도록 함. da83c53

4 최소한의 변경만 일으키기

  • 검색 결과 > 추가 로드시 추가된 목록만 새로 렌더되어야 한다.
    • gitItem을 memo로 감싸서 한번 로딩된 gifItem은 다시 렌더링 되지 않도록 막음
  • Layout Shift 없이 애니메이션이 일어나야 한다.
    • CustomCursor와 gifItem < hover, 도움말의 애니메이션에서 transform을 사용해 화면이 밀리는 layout Shift현상을 없앰
  • Frame Drop이 일어나지 않아야 한다.
    • (Chrome DevTools 기준) Partially Presented Frame 역시 최소로 발생해야 한다.
    image

🧐 공유

처음 보는 키워드라 그런지 방법 찾는 부분부터 막혔던 것 같아요. 성능 최적화라고 하면 단순히 렌더링 최적화만 생각했는데 생각보다 더 다양한 방법이 있어서 놀랐어요ㅋㅋ
그래도 퍼포먼스가 찔끔씩 올라가는거 보니까 뿌듯하기도 하고..
다만 WebPageTest를 진행할 때 첫 방문시 LCP를 어떻게 더 줄일 수 있는지는 잘 모르겠어요.. 이미지 크기 때문인가해서 이미지 크기 더 줄여봤는데 소용이 없네요. 혹시 어떤게 문제인지 같이 찾아봐주실 수 있나요?

  • <link rel="preload" as="image" href="/static/hero.webp" />
    를 index.html에 추가한 것으로 조금 줄이긴 했어요! 번들을 불러온 다음 이미지를 요청해서 시간이 오래걸린다고 하네요..!ㅎㅎ..
image

센트는 어떤 것이 젤 힘들고 재밌었나요?

@hafnium1923 hafnium1923 self-assigned this Sep 6, 2023
Copy link
Member

@kyw0716 kyw0716 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

루루의 리뷰를 맞게 되어 영광입니다👍👍

몇 가지 궁금한 점에 대해 간단하게 리뷰 남겨봤습니다! 확인 부탁드릴게요~~

<div id="app"></div>
</body>
</html>
<head>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기에 이 웹 페이지가 어떤 페이지 인지를 설명하는 meta 태그가 추가되면 좋을 것 같습니다.

ex) <meta name="description" content="{사이트 설명}" />

구글에 특정 사이트를 검색했을 때 하단의 작은 설명 부분에 해당하는 정보라고 하네요!

image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a83d512
적용했습니당!

"@babel/preset-react"
"@babel/preset-react",
{
"modules": false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이 부분은 어떤걸 의미하는 건가요??

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"modules": false을 한 이유는 balel이 commonJS로 변환하기도 하는데 그러면 sideEffects옵션이 작동하지 않는다고해서 넣어준 설정입니다


import NavBar from './components/NavBar/NavBar';
import Footer from './components/Footer/Footer';

import './App.css';

const Home = lazy(() => import('./pages/Home/Home'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 크루분들 중에 Home 컴포넌트는 초기 렌더링에 사용되는 컴포넌트라서 동적 import를 사용하지 않은 분들도 계시는데 루루는 분리 해주셨군요! 혹시 Home 컴포넌트도 동적 import를 적용해준 이유가 있나요?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약 /searsh 로 바로 접속하게 된다면 Home파일도 불러오게 되니까 적용했습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hero 이미지의 크기를 1025 * 684로 해주신 이유가 있나요?! 전 크기를 어떻게 해야할지 몰라서 일반적인 모니터 기준인 1920 * 1080으로 해줬었는데 사이즈를 더 줄일 수 있으면 좋을 것 같아서요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어,, 그냥 변환사이트에서 파일용량이 제 마음에 맞게 작아지는 사이즈로 해둔거였어요! 파일 퀄리티도 용량이 줄어들지만 이미지 크기를 줄이면 꽤나 크게 용량이 줄어들더라구요. 큰 이유는 없습니다.ㅋㅋ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 ㅋㅋㅋㅋ 전 뭔가 지정된 크기가 있었나 해서 여쭤봤었는데 그런게 따로 있지는 않았나보군요!

@@ -19,7 +26,14 @@ const Home = () => {
return (
<>
<section className={styles.heroSection}>
<img className={styles.heroImage} src={heroImage} alt="hero image" />
<picture>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

picture 태그는 어떤 역할을 수행하나요?! 전 한번도 사용해보지 않은 태그여서 궁금합니다!😀

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지를 여러개 정의할 때 사용하는 태그입니다! 저 같은 경우는 webp를 지원할 경우와 안할경우로 나눠서 정의했기 때문에 사용했어요

@@ -16,4 +16,4 @@ const GifItem = ({ imageUrl = '', title = '' }: GifItemProps) => {
);
};

export default GifItem;
export default memo(GifItem);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 주로 memo를

const Component = memo(() => {});

export default Component

이렇게 사용하는데 루루는 export default에서 사용해주셨네요! 혹시 이렇게 사용하시는 이유가 있으신가요?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

큰 변화는 아니지만 컴포넌트 정의 하는 것 자체는 똑같이 하되, 내보낼 때 memo를 감싸게 하여 헷갈리지 않고 간단하게 memo를 적용할 수 있다는 장점이 있다고 생각해서 이렇게 사용합니다ㅎㅎ

new Dotenv()
new Dotenv(),
new MiniCssExtractPlugin(),
new CompressionPlugin({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 플러그인은 어떤 역할을 수행하나요?!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 선택한 압축방식으로 코드를 압축해줍니다. 근데 CDN 정책에도 압축방식이 있어서 이렇게 하면 효과가 있는지는 잘 모르겠습니다. CDN을 적용하기 전에 해둔거라ㅎ..

@@ -21,6 +21,8 @@ function convertResponseToModel(gifList: IGif[]): GifImageModel[] {
});
}

let tredingGif: GifsResult | null = null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로컬에서 캐싱을 해주기 위해 추가한 로직인가요?! 이렇게 따로 변수를 선언하는 방식을 선택하신 이유가 궁금합니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

간단한 코드 추가로 캐싱이 가능하기 때문에 선택했습니다. 이렇게 하면 홈페이지가 닫히기 전까지는 계속 값을 가지게 할 수 있으니까요

@@ -0,0 +1,57 @@
작업 목록
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

깔끔하게 정리해주신 문서 덕분에 리뷰하기 수월했습니다!! 👍👍

Copy link
Member

@kyw0716 kyw0716 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

남겨주신 답변 모두 확인했습니다!! 고생하셨어요~~

@kyw0716 kyw0716 merged commit 3f85e25 into woowacourse:hafnium1923 Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants