[Angular] Http Client 사용 방법

Angular의 HttpClient 모듈은 HTTP 요청을 만들고 응답을 처리하는 간단한 방법을 제공합니다. @angular/common/http 패키지의 일부이며 XMLHttpRequest API 위에 구축되었습니다.

이 글에서는 HttpClient 모듈의 다양한 기능을 자세히 살펴보고 이를 사용하여 Angular에서 HTTP 요청을 만드는 방법을 알아봅니다.

Getting started

Angular 애플리케이션에서 HttpClient 모듈을 사용하려면 루트 모듈(일반적으로 app.module.ts)에서 HttpClientModule을 가져와야 합니다.

1
2
3
4
5
6
7
8
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
imports: [HttpClientModule],
// ...
})
export class AppModule {}

HttpClientModule을 가져오면 이제 HttpClient 서비스를 사용하여 HTTP 요청을 할 수 있습니다.

HTTP 요청하기

HttpClient 서비스를 사용하여 HTTP 요청을 만들려면 get(), post(), put(), delete()patch() 메서드 중 하나를 호출하면 됩니다. 이 메서드는 요청 완료 시 응답을 내보내는 Observable을 반환합니다.

다음은 HttpClient 서비스를 사용하여 GET 요청을 만드는 방법에 대한 예입니다.

1
2
3
4
5
6
7
8
9
10
11
12
import { HttpClient } from '@angular/common/http';

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

getData(): Observable<any> {
return this.http.get<any>('https://api.example.com/data');
}
}

위의 예에서는 HttpClient 서비스를 ApiService 라는 서비스에 주입합니다. 그런 다음 any 유형의 Observable 을 반환하는 getData() 라는 메서드를 정의합니다. HttpClient 서비스의 get() 메서드는 지정된 URL에 대한 GET 요청을 만드는 데 사용됩니다.

마찬가지로, 다른 HTTP 메서드를 사용하여 요청을 수행하고 적절한 데이터를 메서드의 두 번째 인수로 전달할 수 있습니다.

HTTP 응답 처리

HttpClient 서비스는 도착 시 응답을 내보내는 Observable 을 반환합니다. 응답을 처리하기 위해 Observablesubscribe() 메서드를 사용할 수 있습니다.

다음은 getData() 메서드의 응답을 처리하는 방법에 대한 예입니다.

1
2
3
4
5
6
7
8
this.apiService.getData().subscribe(
(response) => {
// handle the response here
},
(error) => {
// handle the error here
}
);

위의 예에서는 ApiService 서비스의 getData() 메서드를 호출하고 Observablesubscribe() 메서드를 사용하여 응답을 구독합니다. subscribe() 메서드의 첫 번째 콜백은 응답이 도착할 때 호출되고, 두 번째 콜백은 오류가 있을 때 호출됩니다.

HTTP 헤더

HttpHeaders 클래스의 set() 메서드를 사용하여 요청에 대한 HTTP 헤더를 설정할 수도 있습니다. Authorization 헤더를 설정하는 방법의 예는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { HttpClient, HttpHeaders } from '@angular/common/http';

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

getData(): Observable<any> {
const headers = new HttpHeaders({
Authorization: 'Bearer my-token',
});

return this.http.get<any>('https://api.example.com/data', { headers });
}
}

위의 예에서는 HttpHeaders 클래스의 새 인스턴스를 생성하고 Authorization 헤더를 Bearer my-token 으로 설정합니다. 그런 다음 헤더 개체를 HttpClient 서비스의 get() 메서드에 대한 두 번째 인수로 전달합니다.

Query parameters

HttpParams 클래스를 사용하여 HTTP 요청에 쿼리 매개변수를 전달할 수도 있습니다. 쿼리 매개변수를 전달하는 방법의 예는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { HttpClient, HttpParams } from '@angular/common/http';

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

getData(page: number, limit: number): Observable<any> {
let params = new HttpParams();
params = params.append('page', page.toString());
params = params.append('limit', limit.toString());

return this.http.get<any>('https://api.example.com/data', { params });
}
}

위의 예에서는 HttpParams 클래스의 새 인스턴스를 만들고 append() 메서드를 사용하여 pagelimit 매개변수를 여기에 추가합니다. 그런 다음 params 개체를 HttpClient 서비스의 get() 메서드에 대한 두 번째 인수로 전달합니다.

오류 처리

HTTP 요청을 할 때 오류를 적절하게 처리하는 것이 중요합니다. HttpClient 서비스는 rxjs 라이브러리의 catchError() 연산자를 사용하여 오류를 처리하는 방법을 제공합니다.

다음은 getData() 메서드에서 오류를 처리하는 방법에 대한 예입니다.

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
28
29
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';

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

getData(): Observable<any> {
return this.http.get<any>('https://api.example.com/data').pipe(
catchError((error: HttpErrorResponse) => {
let errorMessage = '';

if (error.error instanceof ErrorEvent) {
// client-side error
errorMessage = `Error: ${error.error.message}`;
} else {
// server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}

console.error(errorMessage);
return throwError(errorMessage);
})
);
}
}

위의 예에서는 rxjs 라이브러리의 catchError() 연산자를 사용하여 오류를 처리합니다. 오류가 발생하면 catchError() 연산자는 오류를 발생시키고 Observable 체인을 중지합니다. 그런 다음 rxjs 라이브러리의 throwError() 함수를 사용하여 오류를 내보내고 Observable 체인을 계속합니다.

다음은 HttpClient 모듈의 많은 기능을 사용하는 예입니다.

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable({
providedIn: 'root',
})
export class ApiService {
private baseUrl = 'https://example.com/api';
private headers = new HttpHeaders({
'Content-Type': 'application/json',
});

constructor(private http: HttpClient) {}

private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.error('An error occurred:', error.error.message);
} else {
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
return throwError('Something bad happened; please try again later.');
}

private getAuthHeaders() {
return new HttpHeaders({
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('access_token')}`,
});
}

public get<T>(path: string): Observable<T> {
return this.http
.get<T>(`${this.baseUrl}${path}`, {
headers: this.getAuthHeaders(),
})
.pipe(catchError(this.handleError));
}

public post<T>(path: string, data: any): Observable<T> {
return this.http
.post<T>(`${this.baseUrl}${path}`, data, {
headers: this.getAuthHeaders(),
})
.pipe(catchError(this.handleError));
}

public put<T>(path: string, data: any): Observable<T> {
return this.http
.put<T>(`${this.baseUrl}${path}`, data, {
headers: this.getAuthHeaders(),
})
.pipe(catchError(this.handleError));
}

public delete<T>(path: string): Observable<T> {
return this.http
.delete<T>(`${this.baseUrl}${path}`, {
headers: this.getAuthHeaders(),
})
.pipe(catchError(this.handleError));
}
}

HTTP 요청 테스트

@angular/common/http/testing 모듈은 HttpClient 서비스로 생성된 HTTP 요청을 테스트하기 위한 유틸리티 세트를 제공합니다.

이 모듈에서 제공하는 주요 클래스는 HttpTestingController 입니다. 이 클래스를 사용하여 HTTP 요청 및 응답을 모의하고 테스트 중인 애플리케이션에서 올바른 요청이 이루어졌는지 확인할 수 있습니다.

HttpTestingController 를 사용하려면 먼저 테스트 케이스에 삽입해야 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

describe('MyComponent', () => {
let httpTestingController: HttpTestingController;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [MyComponent],
});

httpTestingController = TestBed.inject(HttpTestingController);
});
});

Mocking HTTP Requests

HTTP 요청을 모의하려면 HttpTestingController 인스턴스에서 ExpectOne() 메서드를 호출하여 URL 또는 HttpRequest 객체를 전달할 수 있습니다. 이 메서드는 요청에 대한 응답을 제어하는 데 사용할 수 있는 TestRequest 객체를 반환합니다.

다음은 ExpectOne() 을 사용하여 HTTP GET 요청을 모의하는 방법에 대한 예입니다.

1
2
3
4
5
6
7
8
9
10
11
12
it('should make an HTTP GET request', () => {
const expectedData = { id: 1, name: 'John Doe' };
const url = '/api/user/1';

myComponent.getUser(1).subscribe((data) => {
expect(data).toEqual(expectedData);
});

const req = httpTestingController.expectOne(url);
expect(req.request.method).toEqual('GET');
req.flush(expectedData);
});

이 예에서는 MyComponent 인스턴스에서 getUser() 메서드를 테스트하고 있습니다. 이 메서드는 /api/user/1 에 대한 HTTP GET 요청을 만들고 응답 데이터를 내보내는 Observable 을 반환합니다.

이 메서드를 테스트하기 위해 getUser() 를 호출하고 그것이 반환하는 Observable 을 구독합니다. 그런 다음 요청과 동일한 URL을 사용하여 httpTestingController.expectOne() 을 호출하고 반환된 TestRequest 객체를 사용하여 예상 데이터가 포함된 응답을 flush 합니다.

HTTP 요청 확인

HttpTestingController 를 사용하여 HTTP 요청을 모의한 후 해당 메서드를 사용하여 예상되는 요청이 테스트 중인 애플리케이션에서 이루어졌는지 확인할 수 있습니다.

예를 들어, verify() 메서드를 사용하여 예기치 않은 요청이 발생하지 않았는지 확인할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
it('should make an HTTP GET request', () => {
myComponent.getUser(1).subscribe((data) => {
expect(data).toEqual(expectedData);
});

const req = httpTestingController.expectOne('/api/user/1');
req.flush(expectedData);

httpTestingController.verify();
});

이 예에서는 httpTestingController.verify() 를 사용하여 테스트 중인 애플리케이션에서 다른 요청이 이루어지지 않았는지 확인합니다. 다른 요청이 이루어진 경우 이 메서드는 오류를 발생시킵니다.

expectNone() 메서드를 사용하여 요청이 이루어지지 않았는지 확인할 수도 있습니다.

1
2
3
4
5
6
7
it('should not make an HTTP GET request with incorrect ID', () => {
myComponent.getUser(2).subscribe((data) => {
expect(data).toBeUndefined();
});

httpTestingController.expectNone('/api/user/2');
});

이 예에서는 getUser() 메서드가 /api/user/2 에 HTTP 요청을 하지 않는지 테스트하고 있습니다. 요청과 동일한 URL로 httpTestingController.expectNone() 을 호출하고 요청이 없으므로 테스트가 통과됩니다.

결론

Angular의 HttpClient 모듈의 다양한 기능을 살펴보았습니다. HTTP 요청을 작성하고 응답을 처리하고, HTTP 헤더 및 쿼리 매개변수를 설정하고, 오류를 처리하는 방법을 배웠습니다. HttpClient 모듈은 Angular 애플리케이션에서 HTTP 요청을 만들기 위한 강력하고 사용하기 쉬운 API를 제공합니다.

Share