Conversation
🎨 Storybook 배포 완료PR 작성자: @jyeon03 |
There was a problem hiding this comment.
저는 publicRoutes, privateRoutes로 라우트를 분리하는 방식이 유지보수성과 가독성 측면에서 더 낫다고 생각해요 !!
인증 필요/불필요라는 기준이 명확한 도메인 규칙이기 때문에 오히려 지금처럼 라우트를 한 배열에 섞어두면 규모가 커질수록 분류 비용과 실수 가능성이 크다고 생각합니다 !
특히 새로운 페이지 추가 시에 이 페이지가 인증이 필요한가?를 판단하고 그 결과에 따라 private/public 중 한 곳에만 넣으면 되기 때문에 변경 범위가 작고 리뷰 포인트도 명확해진다고 생각하는데 지연님의 생각은 어떨까요 ?
또한 SSoT 위배 라고 말씀해주셨는데 분리 자체는 중복 정의가 아니라 책임 분리에 가깝다고 생각해요 !
SSoT가 실제로 깨지는 케이스는 이 페이지가 private인지 여부와 같은 동일한 규칙이 routes 파일/guard/메뉴 매핑 등 여러 곳에서 중복으로 관리되어 불일치가 생길 때인데 현재 구조는 접근 정책을 privateRoutes/publicRoutes라는 한 기준으로 모아두는 형태라 오히려 정책을 추적하기 쉽다고 생각합니다 !!
| Component: PublicLayout, | ||
| children: publicRoutes, | ||
| Component: GuardedPublicLayout, | ||
| children: routes.filter((r) => !r.auth), |
There was a problem hiding this comment.
이런식으로 filter 함수를 사용하면 가독성이 떨어질 것 같아요 ! routes 파일을 다시 분리하게 된다면 해결될 문제 같아요 !
| const { pathname } = useLocation(); | ||
|
|
||
| const publicOnlyPaths: string[] = [ | ||
| PATH.LANDING, | ||
| PATH.LOGIN, | ||
| PATH.LOGIN_CALLBACK, | ||
| ]; | ||
|
|
||
| if (accessToken && publicOnlyPaths.includes(pathname)) { |
There was a problem hiding this comment.
const GuardedPrivateLayout = () => (
<PrivateRouteGuard>
<PrivateLayout />
</PrivateRouteGuard>
);PublicRouteGuard를 PublicLayout 전체에 감싸면
PublicLayout 아래에 있는 모든 라우트가 public 영역이 되고 있기 때문에
현재 pathname이 publicOnlyPaths에 해당하나를 검사할 이유가 없을 것 같아요 !!
📌 Summary
분산되어 있던 라우팅 구조를 중앙에서 관리하도록 단일화하고, 불완전했던 접근 제어 로직을 개선하여 유지보수성과 확장성 을 향상시키는 리팩토링 작업을 진행했습니다!!!!!
📚 Tasks
🔍 Describe
왜 이 리팩토링이 필요했나??미인증 사용자 차단과인증된 사용자 처리라는 여러 책임을 가지려 했으나, 후자를 guard에서 제대로 처리하지 못해 로직에 허점이 존재했습니다.어떻게 재설계했나??모든 경로 설정을 routes/index.ts 단일 파일로 통합하여 SSoT을 확보했습니다. 각 경로에 auth: true 메타데이터를 추가하여 인증 필요 여부를 선언적으로 명시하도록 변경했습니다.
변경 후
단일 책임 원칙에 따라, 하나의 복잡한 AuthGuard를 두 개의 명확한 책임을 가진 PrivateRouteGuard와 PublicRouteGuard로 분리했습니다.
변경 전
메인 라우터가 중앙화된 routes 배열을 동적으로 필터링하여 Public/Private 경로 그룹을 자동으로 구성하도록 수정했습니다.
변경 전
👀 To Reviewer
state={{ from: location }}패턴을 사용하면 로그인 후 원래 접근하려던 경로로 복귀시키는 UX를 구현해보면 어떨까싶어요! 추후 딥링크 대응이나 기획 변경 가능성을 고려하면 Guard에서 이 정보를 함께 전달하는 구조도 한 가지 방법일 것 같다는 생각이 들었습니당 🥸