-
Notifications
You must be signed in to change notification settings - Fork 2
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
[ Feat ] 컴포넌트 별 코드 스플릿팅 #210
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
너무 고생하셨어요. 번들 구조, 네트워크 탭, 라이트하우스 지표를 보며 필요한 번들을 불러오는 과정에 대해서 정리해주셔서 이해가 쉬웠어요. 리뷰에 대해서만 확인 부탁드릴게요.
import { useCallback, useState } from 'react'; | ||
|
||
export const usePreloadCalendar = () => { | ||
const [isCalendarLoaded, setIsCalendarLoaded] = useState(false); | ||
|
||
const preloadCalendarComponent = useCallback(() => { | ||
if (!isCalendarLoaded) { | ||
import('@/shared/components/Calendar').then(() => { | ||
setIsCalendarLoaded(true); | ||
}); | ||
} | ||
}, [isCalendarLoaded]); | ||
|
||
return { isCalendarLoaded, preloadCalendarComponent }; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1:
- 캘린더를 preloading 할 때 useState, useCallback 없이 잘 작동하는것으로 확인되는데 사용하신 이유가 궁금해요!
- useState, useCallback 사용 없이 preloading 하는것을 제안드리고 싶어요, 그렇게 되면 커스텀훅을 만들필요도 없을것 같은데 어떻게 생각하나요?!
const handleMouseEnter = () => {
import('@/shared/components/Calendar');
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
p1:
- 캘린더를 preloading 할 때 useState, useCallback 없이 잘 작동하는것으로 확인되는데 사용하신 이유가 궁금해요!
- useState, useCallback 사용 없이 preloading 하는것을 제안드리고 싶어요, 그렇게 되면 커스텀훅을 만들필요도 없을것 같은데 어떻게 생각하나요?!
const handleMouseEnter = () => { import('@/shared/components/Calendar'); };
useState
와 useCallback
을 사용하지 않는다면, 캘린더가 이미 로드되었는지 성공적으로 로드되었는지 추적이 불가능하기 때문에 중복된 import
요청이 발생하지 않을까?라는 우려가 있었습니다. 하지만, 대원님의 의견대로 진행하여도 동일한 모듈을 여러 번 import
하는 경우가 발생해도 이미 로드된 모듈이면 즉시 캐시된 결과를 반환하여 중복 요청을 막을 수 있다고 하네요! 실제로 확인해본 결과 네트워크창에서 한번 로드되었으면 재로드를 하지 않는것을 확인하였습니다. 의견 반영하겠습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
자세한 설명 감사드려요~~
- 말씀해주신대로 동적 import할 때는 브라우저 수준에서 캐시가 되므로, 중복된 네트워크 요청으로 번들을 로드 하는 사항은 고려하지 않아도 괜찮을것 같아요~
- 성공적인 번들 로드에 대해서 언급해주셔서 생각하보니 추가적으로 캘린더 컴포넌트를 동적으로 import 하는 동작을 실패할 경우에 대해서 고려해야할것 같네요. 네트워크가 갑자기 끊기거나 하면 실패할수도 있겠네요. 다음과 같이 에러가 발생했는지 파악할 수 있게 간단하게 console error 코드를 추가하면 어떨까해요!
충분한 예외 사항 고려감사합니다. 하나 배워갑니다~
handleMouseEnter = () => {
import('./components/ImageModal')
.catch((error) => {
console.error('캘린더를 받아오는데 오류가 발생했습니다.', error);
});
};
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
자세한 설명 감사드려요~~
- 말씀해주신대로 동적 import할 때는 브라우저 수준에서 캐시가 되므로, 중복된 네트워크 요청으로 번들을 로드 하는 사항은 고려하지 않아도 괜찮을것 같아요~
- 성공적인 번들 로드에 대해서 언급해주셔서 생각하보니 추가적으로 캘린더 컴포넌트를 동적으로 import 하는 동작을 실패할 경우에 대해서 고려해야할것 같네요. 네트워크가 갑자기 끊기거나 하면 실패할수도 있겠네요. 다음과 같이 에러가 발생했는지 파악할 수 있게 간단하게 console error 코드를 추가하면 어떨까해요!
충분한 예외 사항 고려감사합니다. 하나 배워갑니다~
handleMouseEnter = () => { import('./components/ImageModal') .catch((error) => { console.error('캘린더를 받아오는데 오류가 발생했습니다.', error); }); };
에러코드 추가해주면 좋겠네요! 의견 반영하겠습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생많으셨습니다. 레전드 개발자 김건휘 🚀🚀🚀🚀🚀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
건휘님 고민 과정이 pr과 리뷰에 잘 담겨 있어 인상 깊게 보고 갑니다!
hook으로 분리하던 초기 방식에서 handleMouseEnter로 에러 처리까지 직관적으로 나타내는 방식으로 수정된 부분도 좋았습니다!
수고 많으셨어요 :) LGTM!!
오.... onMouseEnter 속성으로 컴포넌트가 사용되는 시점을 미리 예측해서 preload하는거 너무 신기하고 좋은방법이네요...아티클도 꼼꼼히 작성해주셔서 이해하기 수월했습니다. 재밌게 읽고 갑니다!!Lgtm |
🔥 Related Issues
✅ 작업 리스트
🔧 작업 내용
React
는SPA(Single-Page-Application)
인데, 사용하지 않는 모든 컴포넌트까지 초기에 한 번에 불러오기 때문에 첫 화면이 렌더링 될때까지의 시간이 오래걸린다는 단점이 존재합니다. 저희Morib
프로젝트에서도 초기HomePage
랜더링시 많은 용량을 차지하고 있는DatePicker
번들을 불러오고 있었습니다. 그래서Calendar
컴포넌트를lazy로딩
과suspense
로 동적으로 컴포넌트를 임포트를하게하여DatePicker
가 필요한 시점에 불러오게하여 사용하는 방법으로 성능 최적화를 진행하였습니다.Calendar
는BoxCategory
,ModalAddCategory
컴포넌트에 사용되므로 2개의 컴포넌트에서 Calendar 컴포넌트에 lazy를 적용해주었습니다.다음과 같이 Calendar에 lazy를 걸어주고
Suspense
도 적용해 주었습니다.lazy
를 통해 import하면 해당 컴포넌트를 불러오는 시점에 로딩하는 시간이 생기게 됩니다.Suspense
는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 때 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능입니다.하지만 lazy로딩과 suspense로 동적으로 컴포넌트를 임포트를하게 되면 해당 컴포넌트를 사용하는 시점에 로딩이 발생할 수 있어서 오히려 성능을 저해하거나 사용자 경험을 저해하지 않을까?🤔
그래서
Preloading
을 활용하여 해당 문제를 해결하고자 하였습니다.onMouseEnter
의 속성을 활용하여lazy로딩
이 적용된 컴포넌트가 사용되는 시점을 미리 예측하여 불러오게 하였습니다.BoxCategory
컴포넌트에서는 + 버튼에mouseover
시,ModalAddCategory
컴포넌트에서는 날짜 선택 토글에mouseover
시lazy로딩
이 적용된Calendar
컴포넌트를 불러오도록 하였습니다.usePreloadCalendar
커스텀 훅 생성BoxCategory
,ModalAddCategory
컴포넌트에서 공통적으로 Calendar를 preload하고 있기 때문에, Calendar를 preload하는 로직을 커스텀 훅으로 분리하여 재사용 가능하도록 하였습니다.🧐 새로 알게된 점
🤔 궁금한 점
처음 해보는 코드 스플리팅 작업이어서 제대로 했는지 감이 안잡힙니다. 많은 피드백과 의견 부탁드려요!
📸 스크린샷 / GIF / Link
onMouseEnter
속성을 활용하여, 날짜 토글 위에 마우스가 올라오면Calendar
를preload
할 수 있게 하였습니다. 날짜 토글 위에 마우스가 올라와야 네트워크탭에Calendar
를 불러오고 있는 것을 확인할 수 있다.자세한 내용과 성능 지표 향상 정도는 아티클 참고부탁드립니다.
https://velog.io/@geonhwi1014/React-%EC%BD%94%EB%93%9C-%EC%8A%A4%ED%94%8C%EB%A6%AC%ED%8C%85code-spliting-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94