최근 react-router-dom을 처음 사용하게 되었다.
그동안 하나의 브라우저 주소 안에서 모든 기능을 수행해야 했기 때문에 Modal 창을 이용해 여러 페이지인 척 하였다.
이젠 브라우저 주소를 바꿔가며 페이지를 전환할 수 있다.
처음에는 간단히 기능만 구현해보려고 구글링하여 다른 사람들의 코드를 보고 따라서 만들었다.
페이지 전환은 성공했지만 예상치 못한 난관을 겪게 되었다.
그것은 바로 state가 초기화되는 것이다.
처음에 작성한 코드는 다음과 같다.
// App.js
import { Routes, Route } from 'react-router-dom';
const App = () => {
return (
<>
<Routes>
<Route
path='/'
element={
<>
<Header />
<ProductListPage />
</>
}
/>
<Route path='/product/:id' element={<ProductDetailPage />} />
</Routes>
</>
);
}
export default App;
홈 화면인 /
경로와 제품 상세 페이지인 /product:id
경로를 만들었다.
// ./ProductItem.js
const ProductItem = (props) => {
return (
<li className={styles.item}>
<a href={'/product/' + props.name}>
<div className={styles.image}>
<img src={props.image} alt={props.name} />
</div>
<div className={styles.info}>
<h2 className={styles.name}>{props.name}</h2>
<strong className={styles.price}>{props.price}</strong>
</div>
</a>
</li>
);
};
export default ProductItem;
제품 리스트를 클릭하면 a
태그의 href
경로를 통해 상세 페이지로 넘어간다.
HTML에서 다른 위치로 이동할 때 a
태그를 사용했기 때문에 react-router-dom
에서도 동일할 것이라고 별 다른 의심 없이 사용하였다.
react-router-dom 라이브러리에 속한 컴포넌트인 Link
태그를 사용한다.
// ./ProductItem.js
...
<Link to={'/product/' + props.name}>
<div className={styles.image}>
<img src={props.image} alt={props.name} />
</div>
<div className={styles.info}>
<h2 className={styles.name}>{props.name}</h2>
<strong className={styles.price}>{props.price}</strong>
</div>
</Link>
...
a
태그를 Link
태그로, href
속성을 to
속성으로 변경하면 된다.
a
태그를 사용하면 클릭할 때마다 새로고침이 발생한다.
이는 전체 페이지가 다시 로드되어 리액트 상태가 모두 초기화된다는 것을 말한다.
리액트를 사용할 때 a
태그를 사용하면 치명적인 가장 큰 이유가 된다.
반면 Link
태그는 클릭해도 새로고침되지 않는다.
이는 SPA(Single Page Application)의 핵심 개념 중 하나로, 사용자 경험과 성능을 향상시킨다.
a
태그는 기본적으로 외부 링크를 처리하는 데 사용된다.
그렇기 때문에 페이지가 완전히 새로운 URL로 이동한다.
반면 Link
태그는 내부 페이지 간의 이동에 사용된다.
리액트 라우터가 제공하는 라우팅 기능을 활용하여 페이지를 렌더링하고 URL을 업데이트 할 수 있게 한다.
Link
태그는 브라우저 히스토리 API를 사용해 내부 라우팅을 처리한다.
이는 사용자가 뒤로/앞으로 가기 버튼을 클릭하면 정상적으로 라우팅을 처리할 수 있도록 한다.
반면 a
태그를 사용하면 페이지가 완전히 새로고침 되어 브라우저 히스토리를 관리하지 않는다.
위 3가지 이유로 인해 리액트에서 페이지를 이동할 때 a
태그가 아닌 Link
태그를 사용해야 한다.