앵귤러 라우트와 가드에 대한 이해

redjen·2024년 12월 1일
1

월간 딥다이브

목록 보기
11/11
post-thumbnail

앵귤러 라우터에 대해

https://angular.dev/guide/routing

SPA 애플리케이션에서 새 페이지를 가져오기 위해서는 서버와 통신하지 않고 특정 컴포넌트에 해당하는 화면의 일부를 표시하거나 숨겨서 사용자에게 보이는 내용을 바꾼다.

이러한 플로우에서는 사용자가 애플리케이션 작업을 수행할 때 개발자가 사전에 정의한 서로 다른 뷰들 사이에서 이동하게 된다.

앵귤러에서 하나의 뷰에서 다른 뷰로의 탐색을 시도하기 위해서는 Router 를 사용한다.

Router는 브라우저의 url을 뷰를 변경하라는 명령으로 해석하여 탐색을 가능하게 하는 역할을 한다.

라우터 제어

그리고 사용자가 주어진 라우트로 이동하는 것을 제어하기 위해서는 가드를 사용한다.

예를 들어 사용자가 로그인되었거나 약관에 동의한 경우에만 특정한 페이지를 보여주고 싶은 경우가 있다. 이런 경우 라우트 가드를 사용하여 해당 조건을 검사하고 라우트에 대한 접근을 제어할 수 있다.

라우트 가드

https://raghuvardhankaranam.medium.com/route-guards-in-angular-c2c01fe6167b

앞서 설명했던 것처럼 가드는 특정 조건에 기반한 접근을 허용하거나 거부할 수 있는 것처럼 공항의 보안 요원으로 비유할 수 있다.

앵귤러에서 가드는 라우트로 이동하기 전 단계별로 실행되는 스크립트들이다. 가드는 내비게이션으로 진행시킬 지, 리다이렉트할지 결정한다.

라우트 가드는 그 단계에 따라 여러 종류로 구분된다.

1. CanActivate

CanActivate 가드는 라우트가 활성화 될 수 있는지 체크한다.

사용자 인증처럼 특정 조건을 만족하지 않은 경우에 접근할 수 없도록 라우트를 보호하는 경우에 유용하다.

2. CanActivateChild

CanActivate 와 유사하지만 자식 라우트에 대해 동작한다. 다양한 자식 라우트를 가지는 기능 모듈에 유용하다.

예를 들어 '프로필 설정', '계정 설정', '개인정보 설정' 과 같은 다수의 자식 라우트를 가진 설정 페이지를 만들 때, CanActivateChild 가드를 사용하여 적절한 권한을 가진 사용자만 접근할 수 있도록 할 수 있다.

3. CanDeactivate

CanDeactivate 가드는 컴포넌트에서 나갈 때 동작한다. 사용자에게 저장되지 않은 변경 사항이 있을 때 경고하기 위해 종종 사용된다.

4. Resolve

Resolve 가드는 내비게이션이 종료되기 전에 데이터를 가져온다. 해당 데이터는 라우트 파라미터들을 populate 하기 위해 사용될 수 있다.

이커머스 애플리케이션에서 상품 상세 페이지가 있다고 가정해보자. Resolve 가드는 라우트가 활성화되기 전에 상품 상세 데이터를 먼저 가져와서 사용자가 비거나 완전히 로드되지 않은 페이지를 보지 않게 할 수 있다.

5. CanLoad

CanLoad는 모듈이 lazy load되어야 하는지 체크한다. 인가받지 않은 사용자가 애플리케이션의 일부를 다운로드하는 것을 방지하기 위해서 종종 사용된다.

복수 개의 가드를 사용한다면 어떨까?

이런 가드들은 라우트 설정에 딱 붙어서 해당 라우트로의 내비게이션 관련 이벤트가 발생할 때 같이 발동된다.

당연하게도 여러 개의 가드를 조합해서 사용할 수 있다.

CanActivate 가드를 여러 개 조합해서 이벤트 참여 페이지를 만든다고 가정해보자. 아래와 같은 가드를 조합해 관심사를 서로 분리할 수 있을 것이다.

  • 인가 받은 사용자인지 체크하는 가드
  • 이미 이벤트에 참여한 사용자인지 체크하는 가드

그런데 복수 개의 CanActivate 가드를 조합해서 사용하기 위해서는 조금 유의해야 하는 부분이 있다.

CanActivate 가드의 상세 동작

https://medium.com/angular-in-depth/new-in-angular-v7-1-updates-to-the-router-fd67d526ad05

너무 좋은 글이다..!

https://angular.dev/api/router/CanActivate?tab=api

interface CanActivate {
  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): MaybeAsync<GuardResult>;
}

CanActivateObservable<GuardResult> 또는 Promise<GuardResult> 를 리턴하는데, 이 GuardResult 타입은 boolean | UrlTree | RedirectCommand 로 구성되어 있다.

즉 복수개의 CanActivate 를 적용하게 되었을 때 리턴하는 GuardResult 타입에 따라 각 가드는 UrlTree 를 리턴할 수도, boolean 을 리턴할 수도 있고, RedirectCommand를 리턴할 수도 있는 것이다.

그리고 여러 개의 CanActivate 가 리턴하는GuardResult 의 상세 타입에 따라 분기가 결정된다.

UrlTreeboolean 타입 리턴에 대한 이해

먼저 UrlTree에 대해 알아보자.

앵귤러 라우터 내부에서 url 문자열은 UrlTree라고 불리는 구조로 표현되는데, Router 서비스의 parseUrl 메서드를 통해서 url을 손쉽게 UrlTree 로 변환할 수 있다.

이전에는 가드들이 boolean 타입만 리턴 가능했었다.

  • true 를 리턴하면 내비게이션을 진행
  • false를 리턴하면 내비게이션을 취소

UrlTree 도 리턴할 수 있게 변경되면서, 사용자가 인증 관련 가드 통과를 실패했을 때 바로 로그인 페이지로 리다이렉트 하도록 작성하는 것도 가능해졌다.

복수 개의 가드에는 우선순위가 존재한다

먼저 등장한 (인덱스가 0에 가까운) 가드의 우선순위가 높게 적용된다.

아래와 같이 라우터 설정이 되어 있는 경우를 가정해보자.

{ 
  path: '/member', 
  canActivate: [CanActivateGuardA, CanActivateGuardB], 
  children: [{
    // ... 
  }],
}
  • /member 라우트의 canActivate 절에 의해 자식 라우트의 가드가 동작하기 전에 CanActivateGuardACanActivateGuardB 가 먼저 수행된다.
  • CanActivateGuardACanActivateGuardB 보다 우선순위가 높다.
  • 따라서 가드 B가 UrlTree를 즉시 리턴하여도 가드 A가 resolve 될 때까지 대기한다.
  • 가드 A가 UrlTree를 리턴한다면 가드 B의 결과는 무시되고 해당 url로 내비게이션된다.
  • 가드 A가 false를 리턴한다면 가드 B의 결과는 무시되고 전체 내비게이션은 취소된다.
  • 가드 A가 true를 리턴한다면 가드 B가 리턴하는 UrlTree로 내비게이션된다.

https://github.com/angular/angular/blob/main/packages/router/test/operators/prioritized_guard_value.spec.ts

위 테스트 케이스에서 이를 좀 더 잘 알아볼 수 있다.

복수 개의 가드 적용 시 유의점

즉 아래와 같이 복수 개의 가드를 적용할 때에는 유의하여서 사용해야 한다.

  1. 가드 A에서 UrlTree를 즉시 리턴한다면 가드 B의 결과는 무시된다. 모든 가드의 결과를 조합하고 싶다면 앞선 가드가 boolean 타입을 리턴하도록 작성해야 한다.
  2. 가드 A가 boolean 타입을 리턴하더라도 false를 리턴한다면 가드 B의 결과는 무시되고 내비게이션은 취소된다.
  3. 복수 개의 가드는 모두 parallel 하게 실행되지만 우선순위가 존재하기 때문에 가령 동일한 ajax 요청을 한다면 시점에 따라 데이터의 불일치가 발생할 수 있다. 따라서 가드 조합 시에 이를 유의해야 한다.

TL;DR

  • 앵귤러 라우터는 CanActivate, CanActivateChild, CanDeactivate, Resolve 와 같은 유형의 가드를 사용하여 특정 라우트에 대한 내비게이션이 발생하기 전에 이를 제어할 수 있다.
  • CanActivate 가드는 parallel 하게 동작하지만 우선순위가 존재한다.
  • 따라서 우선순위가 높은 가드가 실행이 완료되지 않으면 우선순위가 낮은 가드가 완료되더라도 내비게이션의 가불 판정은 유예된다.
  • 우선순위가 높은 CanActivate 가드가 false, UrlTree를 리턴한다면 우선순위가 낮은 가드의 실행 결과는 무시된다.
profile
make maketh install

0개의 댓글

관련 채용 정보