웹사이트 검색

Angular 라우터에서 경로 확인자를 사용하는 방법


소개

API에서 데이터 검색 및 표시를 처리하는 한 가지 방법은 사용자를 구성 요소로 라우팅한 다음 해당 구성 요소의 ngOnInit 후크에서 서비스의 메서드를 호출하여 필요한 데이터를 가져오는 것입니다. 데이터를 가져오는 동안 아마도 구성 요소가 로드 표시기를 표시할 수 있습니다.

새 경로로 이동하기 전에 데이터를 가져올 수 있는 경로 확인자를 사용하는 또 다른 방법이 있습니다.

사용할 수 있는 API 중 하나는 Hacker News API입니다. Hacker News는 링크를 공유하고 토론하기 위한 웹 사이트입니다. API를 사용하여 가장 인기 있는 게시물을 검색하고 개별 게시물에 대한 정보를 표시할 수 있습니다.

이 자습서에서는 수집된 데이터를 표시하는 경로로 이동하기 전에 Hacker News API에서 데이터를 가져오는 경로 확인자를 구현합니다.

전제 조건

이 자습서를 완료하려면 다음이 필요합니다.

  • Node.js를 로컬에 설치했습니다. Node.js를 설치하고 로컬 개발 환경을 만드는 방법에 따라 수행할 수 있습니다.
  • Angular 프로젝트 설정에 어느 정도 익숙합니다.

이 튜토리얼은 Node v15.3.0, npm v6.14.9, @angular/core v11.0.1, @angular/common v11에서 확인되었습니다. 0.1, @angular/router v11.0.1 및 rxjs v6.6.0.

1단계 - 프로젝트 설정

이 자습서의 목적을 위해 @angular/cli로 생성된 기본 Angular 프로젝트에서 빌드합니다.

  1. npx @angular/cli new angular-route-resolvers-example --style=css --routing --skip-tests

이렇게 하면 스타일이 "CSS\("Sass\, Less\ 또는 "Stylus\가 아님)로 설정되고 라우팅이 활성화되고 테스트를 건너뛰는 새 Angular 프로젝트가 구성됩니다.

새로 생성된 프로젝트 디렉토리로 이동합니다.

  1. cd angular-route-resolvers-example

이 시점에서 @angular/router가 있는 새 Angular 프로젝트가 있습니다.

2단계 - 리졸버 구축

2초 지연 후 문자열을 반환하는 리졸버를 구현하는 것으로 시작하겠습니다. 이 작은 개념 증명은 대규모 프로젝트에 적용할 수 있는 배선 경로의 기본 사항을 탐색하는 데 도움이 될 수 있습니다.

먼저 고유한 파일에 해결 프로그램에 대한 별도의 클래스를 만듭니다.

  1. ./node_modules/@angular/cli/bin/ng generate resolver news

이것은 @angular/cli를 사용하여 news라는 리졸버를 생성합니다:

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';

import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class NewsResolver implements Resolve<Observable<string>> {
  resolve(): Observable<string> {
    return of('Route!').pipe(delay(2000));
  }
}

Angular 라우터의 Resolve 인터페이스를 구현하려면 클래스에 resolve 메서드가 있어야 합니다. 해당 메서드에서 반환되는 모든 것이 확인된 데이터가 됩니다.

이 코드는 2초 지연 후 문자열을 래핑하는 관찰 가능 항목을 반환합니다.

3단계 - 경로 구성

두 가지 경로를 경험하려면 두 가지 새로운 구성 요소가 필요합니다. 은 랜딩 페이지가 될 것입니다. 그리고 top에는 Hacker News API의 인기 게시물이 표시됩니다.

먼저 @angular/cli를 사용하여 home 구성 요소를 생성합니다.

  1. ./node_modules/@angular/cli/bin/ng generate component home

그런 다음 @angular/cli를 사용하여 top 구성 요소를 생성합니다.

  1. ./node_modules/@angular/cli/bin/ng generate component top

이제 리졸버를 포함하도록 라우팅 모듈을 설정할 수 있습니다.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { NewsResolver } from './news.resolver';

import { TopComponent } from './top/top.component';
import { HomeComponent } from './home/home.component';

const routes: Routes = [
  {
    path: '',
    pathMatch: 'full',
    component: HomeComponent
  },
  {
    path: 'top',
    component: TopComponent,
    resolve: { message: NewsResolver }
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

리졸버가 서비스처럼 제공되고 경로 정의와 함께 리졸버를 포함하는 방법에 주목하십시오. 여기서 확인된 데이터는 message 키 아래에서 사용할 수 있습니다.

4단계 - 구성 요소에서 해석된 데이터에 액세스

구성 요소에서 ActivatedRoutesnapshot 개체의 data 속성을 사용하여 확인된 데이터에 액세스할 수 있습니다.

import { Component, OnInit } from '@angular/core';

import { ActivatedRoute } from '@angular/router';

@Component({ ... })
export class TopComponent implements OnInit {
  data: any;

  constructor(private route: ActivatedRoute) {}

  ngOnInit(): void {
    this.data = this.route.snapshot.data;
  }
}

이제 구성 요소에서 다음과 같이 Route! 메시지에 액세스할 수 있습니다.

<p>The message: {{ data.message }}</p>

이 시점에서 애플리케이션을 컴파일할 수 있습니다.

  1. npm start

그리고 웹 브라우저에서 localhost:4200/top을 방문하세요.

Output
The message: Route!

데이터가 먼저 해결되기 때문에 이제 2초 지연이 있는 상단 경로로 이동할 때 관찰할 것입니다.

5단계 - API에서 데이터 확인

실제로 API에서 일부 데이터를 가져와서 좀 더 실감나게 만들어 봅시다. 여기에서 Hacker News API에서 데이터를 가져오는 서비스를 만듭니다.

끝점을 요청하려면 HttpClient가 필요합니다.

먼저 HttpClientModuleapp.module.ts에 추가합니다.


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

그런 다음 새 서비스를 만듭니다.

  1. ./node_modules/@angular/cli/bin/ng generate service news

이것은 @angular/cli를 사용하여 news라는 이름의 서비스를 생성합니다.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class NewsService {
  constructor(private http: HttpClient) { }

  getTopPosts() {
    const endpoint = 'https://hacker-news.firebaseio.com/v0/topstories.json';

    return this.http.get(endpoint);
  }
}

이제 NewsResolver의 문자열 코드를 NewsService로 바꿀 수 있습니다.

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { Observable } from 'rxjs';

import { NewsService } from './news.service';

export class NewsResolver implements Resolve<any> {
  constructor(private newsService: NewsService) {}

  resolve(): Observable<any> {
    return this.newsService.getTopPosts();
  }
}

이 시점에서 브라우저에서 상위 경로를 보면 Hacker News에서 상위 게시물의 id를 나타내는 숫자 목록이 표시됩니다.

6단계 - 경로 매개변수 액세스

ActivatedRouteSnapshot 개체를 사용하여 해석기에서 현재 경로 매개변수에 액세스할 수 있습니다.

다음은 리졸버를 사용하여 현재 경로의 id 매개변수에 액세스하는 예입니다.

먼저 @angular/cli를 사용하여 post라는 리졸버를 생성합니다.

  1. ./node_modules/@angular/cli/bin/ng generate resolver news

그런 다음 ActivatedRouteSnapshot을 사용하도록 post.resolver.ts를 수정합니다.

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { Observable } from 'rxjs';

import { NewsService } from './news.service';

@Injectable({
  providedIn: 'root'
})
export class PostResolver implements Resolve<any> {
  constructor(private newsService: NewsService) {}

  resolve(route: ActivatedRouteSnapshot): Observable<any> {
    return this.newsService.getPost(route.paramMap.get('id'));
  }
}

다음으로 NewsServicegetPost 메서드를 추가합니다.

// ...

export class NewsService {
  constructor(private http: HttpClient) { }

  // ...

  getPost(postId: string) {
    const endpoint = 'https://hacker-news.firebaseio.com/v0/item';

    return this.http.get(`${endpoint}/${postId}.json`);
  }
}

그리고 PostResolverpost/:id 경로를 app-routing.module.ts에 추가합니다.

// ...

import { PostResolver } from './post.resolver';

// ...

const routes: Routes = [
  // ...
  {
    path: 'post/:id',
    component: PostComponent,
    resolve: { newsData: PostResolver }
  }
];

// ...

다음으로 새로운 PostComponent를 만듭니다.

  1. ./node_modules/@angular/cli/bin/ng generate component post

그런 다음 스냅샷 데이터를 사용하도록 post.component.ts를 수정합니다.

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({ ... })
export class PostComponent implements OnInit {
  data: any;

  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    this.data = this.route.snapshot.data;
  }
}

그리고 제목을 표시하도록 post.component.html을 수정합니다.

<p>{{ data.newsData.title }}</p>

이제 사용자가 http://localhost:4200/post/15392112로 이동하면 게시물 ID 15392112에 대한 데이터가 확인됩니다.

7단계 - 오류 처리

데이터를 가져오는 동안 오류가 발생하면 RxJS의 catch 연산자를 사용하여 리졸버에서 오류를 잡아서 처리할 수 있습니다. 예를 들면 다음과 같습니다.

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';

import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { NewsService } from './news.service';

@Injectable()
export class NewsResolver implements Resolve<any> {
  constructor(private newsService: NewsService) {}

  resolve(): Observable<any> {
    return this.newsService.getTopPosts().pipe(catchError(() => {
      return of('data not available at this time');
    }));
  }
}

또는 EMPTY 관찰 가능 항목을 반환하고 사용자를 루트 경로로 반환할 수 있습니다.

import { Injectable } from '@angular/core';
import { Router, Resolve } from '@angular/router';

import { Observable, EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';

import { NewsService } from './news.service';

@Injectable()
export class NewsResolver implements Resolve<any> {
  constructor(private router: Router, private newsService: NewsService) {}

  resolve(): Observable<any> {
    return this.newsService.getTopPosts().pipe(catchError(() => {
      this.router.navigate(['/']);
      return EMPTY;
    }));
  }
}

이 두 가지 접근 방식은 API에서 데이터를 검색할 때 오류가 발생하는 경우 더 나은 사용자 경험을 제공합니다.

결론

이 자습서에서는 수집된 데이터를 표시하는 경로로 이동하기 전에 Hacker News API에서 데이터를 가져오는 경로 확인자를 구현했습니다. 이것은 @angular/router, @angular/common/httprxjs를 활용하여 달성되었습니다.

Angular에 대해 자세히 알아보려면 연습 및 프로그래밍 프로젝트에 대한 Angular 주제 페이지를 확인하세요.