개발일기
[내일배움캠프] 최종 프로젝트 - <picture>태그와 <source>태그를 활용한 이미지 최적화, uselocation hook을 이용한 페이지 이동 시 스크롤 탑 본문
카테고리 없음
[내일배움캠프] 최종 프로젝트 - <picture>태그와 <source>태그를 활용한 이미지 최적화, uselocation hook을 이용한 페이지 이동 시 스크롤 탑
코찡 2023. 9. 16. 16:001. <picture>태그와 <source>태그를 활용한 이미지 최적화
* 이미지 로딩 이슈(Layout Shift) 해결방법
1. 디바이스별 별도 이미지 사이즈 제공
2. <picture> 와 <source> 태그 (webp 지원 여부)
3. 이미지 변환 도구 - squoosh
-> 여기에서 사용해 볼 방법은 두 번째 방법 !
브라우저는 <picture> 태그 내에 선언된 <source> 태그 요소 중에서 srcset, media, type과 같이 선언된 속성(attibutes)들을 통해 기기에 적합한 이미지를 순차적으로 확인하고 노출하게 된다. 적합한 요소가 선언되어 있지 않거나, 브라우저가 picture를 지원하지 않을 때에는 <img> 태그에서 선언된 이미지가 노출된다.
정리하자면, <source> 태그는 브라우저가 렌더링해야 하는 파일과 크기를 결정하는 데 도움이 되는 정보를 제공하며, <img> 태그는 이미지의 크기와 대체 텍스트를 제공하고, <source> 태그가 적합한 이미지를 제공할 수 없는 경우에는 대체 이미지를 제공한다.
import mainBannerAvif from '../../../assets/imgs/partner/partner_post_banner.avif';
import mainBanner from '../../../assets/imgs/partner/partner_post_banner.png';
import mainBannerWebp from '../../../assets/imgs/partner/partner_post_banner.webp';
import * as St from './style';
function PartnerBanner() {
return (
<St.ImageWrapper $banner={`partner`}>
<St.PartnerMainImageBox>
<picture>
<source srcSet={mainBannerAvif} type="image/avif" />
<source srcSet={mainBannerWebp} type="image/webp" />
<img src={mainBanner} alt="동행 찾기 메인 배너 이미지" />
</picture>
</St.PartnerMainImageBox>
</St.ImageWrapper>
);
}
export default PartnerBanner;
2. uselocation hook을 이용한 페이지 이동 시 스크롤 탑
1) ScrollToTop 컴포넌트 정의
// components 폴더 하위 common 폴더 하위 scrollToTop 폴더 하위 ScrollToTop.tsx
import { useEffect } from 'react';
import { useLocation } from 'react-router';
export default function ScrollToTop() {
const { pathname } = useLocation();
useEffect(() => {
window.scrollTo(0, 0);
}, [pathname]);
return null;
}
2) ScrollToTop 컴포넌트 적용
(1) 모든 컴포넌트는 App 컴포넌트 아래 Router에서 관리하고 있습니다.
// root 경로에 App.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { Reset } from 'styled-reset';
import Router from './shared/Router';
const queryClient = new QueryClient({
defaultOptions: {
queries: {},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
<Reset />
<Router />
<ReactQueryDevtools initialIsOpen={false} position="bottom-right" />
</QueryClientProvider>
);
}
export default App;
(2) 따라서 Router 상단에 ScrollToTop 컴포넌트 import해주면, 모든 컴포넌트 페이지 이동 시 스크롤 탑 구현 가능
// shared 폴더 하위 Router.ts
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Layout from '../components/common/layout/Layout';
import ErrorPage from '../pages/ErrorPage';
import Intro from '../pages/Intro';
import LogIn from '../pages/LogIn';
import MyPage from '../pages/MyPage';
import Partner from '../pages/Partner';
import PartnerDetail from '../pages/PartnerDetail';
import PartnerWrite from '../pages/PartnerWrite';
import SignUp from '../pages/SignUp';
import SpotShare from '../pages/SpotShare';
import SpotShareDetail from '../pages/SpotShareDetail';
import SpotShareWrite from '../pages/SpotShareWrite';
import StyledWrapper from '../components/common/layout/StyleWrapper';
// ScrollToTop 임포트
import ScrollToTop from '../components/common/scrollToTop/ScrollToTop';
const Router: React.FC = () => {
// ScrollToTop 컴포넌트 삽입
return (
<BrowserRouter>
<ScrollToTop />
<Routes>
<Route path="/" element={<Intro />} />
<Route path="*" element={<ErrorPage />} />
<Route
path="/login"
element={
<StyledWrapper>
<LogIn />
</StyledWrapper>
}
/>
<Route
path="/signup"
element={
<StyledWrapper>
<SignUp />
</StyledWrapper>
}
/>
<Route
path="/partner"
element={
<StyledWrapper>
<Partner />
</StyledWrapper>
}
/>
<Route
path="/spotshare"
element={
<StyledWrapper>
<SpotShare />
</StyledWrapper>
}
/>
<Route element={<Layout />}>
<Route path="/mypage" element={<MyPage />} />
<Route path="/partner/detail/:postid" element={<PartnerDetail />} />
<Route path="/partner/write" element={<PartnerWrite />} />
<Route path="/partner/write/:postid" element={<PartnerWrite />} />
<Route path="/spotshare/detail/:postid" element={<SpotShareDetail />} />
<Route path="/spotshare/write" element={<SpotShareWrite />} />
<Route path="/spotshare/write/:postid" element={<SpotShareWrite />} />
</Route>
</Routes>
</BrowserRouter>
);
};
export default Router;