내가 했던 라우팅 작업을 요약하자면 다음과 같다. (써놓고 보니 별거 없다.)
React 자체에서 따로 route 기능을 제공하지 않기 때문에 react-router-dom이라는 라이브러리의 도움을 받았다.
유저의 현재 상태에 따라 접근 가능한 경로와, 그렇지 않은 경로가 결정된다. 아래의 예시를 보면 더 명확하다.
위 같은 경우를 처리하기 위해서 react-router-dom 라이브러리에 있는 Route를 wrapping 하는 컴포넌트(?)를 작성하였다. 역시나 구글은 모든 것을 다 알려준다.
PrivateRoute
export const PrivateRoute = ({ component: ComponentName, ...rest }: RouteModel) => {
const { id } = useAuth(); // 유저 정보 뽑아오는 부분
return <Route {...rest} render={(props) => (id ? <ComponentName {...props} /> : <Redirect to="/"/> )} />;
};
PrivateRoute같은 경우는 자신의 로그인 정보가 있어야만 접근 가능한 경로에 적용해 주었다.
component : Route에서 경로가 맞으면 보여줄 컴포넌트를 입력하는 부분이다.
...rest : 나머지 props들
useAuth : redux store에서 자신의 정보를 뽑아주는 역할을 하는 hook
흐름은 간단하다.
PublicRoute
export const PublicRoute = ({ component: ComponentName, restricted = false, ...rest }: RouteModel) => {
const { id } = useAuth();
return <Route {...rest} render={(props) => (id && restricted ? <Redirect to="/" /> : <ComponentName {...props} />)} />;
};
PrivateRoute와 다르게, 하나의 restricted라는 prop을 하나 더 받는다. 그 이유는 PublicRoute로 접근하는 경우는 좀 더 많은 경우가 존재하기 때문이다. 로그인 페이지의 예를 들어보자.
위와 같은 경우처럼, 로그인을 한 여부에 따라 접근할 수 없는 경우가 있기 때문에 restricted라는 props를 받아, 로그인 한 경우 접근을 제한시키도록 설정했다.
새로운 경로를 추가할 때, Switch가 url이 Route와 가장 첫번째로 매치되는 경우를 렌더링하다보니, 꽤나 자주 App.tsx 부분을 손대야 하는 경우가 생겼다.
사실 제대로 설정안하고, 이리저리 바꾸면 제대로 동작해서 그냥 했을지도...
이 참에 어떻게 해야 제대로 동작하는 지 정리해보고자 한다.
근데 아무리 찾아봐도 뭘 기준으로 매칭을 하는지 전혀 알 수가 없었다. 공식문서문서에서 이리저리 읽어보다가 간신히 발견한 것 같다.
아래의 링크를 참조하였다. 아흑흑... 다른거도 해야해서 잠시 패쓰...
정신을 다시 차리고서,어떤 기준으로 path를 match하는지 너무 궁금해졌다. 단순히 정규표현식으로만 match를 한다면 '/about/:id'와 '/about'은 매치가 되지 않아야 할텐데...
한참동안 정규표현식의 늪에 빠져있다가, 역시 공식문서에는 답이 있더라.
Route.js코드를 까보니, 그 안에 matchPath라는 부분이 있었다.즉, 새로운 url로 접근을 할 때마다 모든 Route마다 matchPath를 거쳐서 match되는 것이 존재하면, 그 부분을 rendering 하는 것이었다.
이제 그걸 Switch로 막는 것이고.
그렇기 때문에 가장 nested된 url을 상단에 두고, 하위로 내려갈 수록 점점 root와 근접해지는 방식으로 순서를 두면 될 듯 싶다.