CHAPTER 15. Router

Intro

์ด ์žฅ์—์„œ๋Š” ๋งˆ์ง€๋ง‰ ๋ผ์šฐํ„ฐ API (v3)๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰, ๋ผ์šฐํ„ฐ ํŒจํ‚ค์ง€์˜ ๋ฒ„์ „ ๋ฒˆํ˜ธ๊ฐ€ 3.0.0์ด๊ณ  ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์˜ ๋ฒ„์ „ ๋ฒˆํ˜ธ๊ฐ€ 2.0.0 ์ธ ๊ฒฝ์šฐ์ด๋‹ค.

URL์„ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์ƒํƒœ๋กœ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋ถ๋งˆํฌ์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋Œ์•„์˜ฌ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ์›ํ•˜๋ฉด ์ „์ฒด์ ์œผ๋กœ ๋” ๋‚˜์€ ํ™˜๊ฒฝ์„ ์ œ๊ณต ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์ž‘์—…์„ ๋‹ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์„ ๋ผ์šฐํ„ฐ๋ผ๊ณ  ํ•˜๋ฉฐ, ๋ชจ๋“  ํ”„๋ ˆ์ž„ ์›Œํฌ์—๋Š” ๊ณ ์œ ํ•œ (๋˜๋Š” ๋ช‡ ๊ฐ€์ง€) ํ”„๋ ˆ์ž„ ์›Œํฌ๊ฐ€ ์žˆ๋‹ค.

Angular 2์˜ ๋ผ์šฐํ„ฐ๋Š” ์•ฑ์˜ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•˜๋Š” ์˜๋ฏธ์žˆ๋Š” URL์„ ํ—ˆ์šฉํ•˜๊ณ  ๊ฐ URL์— ๋Œ€ํ•ด ํŽ˜์ด์ง€์—์„œ ์–ด๋–ค ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ์‚ฝ์ž…ํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ฐ„๋‹จํžˆ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์น˜์ง€ ์•Š๊ณ  ๋ฐฑ์—”๋“œ ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ์š”์ฒญ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š๊ณ  ์ด ๋ชจ๋“  ๊ฒƒ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฝ”์–ด ํŒ€์—์„œ ngRoute๋ผ๋Š” ๋ชจ๋“ˆ๋กœ ๊ด€๋ฆฌํ•˜๋Š” AngularJS 1.x์— ์ด๋ฏธ ๋ผ์šฐํ„ฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋˜ํ•œ ๋งค์šฐ ๋‹จ์ˆœํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ฐ„๋‹จํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” OK์ด์ง€๋งŒ URL ๋‹น ๋‹จ์ผ๋ณด๊ธฐ ๋งŒ ํ—ˆ์šฉํ•˜๊ณ  ์ค‘์ฒฉ์ด ๋ถˆ๊ฐ€๋Šฅ ํ–ˆ๋‹ค. ์กฐํšŒ์ˆ˜๊ฐ€ ๋งŽ์€ ๋Œ€ํ˜• ์•ฑ์—์„œ ์ž‘์—…ํ•˜๋Š” ๋ฐ ์•ฝ๊ฐ„์˜ ์ œํ•œ์ด ์žˆ์—ˆ๋‹ค. ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์ •๋ง ํ›Œ๋ฅญํ•œ ์ผ์„ ํ•˜๊ณ  ์žˆ๋Š” ui-router๋ผ๊ณ  ํ•˜๋Š” ๋งค์šฐ ์ธ๊ธฐ์žˆ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ชจ๋“ˆ์ด ์žˆ์—ˆ๋‹ค.

Angular 2์˜ ํŒ€์€ ๊ฒฉ์ฐจ๋ฅผ ์ค„์ด๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜๊ณ  RouterModule์ด๋ผ๋Š” ์ƒˆ๋กœ์šด ๋ชจ๋“ˆ์„ ์ž‘์„ฑํ–ˆ๋‹ค. ์ด ๋ชจ๋“ˆ์€ ์šฐ๋ฆฌ์˜ ๋ชจ๋“  ์š”๊ตฌ๋ฅผ ์ถฉ์กฑ์‹œํ‚ฌ ๊ฒƒ์ด๋‹ค! ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ค‘ ์ผ๋ถ€๋Š” ์ •๋ง ํฅ๋ฏธ๋กœ์šธ ๊ฒƒ์ด๋‹ค.

En route

๋ผ์šฐํ„ฐ ์‚ฌ์šฉ์„ ์‹œ์ž‘ํ•ด๋ณด์ž. ์ด ๋ชจ๋“ˆ์€ ์ฝ”์–ด ํ”„๋ ˆ์ž„ ์›Œํฌ์— ํฌํ•จ๋˜์ง€ ์•Š๋Š” ์„ ํƒ์  ๋ชจ๋“ˆ์ด๋‹ค.

๋‹ค๋ฅธ ๋ชจ๋“ˆ์—์„œ ๋ณด์•˜ ๋“ฏ์ด ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ฃจํŠธ ๋ชจ๋“ˆ์— ๋ชจ๋“ˆ์„ ํฌํ•จํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” URL๊ณผ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐ„์˜ ๋งคํ•‘์„ ์ •์˜ํ•˜๋Š” ๊ตฌ์„ฑ์ด ํ•„์š”ํ•˜๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ app.routes.ts์™€ ๊ฐ™์€ ์ด๋ฆ„์˜ ์ „์šฉ ํŒŒ์ผ๋กœ ๊ตฌ์„ฑ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ตฌ์„ฑ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐฐ์—ด์„ ํฌํ•จํ•œ๋‹ค.

import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { RacesComponent } from './races/races.component';
export const ROUTES: Routes = [
  { path: '', component: HomeComponent },
  { path: 'races', component: RacesComponent }
];

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฃจํŠธ ๋ชจ๋“ˆ์—์„œ ๋ผ์šฐํ„ฐ ๋ชจ๋“ˆ์„ ๊ฐ€์ ธ ์™€์„œ ์ ์ ˆํ•œ ๊ตฌ์„ฑ์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•ด์•ผํ•œ๋‹ค.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { ROUTES } from './app.routes';
import { HomeComponent } from './home/home.component';
import { RacesComponent } from './races/races.component';
@NgModule({
  imports: [BrowserModule, RouterModule.forRoot(ROUTES)],
  declarations: [PonyRacerAppComponent, HomeComponent, RacesComponent],
  bootstrap: [PonyRacerAppComponent]
})
export class AppModule {
}

๋˜ํ•œ ๋ฃจํŠธ ๋ชจ๋“ˆ์˜ ์„ ์–ธ ์†์„ฑ์—์„œ ๋ผ์šฐํ„ฐ ๋ชจ๋“ˆ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ๋ณด์‹œ๋‹ค์‹œํ”ผ Routes๋Š” ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ด๋ฉฐ ๊ฐ ๊ฐ์ฒด๋Š” ๊ฒฝ๋กœ์ด๋‹ค. ๋ผ์šฐํŠธ ๊ตฌ์„ฑ์€ ๋ณดํ†ต ํ•œ ์Œ์˜ ๋“ฑ๋ก ์ •๋ณด์ด๋‹ค.

โ€ข path : ํƒ์ƒ‰์„ ํŠธ๋ฆฌ๊ฑฐ ํ•  URL โ€ข component : ์ดˆ๊ธฐํ™”๋˜๊ณ  ์‚ฝ์ž… ๋  ์ปดํฌ๋„ŒํŠธ

๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํŽ˜์ด์ง€์— ์‚ฝ์ž… ๋  ์œ„์น˜ ๋‹น์‹ ์€ ๊ถ๊ธˆ ํ•  ๊ฒƒ์ด๋‹ค, ๊ทธ๊ฒƒ์€ ์ข‹์€ ์งˆ๋ฌธ์ด๋‹ค. ์œ„์˜ ์˜ˆ์—์„œ RacesComponent์™€ ๊ฐ™์ด ์•ฑ์— ํฌํ•จ๋  ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ์ฃผ ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ…œํ”Œ๋ฆฟ์— ํŠน์ˆ˜ ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

์ด๊ฒƒ์€ ๋ฌผ๋ก  Angular ์ง€์‹œ๋ฌธ์ด๋‹ค. ์ด ์ง€์‹œ๋ฌธ์€ ํ˜„์žฌ ๊ฒฝ๋กœ์˜ ๊ตฌ์„ฑ ์š”์†Œ ํ…œํ”Œ๋ฆฟ์— ๋Œ€ํ•œ ์ž๋ฆฌ ํ‘œ์‹œ์ž ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์šฐ๋ฆฌ์˜ ์•ฑ ํ…œํ”Œ๋ฆฟ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

<header>
  <nav>...</nav>
</header>
<main>
  <router-outlet></router-outlet>
  <!-- the component's template will be inserted here-->
</main>
<footer>made with &lt;3 by Ninja Squad</footer>

ํƒ์ƒ‰ ํ•  ๋•Œ ๋ชจ๋“  ํ•ญ๋ชฉ (๋จธ๋ฆฌ๊ธ€, ๊ธฐ๋ณธ ๋ฐ ๋ฐ”๋‹ฅ ๊ธ€)์ด ์œ ์ง€๋˜๋ฉฐ ํ˜„์žฌ ๊ฒฝ๋กœ์™€ ์ผ์น˜ํ•˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ RouterOutlet ์ง€์‹œ๋ฌธ ๋ฐ”๋กœ ๋’ค์— ์‚ฝ์ž…๋œ๋‹ค.

Transforming data

Observable ๊ฐ์ฒด๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ฐ›๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ๋ณ€ํ˜• ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์žŠ์ง€ ๋งˆ์‹œ์˜ค. ๊ฒฝ์ฃผ ์ด๋ฆ„์˜ ๋ชฉ๋ก์„ ์›ํ•˜๋Š”๊ฐ€? ์ธ์ข…์„ ์š”์ฒญํ•˜๊ณ  ์ด๋ฆ„์„ ๋งคํ•‘ํ•˜๋ฉด ๋œ๋‹ค! ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด RxJS์— ๋Œ€ํ•œ mapoperator๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค. Angular ํŒ€์€ ์•ฑ์— ์ „์ฒด RxJS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํฌํ•จํ•˜๊ธฐ๋ฅผ ์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ช…์‹œ ์ ์œผ๋กœ ํ•„์š”ํ•œ ์—ฐ์‚ฐ์ž๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค.

import 'rxjs/add/operator/map';

์ด์ œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

http.get(`${baseUrl}/api/races`)
// extract json body
  .map(res => res.json())
  .subscribe(races => {
   // store the array of the races in the component
   this.races = races;
  });

์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ์ž‘์—…์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ „์šฉ ์„œ๋น„์Šค๋กœ ์ˆ˜ํ–‰๋œ๋‹ค. RaceService์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๋‹ค. RaceService๋Š” ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋œ ๊ณณ์ด๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚ด ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์„œ๋น„์Šค ๋ฐฉ๋ฒ•์„ ๊ตฌ๋… ํ•ด์•ผํ•˜๋ฉฐ ํ›„๋“œ ๋‚ด๋ถ€์—์„œ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์ง€ ๋ชปํ•œ๋‹ค.

raceService.list()
  .subscribe(races => {
   // store the array of the races in the component
   this.races = races;
  });

๋˜ํ•œ RxJS๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํŒจํ•œ ์š”์ฒญ์„ ๋ช‡ ๋ฒˆ ๋‹ค์‹œ ์‹œ๋„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

raceService.list()
  // if the request fails, retry 3 times
  .retry(3)
  .subscribe(races => {
   // store the array of the races in the component
   this.races = races;
  });

๋‹ค๋ฅธ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์–ด๋–ป๊ฒŒ ํƒ์ƒ‰ ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ๊ธ€์Ž„, ์ˆ˜๋™์œผ๋กœ URL์„ ์ž…๋ ฅํ•˜๊ณ  ํŽ˜์ด์ง€๋ฅผ ์ƒˆ๋กœ ๊ณ ์นจ ํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ๊ทธ๋‹ค์ง€ ํŽธ๋ฆฌํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” "๋กœ"๊ณ ์ „์ ์ธ "๋งํฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค. ์‹ค์ œ๋กœ ๋งํฌ๋ฅผ ํด๋ฆญํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํ•ด๋‹น URL์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋กœ๋“œํ•˜๊ณ  ์ „์ฒด Angular ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ์‹œ์ž‘ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ Angular์˜ ๋ชฉํ‘œ๋Š” ์ด๋Ÿฌํ•œ ํŽ˜์ด์ง€ ๋‹ค์‹œ ๋กœ๋“œ๋ฅผ ํ”ผํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‹จ์ผ ํŽ˜์ด์ง€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค. ๋ฌผ๋ก  ๋‚ด์žฅ๋œ ์†”๋ฃจ์…˜์ด ์žˆ๋‹ค.

ํ…œํ”Œ๋ฆฟ์—์„œ ์ด๋™ํ•˜๋ ค๋Š” ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ง€์‹œ๋ฌธ RouterLink๊ฐ€ ํฌํ•จ ๋œ ๋งํฌ๋ฅผ ์‚ฝ์ž… ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฃจํŠธ ๋ชจ๋“ˆ์ด RouterModule์„ ๊ฐ€์ ธ์™€ RouterModule์˜ ๋‚ด ๋ณด๋‚ธ ๋ชจ๋“  ์ง€์‹œ๋ฌธ์„ ๋ฃจํŠธ ๋ชจ๋“ˆ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด ์ง€์‹œ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. outerLink ์ง€์‹œ๋ฌธ์€ ์ด๋™ํ•˜๋ ค๋Š” ๊ฒฝ๋กœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ƒ์ˆ˜ ๋˜๋Š” ๊ฒฝ๋กœ ๋ฐ ํ•ด๋‹น ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฌธ์ž์—ด ๋ฐฐ์—ด์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด RacesComponent ํ…œํ”Œ๋ฆฟ์—์„œ HomeComponent๋กœ ์ด๋™ํ•˜๋ ค๋ฉด ์ƒ์ƒํ•ด ๋ณด๋ผ.

<a href="" routerLink="/">Home</a>
<!-- same as -->
<a href="" [routerLink]="['/']">Home</a>

๋Ÿฐํƒ€์ž„์— ๋งํฌ href๋Š” ๋ผ์šฐํ„ฐ์— ์˜ํ•ด ๊ณ„์‚ฐ๋˜๊ณ  /๋ฅผ ๊ฐ€๋ฆฌ ํ‚ต๋‹ˆ๋‹ค.

๊ฒฝ๋กœ์˜ ์„ ํ–‰ ์Šฌ๋ž˜์‹œ๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋ฉด, RouterLink๋Š” URL์„ ํ˜„์žฌ ๊ฒฝ๋กœ์— ์ƒ๋Œ€์ ์œผ๋กœ ์ž‘์„ฑํ•œ๋‹ค (๋‚˜์ค‘์— ๋ณด๊ฒŒ ๋  ๊ฒƒ์ฒ˜๋Ÿผ ์ค‘์ฒฉ ๋œ ๊ตฌ์„ฑ ์š”์†Œ์— ์œ ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค). ์Šฌ๋ž˜์‹œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ๊ธฐ๋ณธ URL์—์„œ URL์„ ๊ณ„์‚ฐํ•ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.

RouterLink ์ง€์‹œ๋ฌธ์€ RouterLinkActive ์ง€์‹œ๋ฌธ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ง€์‹œ๋ฌธ์€ ๋งํฌ๊ฐ€ ํ˜„์žฌ ๊ฒฝ๋กœ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒฝ์šฐ CSS ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ๋•Œ ์„ ํƒ๋œ ๋ฉ”๋‰ด ํ•ญ๋ชฉ์˜ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

<a href="" routerLink="/" routerLinkActive="selected-menu">Home</a>

๋ผ์šฐํ„ฐ ์„œ๋น„์Šค์™€ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ navigate ()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ์—์„œ ํƒ์ƒ‰ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ž‘์—… ํ›„ ์‚ฌ์šฉ์ž๋ฅผ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค.

export class RacesComponent {
  constructor(private router: Router) {
  }
  saveAndMoveBackToHome() {
   // ... save logic ...
   this.router.navigate(['']);
  }
}

์ด ๋ฉ”์„œ๋“œ๋Š” ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋กœ ํƒ์ƒ‰ ํ•  ๊ฒฝ๋กœ๊ฐ€์žˆ๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•œ๋‹ค. URL์— ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋™์  URL์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ponyies / the-pony- / the-pony-name-the-pony ๊ฐ™์€ ์ด ํŽ˜์ด์ง€์˜ ์˜๋ฏธ์žˆ๋Š” URL์ด ์žˆ๋Š” ์กฐ๋ž‘๋ง์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด ํŽ˜์ด์ง€๋ฅผ ํ‘œ์‹œํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜ ๋˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋™์  ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ๊ตฌ์„ฑ์—์„œ ๊ฒฝ๋กœ๋ฅผ ์ •์˜ํ•˜์ž

export const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'races', component: RacesComponent },
  { path: 'races/:raceId/ponies/:ponyId', component: PonyComponent }
];

๊ทธ๋Ÿฐ ๋‹ค์Œ routerLink๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์  ๋งํฌ๋ฅผ ์ •์˜ ํ•  ์ˆ˜ ์žˆ๋‹ค.

<a href="" [routerLink]="['/races', race.id, 'ponies', pony.id]">See pony</a>

๋ฌผ๋ก  ๋Œ€์ƒ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ฃผ์–ด์ง„ ์‹๋ณ„์ž๋กœ ํฌ๋‹ˆ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ํ‘œ์‹œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ด๋Ÿฌํ•œ ๋งค๊ฐœ ๋ณ€์ˆ˜์— ์•ก์„ธ์Šค ํ•ด์•ผ ํ•œ๋‹ค. ๋งค๊ฐœ ๋ณ€์ˆ˜ ๊ฐ’์„ ์–ป๊ธฐ ์œ„ํ•ด ๋ผ์šฐํ„ฐ๋Š” ActivatedRoute๋ผ๋Š” ๊ตฌ์„ฑ ์š”์†Œ์— ๋ฌผ๋ก  ์‚ฝ์ž… ํ•  ์ˆ˜์žˆ๋Š” ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด ๊ฐ์ฒด๋Š” ngOnInit ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋งค์šฐ ์œ ์šฉํ•œ ํ•„๋“œ ์ธ ์Šค๋ƒ… ์ƒท์ด ์žˆ๋‹ค. ์ด ํ•„๋“œ์—๋Š” params์—์žˆ๋Š” URL์˜ ๋ชจ๋“  ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค!

export class PonyComponent implements OnInit {
  pony: any;
  constructor(private ponyService: PonyService, private route: ActivatedRoute) {
  }
  ngOnInit() {
   const id = this.route.snapshot.params['ponyId'];
   this.ponyService.get(id).subscribe(pony => this.pony = pony);
  }
}

์ด ๊ณ ๋ฆฌ๋Š” ๋ณผ ์ˆ˜์žˆ๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ์—๋„ ์ข‹๋‹ค. ๋‹น์‹ ์ด ๋ฐœ๊ฒฌํ–ˆ์„์ง€๋„ ๋ชจ๋ฅด๋Š” ๊ฒƒ์— ๋”ฐ๋ผ, ์šฐ๋ฆฌ๋Š” ์Šค๋ƒ… ์‚ฌ์ง„์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ์Šค๋ƒ… ์ƒท์ด ์•„๋‹Œ ๋ฒ„์ „์ด ์žˆ๋Š”๊ฐ€? ๊ทธ๋ ‡๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ๋งค๊ฐœ ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ์„ ๊ตฌ๋… ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ๊ด€์ฐฐ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ params๋ผ๊ณ  ํ•œ๋‹ค.

์ด๊ฒƒ์€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค : ๋ผ์šฐํ„ฐ๋Š” ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์žฌ์‚ฌ์šฉ ํ•œ๋‹ค! ์šฐ๋ฆฌ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋‹ค์Œ ์กฐ๋ž‘๋ง์„ ๋ณผ ์ˆ˜์žˆ๋Š” "๋‹ค์Œ"๋ฒ„ํŠผ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ • ํ•ด ๋ณด์ž. ์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญ ํ•  ๋•Œ URL์€ / ponies / 1์—์„œ / ponies / 2๋กœ ๋ณ€๊ฒฝ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ผ์šฐํ„ฐ๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ค์‹œ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰, ngOnInit์ด ๋‹ค์‹œ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค! ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ํƒ์ƒ‰์„ ์œ„ํ•ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด params observable์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ์™ธ์—๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค!

export class PonyReusableComponent implements OnInit, OnDestroy {
  pony: any;
  paramsSubscription: Subscription;
  constructor(private ponyService: PonyService, private route: ActivatedRoute) {
  }
  ngOnInit() {
   this.paramsSubscription = this.route.params.subscribe(params => {
   const id = params['ponyId'];
   this.ponyService.get(id).subscribe(pony => this.pony = pony);
   });
  }
  ngOnDestroy() {
   this.paramsSubscription.unsubscribe();
  }
}

์—ฌ๊ธฐ์„œ๋Š” ActivatedRoute์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ด€์ฐฐ ๊ฐ€๋Šฅ ํ•ญ๋ชฉ์„ ๊ตฌ๋…ํ•˜๊ณ  ํ•„๋“œ์— ๊ตฌ๋…์„ ์ €์žฅํ•˜๋ฏ€๋กœ ๋‚˜์ค‘์— ngOnDestroy์—์„œ ๊ตฌ๋…์„ ์ทจ์†Œํ•˜์—ฌ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด์ œ URL์ด '/ ponies / 1'์—์„œ '/ ponies / 2'๋กœ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๊ด€์ฐฐ ํ•  ์ˆ˜์žˆ๋Š” ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ณ  ํ™”๋ฉด์— ํ‘œ์‹œ ํ•  ์˜ฌ๋ฐ”๋ฅธ ์กฐ๋ž‘๋ง์„ ๊ฐ€์ ธ์˜จ๋‹ค. params ์—…๋ฐ์ดํŠธ๋ฅผ ๊ตฌ๋… ํ•œ ๋‚ด๋ถ€์˜ PonyService ๊ฒฐ๊ณผ์— ๊ฐ€์ž…ํ•˜๋Š” ๋Œ€์‹  ์ข€๋” ์šฐ์•„ํ•œ switchMap ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

export class PonySwitchMapComponent implements OnInit, OnDestroy {
  pony: any;
  paramsSubscription: Subscription;
  constructor(private ponyService: PonyService, private route: ActivatedRoute) {
  }
  ngOnInit() {
   this.paramsSubscription = this.route.params
   .map(params => params['ponyId'])
   .switchMap(id => this.ponyService.get(id))
   .subscribe(pony => this.pony = pony);
  }
  ngOnDestroy() {
   this.paramsSubscription.unsubscribe();
  }
}

Reference URL

Last updated