RouterLink 디렉티브는 Angular에서 선언적으로 내비게이션을 구성하는 방식입니다.
표준 앵커 엘리먼트(<a>)를 Angular 라우팅 시스템과 자연스럽게 연결해서 사용할 수 있습니다.
RouterLink 사용하기
href 어트리뷰트가 있는 일반적인 앵커 엘리먼트 <a> 대신 RouterLink 디렉티브에 경로를 지정하면 Angular 라우팅을 사용할 수 있습니다.
import {RouterLink} from '@angular/router';
import {Component} from '@angular/core';
@Component({
template: `
<nav>
<a routerLink="/user-profile">User profile</a>
<a routerLink="/settings">Settings</a>
</nav>
`,
imports: [RouterLink],
...
})
export class App {}
절대 링크와 상대 링크 사용하기
Angular 라우팅의 상대 URL을 사용하면 현재 라우팅 규칙 위치를 기준으로 이동할 경로를 정의할 수 있습니다.
프로토콜(예: http://)과 루트 도메인(예: google.com)을 포함한 전체 경로를 지정하는 절대 URL과는 다릅니다.
<!-- 절대 URL -->
<a href="https://www.angular.dev/essentials">Angular Essentials Guide</a>
<!-- 상대 URL -->
<a href="/essentials">Angular Essentials Guide</a>
첫 번째 예제는 핵심 가이드 페이지의 전체 경로에 프로토콜(https://)과 루트 도메인(angular.dev)을 명시합니다.
반면 두 번째 예제는 사용자가 이미 /essentials에 해당하는 올바른 루트 도메인에 있다고 가정합니다.
일반적으로 상대 URL을 권장합니다. 라우팅 계층에서 절대 위치를 알 필요가 없기 때문에 여러 애플리케이션에서 유지보수하기 쉽습니다.
상대 URL의 동작 방식
Angular 라우팅에서는 문자열과 배열, 두 가지 문법으로 상대 URL을 정의할 수 있습니다.
<!-- 사용자를 /dashboard로 이동시킵니다. -->
<a routerLink="dashboard">Dashboard</a>
<a [routerLink]="['dashboard']">Dashboard</a>
참고: 상대 URL을 정의할 때는 문자열을 전달하는 방식이 가장 흔합니다.
상대 URL에 동적 파라미터를 지정해야 한다면 배열 문법을 사용하세요.
<a [routerLink]="['user', currentUserId]">Current User</a>
Angular 라우팅에서는 상대 경로 앞에 슬래시(/)가 있는지에 따라 현재 URL을 기준으로 할지, 루트 도메인을 기준으로 할지도 지정할 수 있습니다.
예를 들어 사용자가 example.com/settings에 있다면 상황에 따라 다음과 같이 상대 경로를 정의할 수 있습니다.
<!-- /settings/notifications로 이동합니다. -->
<a routerLink="notifications">Notifications</a>
<a routerLink="/settings/notifications">Notifications</a>
<!-- /team/:teamId/user/:userId로 이동합니다. -->
<a routerLink="/team/123/user/456">User 456</a>
<a [routerLink]="['/team', teamId, 'user', userId]">Current User</a>
코드로 라우팅 규칙 사이 이동하기
RouterLink는 템플릿에서 선언적으로 내비게이션을 처리합니다.
로직, 사용자 동작, 애플리케이션 상태에 따라 이동해야 하는 경우에는 Angular가 제공하는 코드 기반 내비게이션을 사용할 수 있습니다.
Router를 주입하면 TypeScript 코드에서 동적으로 라우팅 규칙 사이를 이동하고, 파라미터를 전달하고, 내비게이션 동작을 제어할 수 있습니다.
router.navigate()
router.navigate() 메서드에 URL 경로 배열을 지정하면 코드로 라우팅 규칙 사이를 이동할 수 있습니다.
import {Router} from '@angular/router';
import {Component, inject} from '@angular/core';
@Component({
selector: 'app-dashboard',
template: ` <button (click)="navigateToProfile()">View Profile</button> `,
})
export class AppDashboard {
private router = inject(Router);
navigateToProfile() {
// 기본 내비게이션
this.router.navigate(['/profile']);
// 라우팅 규칙 파라미터 사용
this.router.navigate(['/users', userId]);
// 쿼리 파라미터 사용
this.router.navigate(['/search'], {
queryParams: {category: 'books', sort: 'price'},
});
// 매트릭스 파라미터 사용
this.router.navigate(['/products', {featured: true, onSale: true}]);
}
}
router.navigate()는 간단한 라우팅부터 복잡한 라우팅까지 지원합니다.
라우팅 규칙 파라미터와 쿼리 파라미터를 전달하고 내비게이션 동작을 제어할 수 있습니다.
relativeTo 옵션을 사용하면 라우팅 트리에서 컴포넌트가 있는 위치를 기준으로 동적 이동 경로를 구성할 수도 있습니다.
import {Router, ActivatedRoute} from '@angular/router';
import {Component, inject} from '@angular/core';
@Component({
selector: 'app-user-detail',
template: `
<button (click)="navigateToEdit()">Edit User</button>
<button (click)="navigateToParent()">Back to List</button>
`,
})
export class UserDetail {
private route = inject(ActivatedRoute);
private router = inject(Router);
// 형제 라우팅 규칙으로 이동합니다.
navigateToEdit() {
// 출발: /users/123
// 도착: /users/123/edit
this.router.navigate(['edit'], {relativeTo: this.route});
}
// 부모로 이동합니다.
navigateToParent() {
// 출발: /users/123
// 도착: /users
this.router.navigate(['..'], {relativeTo: this.route});
}
navigateToList() {
// Angular는 명령 배열을 현재 라우팅 규칙 기준의 단일 이동 경로로 해석합니다.
// 출발: /users/123
// 결과: /users/list
this.router.navigate(['..', 'list'], {relativeTo: this.route});
}
}
여러 단계 위로 이동할 때는 모든 .. 세그먼트를 명령 배열의 첫 번째 항목에 넣어야 합니다.
라우터는 첫 번째 명령 문자열에서만 ..를 해석하며, 그 뒤의 배열 항목은 일반 경로 세그먼트로 처리합니다.
// 출발: /team/123/users/456
// 결과: /team/123/settings
this.router.navigate(['../../settings'], {relativeTo: this.route});
relativeTo를 사용할 때는 첫 번째 명령 앞에 /를 붙이지 마세요.
맨 앞에 /가 있으면 절대 경로 내비게이션이 되며 relativeTo는 완전히 무시됩니다.
// 출발: /team/123/users/456
// 결과: /team/123/users/456/edit
this.router.navigate(['edit'], {relativeTo: this.route});
// 출발: /team/123/users/456
// 맨 앞에 '/'가 있으면 절대 경로로 이동하며 relativeTo는 무시됩니다.
// 결과: /edit
this.router.navigate(['/edit'], {relativeTo: this.route});
router.navigateByUrl()
router.navigateByUrl() 메서드는 세그먼트 배열 대신 URL 경로 문자열로 직접 내비게이션을 실행합니다.
전체 URL 경로가 있고 절대 경로로 이동해야 할 때 적합하며, 특히 외부에서 받은 URL이나 딥 링크를 처리할 때 유용합니다.
// 기본 라우팅 규칙 내비게이션
router.navigateByUrl('/products');
// 중첩 라우팅 규칙으로 이동합니다.
router.navigateByUrl('/products/featured');
// 파라미터와 프래그먼트가 있는 전체 URL
router.navigateByUrl('/products/123?view=details#reviews');
// 쿼리 파라미터와 함께 이동합니다.
router.navigateByUrl('/search?category=books&sortBy=price');
// 매트릭스 파라미터 사용
router.navigateByUrl('/sales-awesome;isOffer=true;showModal=false');
히스토리의 현재 URL을 교체해야 한다면 navigateByUrl에 replaceUrl 옵션이 있는 설정 객체를 전달할 수도 있습니다.
// 히스토리의 현재 URL을 교체합니다.
router.navigateByUrl('/checkout', {
replaceUrl: true,
});
주소 표시줄에 다른 URL 표시하기
navigateByUrl에 browserUrl 옵션을 전달하면 라우팅 규칙 매칭에 사용하는 URL과 다른 URL을 브라우저 주소 표시줄에 표시할 수 있습니다.
사용자가 처음 방문하려던 URL을 유지하면서 다른 라우팅 규칙(예: 오류 페이지)으로 리다이렉트하고 싶을 때 유용합니다.
router.navigateByUrl('/not-found', {browserUrl: '/products/missing-item'});
Angular는 /not-found 라우팅 규칙으로 이동해서 렌더링하지만, 브라우저 주소 표시줄에는 /products/missing-item이 표시됩니다.
참고: browserUrl은 브라우저 주소 표시줄에 표시되는 내용에만 영향을 줍니다.
RouterLink로 브라우저 URL 조정하기
RouterLink 디렉티브도 browserUrl 입력 프로퍼티를 지원합니다.
따라서 링크를 클릭했을 때 Angular가 이동하는 라우팅 규칙과 별개로 브라우저 주소 표시줄에 표시할 URL을 제어할 수 있습니다.
<!-- /dashboard로 이동하지만 주소 표시줄에는 /home을 표시합니다. -->
<a [routerLink]="['/dashboard']" [browserUrl]="'/home'">Go to Dashboard</a>
더 동적인 처리가 필요하면 UrlTree를 바인딩할 수도 있습니다.
import {Component, inject} from '@angular/core';
import {Router, RouterLink, UrlTree} from '@angular/router';
@Component({
template: `
<a [routerLink]="['/products', product.id]" [browserUrl]="displayUrl">
{{ product.name }}
</a>
`,
imports: [RouterLink],
})
export class ProductList {
private router = inject(Router);
product = {id: 42, name: 'Widget'};
// 주소 표시줄에 표시할 UrlTree를 생성합니다.
displayUrl: UrlTree = this.router.createUrlTree(['/products', 'widget']);
}
다음 단계
라우팅 규칙 상태를 읽는 방법을 알아보고, 변화와 컨텍스트에 반응하는 컴포넌트를 만들어 보세요.