
Vue 애플리케이션에서 Vue Router는 URL과 화면을 연결하는 기능을 넘어 로그인 확인, 권한 제어, 데이터 준비, 뒤로 가기 경험을 결정합니다. 라우터 가드에 모든 업무 로직을 몰아넣으면 이동이 멈추거나 무한 리다이렉트가 발생하기 쉽습니다. 또한 프런트엔드에서 메뉴를 숨기는 것만으로는 보안을 보장할 수 없습니다. 안정적인 라우팅의 핵심은 화면 접근 정책과 서버 권한 검사를 분리하고 이동 흐름을 예측 가능하게 만드는 것입니다.
라우트 이름과 동적 경로 사용하기
문자열 URL을 여러 컴포넌트에 직접 쓰면 경로가 바뀔 때 수정 범위가 커집니다. 각 라우트에 안정적인 name을 부여하고 router.push({ name: 'user-detail', params: { id } })처럼 이동하면 의도가 명확합니다. params는 경로 정의에 있는 동적 구간과 일치해야 하며 선택적인 검색 조건은 query로 분리합니다. 사용자 입력을 경로에 넣을 때는 라우터가 제공하는 인코딩 방식을 사용합니다.
중첩 라우트로 레이아웃 표현하기
관리자 영역처럼 공통 메뉴와 하위 화면이 있다면 중첩 라우트와 RouterView로 구조를 표현할 수 있습니다. 부모 경로와 자식 경로의 절대·상대 작성 방식에 따라 최종 URL이 달라지므로 규칙을 통일합니다. 레이아웃 컴포넌트가 사용자 데이터를 매번 요청하지 않도록 상태의 수명과 캐시 정책을 정해야 합니다.
meta에 접근 정책을 선언하기
각 라우트의 meta에 requiresAuth, 필요한 역할, 화면 제목 같은 메타데이터를 선언하면 전역 가드가 일관된 정책을 적용할 수 있습니다. 문자열 역할 이름을 곳곳에 직접 쓰지 말고 상수나 권한 모델로 관리합니다. 여러 중첩 라우트가 매칭되므로 최종 라우트 하나만 보지 말고 matched 배열의 정책을 어떻게 합칠지 결정합니다.
보안 원칙: Vue Router 가드는 사용자 경험을 위한 1차 제어일 뿐이며 데이터 조회와 변경 권한은 서버 API가 반드시 다시 검사해야 합니다.
로그인 리다이렉트와 무한 반복 막기
로그인이 필요한 화면에 비로그인 사용자가 접근하면 로그인 화면으로 보내고 원래 목적지를 안전하게 보관할 수 있습니다. 로그인 성공 후 돌아갈 경로는 앱 내부의 허용된 경로인지 검증해야 외부 사이트로 보내는 오픈 리다이렉트 문제가 생기지 않습니다. 로그인 라우트 자체에는 인증 요구를 적용하지 않고, 이미 로그인한 사용자의 처리 규칙을 명시해 무한 이동을 막습니다.
가드 체크포인트
- 모든 코드 경로에서 허용 또는 리다이렉트를 반환합니다.
- 인증 초기화가 끝나기 전에 잘못 판단하지 않습니다.
- 네트워크 실패와 미인증을 구분합니다.
- 같은 위치로 반복 리다이렉트하지 않습니다.
- 가드 안에서 사용자에게 보이지 않는 긴 작업을 피합니다.
인증 상태 복원과 첫 이동
앱을 새로고침하면 Pinia의 메모리 상태는 초기화될 수 있습니다. 전역 가드가 실행되기 전에 세션 확인이 필요하다면 인증 스토어에 한 번만 실행되는 초기화 Promise를 두고 가드가 이를 기다리도록 설계할 수 있습니다. 여러 이동이 동시에 초기화를 호출해도 API 요청은 하나만 나가게 합니다. 토큰이 있다고 로그인으로 단정하지 말고 만료와 서버 세션 상태를 확인합니다.
컴포넌트 재사용과 매개변수 변경
/users/1에서 /users/2로 이동하면 같은 컴포넌트 인스턴스가 재사용될 수 있어 mounted 훅이 다시 실행되지 않습니다. route params를 watch하거나 onBeforeRouteUpdate를 사용해 새 ID의 데이터를 가져옵니다. 이전 요청은 취소하고 응답이 현재 ID와 일치하는지 확인해야 느린 응답이 다른 사용자의 화면을 덮지 않습니다.
이탈 방지 가드의 한계
편집 중인 폼에서 이동할 때 onBeforeRouteLeave로 확인 창을 보여줄 수 있습니다. 단순히 폼 객체가 존재하는지가 아니라 최초 값과 달라졌는지 판단해야 합니다. 저장 성공 후에는 변경 플래그를 초기화하고, 브라우저 탭 닫기에는 beforeunload가 별도로 필요할 수 있습니다. 커스텀 대화상자는 비동기 이동과 중복 클릭을 정확히 처리해야 합니다.
지연 로딩과 오류 화면
라우트 컴포넌트를 동적 import로 불러오면 초기 번들을 줄일 수 있습니다. 네트워크 오류나 새 배포로 이전 청크가 사라진 상황을 고려해 실패 화면과 한정된 새로고침 정책을 제공합니다. 모든 화면을 지나치게 잘게 쪼개면 작은 요청이 많아질 수 있으므로 기능 화면 단위가 적절합니다. 자주 이동할 가능성이 높은 라우트는 사용자 행동을 기준으로 미리 불러올 수 있습니다.
스크롤과 접근성
라우트 이동 뒤 새 페이지의 스크롤을 위로 올리고, 뒤로 가기에서는 이전 위치를 복원하는 정책을 scrollBehavior에 구현할 수 있습니다. 화면 제목을 갱신하고 주요 콘텐츠로 초점을 이동하면 키보드와 스크린 리더 사용자가 화면 전환을 인지하기 쉽습니다. 단순히 URL만 바뀌고 초점이 기존 버튼에 남으면 접근성이 나빠집니다.
테스트 순서
- 비로그인 사용자의 보호 화면 접근을 시험합니다.
- 로그인 후 원래 내부 경로로 돌아가는지 확인합니다.
- 권한이 없는 사용자의 메뉴와 직접 URL 접근을 검사합니다.
- params만 바뀌는 이동에서 데이터가 갱신되는지 봅니다.
- 느린 인증 확인과 네트워크 실패를 재현합니다.
- 수정 중 이탈과 저장 후 이동을 테스트합니다.
- 뒤로 가기, 스크롤 복원과 키보드 초점을 확인합니다.
라우터 가드는 간결할수록 진단하기 쉽습니다. 인증 상태 확인은 스토어, 실제 권한 판단은 서버, 화면별 데이터 요청은 컴포넌트나 전용 composable에 두고 가드는 이동 허용 여부를 조합합니다. 이 책임 분리를 지키면 라우트가 늘어나도 권한과 사용자 이동을 안정적으로 관리할 수 있습니다.
한 줄 요약: Vue Router는 선언적인 meta와 간결한 가드, 서버 권한 재검사, 매개변수·취소 처리를 함께 설계해야 안전합니다.