왕초보를 위한 React Router v5 핵심 요약(feat. 풍부한 예시 코드, 꼼꼼한 설명)
#전체
#개발자
#프론트엔드
#react router
#react router 6
#react router tutorial
#router
#react router 6 tutorial
#react router version 6
00:00
react-router-v6 공식 문서 링크: https://reactrouter.com/docs/en/v6
사용하는 용어 정리:
pathname은 localhost:3000/products에서 /products를 의미
01:02~02:15
해당 강의에 사용된 코드를 저장하는 법과 프로젝트 파일을 여는 법을 설명합니다.
*해당 학습노트용 코드는 lesson-1 branch 지정 후 다운로드 받으셔야합니다.
*Visual Studio Code를 설치해놓으셔야 합니다.
링크: https://github.com/iamshaunjp/React-Router-Version-6
02:36
react-router 버전 5.1으로 작성된 코드를 먼저 살펴본 후에 점진적으로 버전 6 코드로 수정해 나갈 예정이라 소개합니다.
02:59Visual Studio Code를 통해 terminal을 여는 법을 소개하고 terminal을 통해 package.json에 명시된 라이브러리를 프로젝트에 다운로드 하는 법을 소개합니다.
03:10~05:33
App.js 코드 설명
react router 5.1 버전에서는 react-router에서 import한 컴포넌트를 사용하기 위해 BrowserRouter 컴포넌트로 감싸줘야합니다.
nav 태그에는 다른 페이지로 전환할 수 있는 Link 컴포넌트가 세 개 위치합니다. 클릭하면 각각 '/', '/about', '/products'로 pathname을 변경합니다.
그 아래 Switch 컴포넌트는 현재 pathname에 따라 어떤 화면(컴포넌트)을 보여줄지 정해주는 filtering 같은 존재입니다.(한 번에 하나의 Route만 활성화 됩니다)
즉, 특정 pathname에 대해 어떤 동작을 할지 정의하는 행위를 일컬어 routing이라 하며 이 동작의 주체를 router라고 하는 것이죠(react-router의 이름 이유)
특정 pathname에 어떤 컴포넌트를 띄워줄지 지정하려면 Route 컴포넌트를 사용해야합니다. Route의 path에는 연결할 pathname(예: '/', '/about')을 적어주며 component에는 현재 pathname과 Route의 path가 일치할 시 띄울 컴포넌트를 입력합니다(<About />, <Products /> 처럼 감싸는 형식으로 입력해도 됩니다)
또한 <Route path="/products/:id" >에서 :id는 changable한 값입니다. '/products/1'로 접근해도 되고 '/products/2'로 접근해도 되는것이죠.
version 5.1에서 routing할 때 주의할 점은 Route 간의 순서입니다. react-router v5에서는 Route를 위에서 아래 순으로 현재 pathname과 path를 비교하기 시작하는데요, 만약 <Route path="/products" />가 <Route path="/products/:id" /> 보다 위에 있었다면 pathname: /products/3으로 접근해도 /products pathname에 지정된 컴포넌트가 화면에 나왔을 것입니다. 그 이유는 Route의 path가 pathname에 에 포함되어있을 시 제대로 매칭되었다고 판정 내리기 때문이에요. 그래서 <Route path="/products/:id" />를 위에 위치시켜놓은 것이죠.
위 문제를 해결하기 위해 exact prop을 전달합니다. exact prop이 Route에 전달되면 pathname과 Route의 path가 정확히 일치해야지만 Rotue 내의 컴포넌트를 화면에 띄웁니다.
05:32~05:59
Home 컴포넌트 설명
Home 컴포넌트의 구조를 설명합니다. 내부 코드는 react-router 내용에 외적인 부분이므로 별도 언급하지 않겠습니다.
강의에서 Home.js에서 App.js 파일로 넘어가 설명하는 부분이 있는데, <Route exact path="/" component={Home} />으로 인해 pathname이 '/'일 경우 Home 컴포넌트가 띄워진다는 설명을 하고 있습니다.
06:01~06:59
About 컴포넌트 설명
Home 컴포넌트와 마찬가지로 react-router 외적으로는 설명을 건너뛰겠습니다.
About 컴포넌트에서 주목할 점은 nested route입니다. 말그대로 route 속 route이죠.
pathname이 '/about'일 때 <Route path="/about" />에 의해서 About 컴포넌트가 화면에 띄워지죠? 그러면은 About 내부의 Route도 조건을 충족하는지 확인해볼까요? pathname이 '/about'이지만 <Route path="/about/offers" />을 보면 Route의 path가 pathname에 포함되지 않기 때문에 routing 조건을 충족하지 않고 결과적으로 Offers 컴포넌트가 렌더링 되지 않게 됩니다.
반대로 pathname이 /about/offers일 경우는 About 컴포넌트 속 서브 Route의 path가 pathname에 포함되게 되므로 화면에 Offers 컴포넌트가 띄워지는 것이죠.
*서브 라우트를 하는 이유: 갑자기 등장한 nested route에 혼란스러울 수 있는데요. 만약 nested route 없이 About의 내용을 구현하려면 어떻게 해야할까요? App 컴포넌트에서 <Switch> 하위에 <Route path="/about/offers" />를 둬야할 것이고 또 기존 About 컴포넌트에 Offers 컴포넌트를 추가한 버전의 컴포넌트를 Route의 component prop으로 전달해야할 것입니다. 그리고 별도로 <Route path="/about" />와 Offers를 렌더링하지 않는 버전의 About 컴포넌트를 Route의 component prop에 전달해야겠죠.
즉 화면에 띄워야하는 기본 내용은 존재하되 pathname에 따라 추가적인 정보를 보여줘야하는 상황에서 nested route를 사용합니다. 결과적으로 작성해야할 코드도 줄어들고 가독성도 좋아지는 효과가 있습니다.
06:59~07:58
Offers 컴포넌트 설명
react-router와 관련된 내용은 나오지 않기 때문에 해당 구간은 설명을 Skip하겠습니다.
08:04~09:22
Products 컴포넌트 설명
Products 컴포넌트는 pathname이 '/products '일 때 띄워집니다.
또한 12개의 product에 대한 UI를 반환하네요.
product UI를 클릭할 시 pathname이 변경됩니다.
product 클릭으로 인해 변경가능한 pathname 범위: /products/0 ~ /products/11
09:23~10:54
ProductDetail 컴포넌트 설명
Route의 path에 '/products/:id'를 지정하면 pathname이 /products/0 이든 /products/1 이든 /products/2 이든 ProductDetail 컴포넌트가 렌더링됩니다. ProductDetail 입장에서 저 pathname 뒤에 붙는 숫자는 어떻게 읽어와야할까요?
Route의 path에 changable value를 넣었을 경우 (예시: <Route path =" /products/:id" />에서 :id가 changable value) 저 Route에 의해 렌더링 되는 컴포넌트 속에서는 pathname에 포함된 changableValue를 알아내기 위해 useParams() hook을 호출합니다.
*useParams는 v6와 차이가 없습니다.
id의 값을 구했으니 활용해 몇 번 Product인지 UI로 표현할 수 있겠죠.
ProductDetail 컴포넌트 내부에도 nested route가 사용되네요. 차이점이라면 '/about/offers'처럼 Route path에 값을 직접 적어준 것이 아니라 path라는 변수에 값을 담아 <Route path={`${path}/offers`} /> 형식으로 사용하고 있네요.
이유가 무엇일까요? 그것은 바로 ProductDetail 컴포넌트를 감싸는 Route에서 path에 changableValue를 사용했기 때문입니다. Products에서 ProductDetail 컴포넌트로 넘어올 때 Link를 클릭하잖아요? 이 각각의 Link들은 pathname '/products/0' ~ '/products/11' 즉 12개의 pathname으로의 변경 가능성을 만듭니다. 이것에 대해 일일이 대응하기 위해 ProductDetail 내부의 nested route에서 path를 다 적어줄 수는 없겠죠. 유동적인 pathname을 컴포넌트에서 대응하려면 useRouteMatch() hook을 사용해야합니다. 이 hook은 결과 값으로 path를 받을 수 있는데, 이 값이 현재 pathname이기 때문에 Offers를 감싸는 Route의 path에서 사용하는 것이죠.
예를들어 Products의 <Link to ="/products/0" />를 눌러 ProductDetail 컴포넌트로 왔다면 useRouteMatch의 path는 '/products/0'이 될테고 ProductDetail의 서브 Route의 path는 /products/0/offers가 되는 것이죠.
11:10~11:20
index.css 설명
css는 react-router와 관련된 내용이 아니므로 해당 구간은 설명을 Skip하겠습니다.(강사도 대충 설명하고 넘어가네요!)
11:20~12:35
방금까지 설명한 코드가 잘 동작하는지 브라우저에 띄워서 확인합니다. pathname이 바뀔 때마다 화면이 어떻게 바뀌는지, 각 pathname마다 어떤 컴포넌트가 띄워지도록 routing 되어있는지 복기하며 따라가보세요.
12:36~14:20
react-router-v6 실습을 위해 npm으로 library를 설치합니다.
react-router-v6는 v5와 호환되지 않는 부분이 있기 때문에 수정이 필요한데요, 버전 호환을 위한 코드 수정, v5, v6의 차이를 다루는 내용은 해당 영상의 유튜버 분의 다음 영상들을 토대로 다뤄보도록 하겠습니다.
해당 학습노트에서는 react router 버전6에서 redirect를 어떻게 구현하는지 소개합니다.
공식 문서: https://reactrouter.com/
00:50
react router 버전5에서 redirect를 구현하는 방법입니다.
*예상 시나리오: pathname이 '/redirect'인 page 접근 시 pathname '/about'인 page로 전환됨
*특정 pathname에 redirect 로직을 등록하는 이유는 가지각색이겠지만 그 중 대표적인 용도는 로그인 여부 검사입니다. 서비스를 이용하는 유저가 로그인을 했을 경우 특정 pathname에 접근하지 못하도록 사용하는 것이죠.