만약 AngularJS를 사용하여 애플리케이션을 개발해 오셨다면, 아마 HTTP 인터셉터에 대해 알고 계실 것입니다. 하지만 이러한 HTTP 인터셉터는 버전 4.3 이전의 Angular에서는 사용할 수 없었습니다. 이 튜토리얼에서는 Angular에서 인터셉터를 사용하여 HTTP 요청 및 응답을 처리하고 오류를 처리하는 방법을 알아봅니다.
사전 요구 사항
Angular 애플리케이션은 Node.js 런타임을 사용합니다. 이 튜토리얼을 완료하려면 컴퓨터에 Node.js가 설치되어 있어야 합니다. 다행히도 Node.js는 설치가 매우 쉽습니다. 다음 페이지에 완전한 가이드가 준비되어 있습니다: How to Install Node.js on Ubuntu 18.04 here.
또한, Angular를 알고 Angular CLI를 사용하여 Angular 애플리케이션을 빌드하는 데 익숙하면 도움이 됩니다. 여기서는 Node v8.12.0 및 npm v6.4.1을 사용합니다.
1단계: Angular 앱 생성
먼저 Angular CLI를 사용하여 새로운 Angular 앱을 만들어 보겠습니다. 애플리케이션 이름은 Angular-Interceptor로 지정하겠습니다. 앱을 생성하려면 아래 명령어를 실행하세요:
|
1 |
npx @angular/cli@7.0.6 new Angular-Interceptor |
몇 가지 선택 사항을 묻는 메시지가 나타납니다. 기본값을 입력하고 진행하세요:

다음으로 애플리케이션 디렉터리로 이동한 후, 아래 명령어를 실행하여 애플리케이션을 시작합니다:
|
1 |
npx ng serve --open |

그런 다음 브라우저에서 http://localhost:4200 을 열어 앱을 확인합니다. 이제 기본적인 Angular 앱 구성이 완료되었습니다.
Step 2: Style Angular App
여기서는 Angular Material을 사용하여 Angular 앱의 스타일을 지정하겠습니다. 프로젝트에 Angular Material을 설치하려면 아래 명령어를 실행하세요:
|
1 |
npm install --save @angular/material@7.0.4 @angular/cdk@7.0.4 @angular/animations@7.0.4 |
이렇게 하면 프로젝트에 @angular/material, @angular/cdk, 그리고 @angular/animation이 설치됩니다. 다음으로 프로젝트에 애니메이션을 설정하겠습니다. BrowserAnimationsModule을 src/app/module.ts 파일에 추가합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @NgModule({ ... imports: [ ... BrowserAnimationsModule ], ... }) export class AppModule { } |
Angular Material의 Dialog 컴포넌트를 사용하겠습니다. Dialog 컴포넌트를 사용하려면 MatDialogModule을 src/app/app.module.ts 파일에 임포트해야 합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { MatDialogModule } from '@angular/material'; @NgModule({ ... imports: [ ... MatDialogModule ], ... }) export class AppModule { } |
UI를 더 매력적으로 만들기 위해, indigo-pink.css를 styles.scss 파일에 추가해 보겠습니다:
|
1 |
@import "~@angular/material/prebuilt-themes/indigo-pink.css"; |
3단계: Angular 인터셉터 빌드하기
Under the app 폴더 아래에, interceptor라는 새 폴더를 생성하겠습니다. 이 새로 생성된 폴더 안에 새 httpconfig.interceptor.ts 파일을 생성합니다.
인터셉터가 작동하도록 하려면 httpconfig.interceptor.ts 파일에 몇 가지 의존성을 임포트해야 합니다. 이러한 의존성은 HttpInterceptor, HttpRequest, HttpResponse, 그리고 HttpHandler, HttpEvent, HttpErrorResponse.
임포트한 후의 httpconfig.interceptor.ts 파일은 다음과 같습니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http'; import { Observable, throwError } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; |
다음으로, HttpConfigInterceptor 클래스를 생성하고 다음 인터페이스를 구현합니다: HttpInterceptor. 다음은 예시입니다:
|
1 2 3 4 5 6 7 |
@Injectable() export class HttpConfigInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { // ... } } |
아래 코드를 다음에 추가합니다: httpconfig.interceptor.ts 파일:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
... @Injectable() export class HttpConfigInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token: string = localStorage.getItem('token'); if (token) { request = request.clone({ headers: request.headers.set('Authorization', 'Bearer ' + token) }); } if (!request.headers.has('Content-Type')) { request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') }); } request = request.clone({ headers: request.headers.set('Accept', 'application/json') }); return next.handle(request).pipe( map((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { console.log('event--->>>', event); } return event; })); } } |
작동하려면 다음을 임포트해야 합니다: httpconfig.interceptor.ts - 위치: app.module.ts 파일:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
... import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; ... import { HttpConfigInterceptor } from './interceptor/httpconfig.interceptor'; @NgModule({ ... imports: [ ... HttpClientModule ], ... }) |
추가: HttpConfigInterceptor -> providers. 여러 인터셉터를 처리하기 위해 multi: true 로 설정합니다:
|
1 2 3 4 5 6 7 8 9 10 |
... @NgModule({ ... providers: [ ... { provide: HTTP_INTERCEPTORS, useClass: HttpConfigInterceptor, multi: true } ], ... }) ... |
다음 섹션에서는 에러를 처리하기 위한 서비스를 생성하겠습니다.
4단계: 에러 처리 서비스
여기서는 에러를 처리하는 코드를 작성합니다. 에러를 캡처하여 최종 사용자에게 적절하게 표시해야 합니다. 요약하자면, 진행할 단계는 다음과 같습니다:
- 다음 폴더를 생성합니다: error-dialog - 위치: app 폴더.
- 다음 이름의 에러 서비스를 생성합니다: errorDialogService - 파일명: errordialog.service.ts.
- 아래 코드를 다음에 추가합니다: errordialog.service.ts :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
import { Injectable } from '@angular/core'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { ErrorDialogComponent } from './errordialog.component'; @Injectable() export class ErrorDialogService { public isDialogOpen: Boolean = false; constructor(public dialog: MatDialog) { } openDialog(data): any { if (this.isDialogOpen) { return false; } this.isDialogOpen = true; const dialogRef = this.dialog.open(ErrorDialogComponent, { width: '300px', data: data }); dialogRef.afterClosed().subscribe(result => { console.log('대화 상자가 닫혔습니다'); this.isDialogOpen = false; let animal; animal = result; }); } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA } from '@angular/material'; @Component({ selector: 'app-root', templateUrl: './errordialog.component.html' }) export class ErrorDialogComponent { title = 'Angular-Interceptor'; constructor(@Inject(MAT_DIALOG_DATA) public data: string) {} } |
|
1 2 3 4 5 6 7 8 9 10 |
<div> <div> <p> 이유: {{data.reason}} </p> <p> 상태: {{data.status}} </p> </div> </div> |
요약하자면, 아래 단계를 나열해 보겠습니다:
- 먼저 다음을 가져오는 것부터 시작합니다: errordialog.service.
- 그런 다음, 다음에 대한 생성자를 추가합니다: errorDialogService.
- 또한 다음을 사용하여 오류 응답을 처리하는 코드를 추가합니다: catchError 및 throwError.
- 다음을 errordialog.service 및 errordialog.component을(를) 다음으로 가져옵니다: AppModule.
변경을 완료하면 두 개의 파일이 수정됩니다: app.module.ts 및 httpconfig.interceptor.ts:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
... import { ErrorDialogComponent } from './error-dialog/errordialog.component'; ... import { ErrorDialogService } from './error-dialog/errordialog.service'; ... @NgModule({ ... declarations: [ ... ErrorDialogComponent ], ... providers: [ ... ErrorDialogService ], entryComponents: [ErrorDialogComponent], }) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
... import { ErrorDialogService } from '../error-dialog/errordialog.service'; ... @Injectable() export class HttpConfigInterceptor implements HttpInterceptor { constructor(public errorDialogService: ErrorDialogService) { } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { ... return next.handle(request).pipe( map((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { console.log('event--->>>', event); } return event; }), catchError((error: HttpErrorResponse) => { let data = {}; data = { reason: error && error.error && error.error.reason ? error.error.reason : '', status: error.status }; this.errorDialogService.openDialog(data); return throwError(error); })); } } |
5단계: 샘플 서비스 생성하기
이 단계에서는 샘플로 두 개의 서비스를 생성합니다:
- 로그인 API
- 고객 상세 정보 API
다음과 같은 이름의 새 폴더를 생성합니다: services (위치: src 폴더). 다음으로, 새로 생성된 이 폴더 내에 다음과 같은 이름의 새 파일을 생성합니다: login.service.ts, 그리고 두 개의 함수를 추가합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable() export class LoginService { constructor(private http: HttpClient) { } login(data) { data = { email: 'admin', password: 'admin' }; return this.http.post('http://localhost:3070/api/login', data); } getCustomerDetails() { return this.http.get('http://localhost:3070/customers/details'); } } |
6단계: HTTP 클라이언트 서비스 호출하기
마지막으로, 튜토리얼의 마지막 부분입니다. 다음 파일에서 HTTP 서비스를 호출합니다: app.component.ts 파일. 두 개의 LoginService 함수를 다음에 추가합니다: app.component.ts에 추가합니다. onload 시 로그인 API를 호출하고, 다음을 사용하여 customers/details를 호출합니다: onclick:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import { Component } from '@angular/core'; import { LoginService } from './services/login.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'Angular-Interceptor'; constructor(public loginService: LoginService) { this.loginService.login({}).subscribe(data => { console.log(data); }); } getCustomerDetails() { this.loginService.getCustomerDetails().subscribe((data) => { console.log('----->>>', data); }); } } |
이제 다음 위치에 UI 요소를 추가해야 합니다: app.component.html, 사용자가 클릭할 수 있도록 합니다:
|
1 |
<h2 (click)="getCustomerDetails()">고객 상세 정보 가져오기</h2> |
마지막으로, LoginService를 providers에 추가해야 합니다 (대상: AppModule:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
... import { LoginService } from './services/login.service'; ... @NgModule({ ... providers: [ ... LoginService ] ... }) |
아래에서 오류 처리기 대화 상자의 스크린샷을 확인하세요:

결론
이 튜토리얼에서는 Angular 인터셉터를 사용하여 HTTP 요청 및 응답을 처리하는 방법을 배웠습니다. 또한 Angular Material의 대화 상자(dialog)를 사용하여 오류를 처리하는 방법도 배웠습니다.
Angular 앱은 Node.js를 런타임으로 사용합니다. Node.js에 대해 자세히 알아보고 Docker에 Node.js 애플리케이션을 배포하는 방법을 알아보려면 다음 가이드를 확인하세요: Ubuntu 20.04에서 Docker로 Node.js (Express.js) 앱을 배포하는 방법 가이드. 다음 가이드도 확인할 수 있습니다: Ubuntu 20.04에서 Node.js로 프로덕션 작업을 수행하는 방법 및 CentOS 8에 Node.js 설치하기: 전체 가이드.
즐거운 컴퓨팅 되세요!
댓글
아직 댓글이 없습니다. 첫 번째로 작성해 보세요.