프론트엔드 어플리케이션은 서버와 통신하기위해 HTTP프로토콜로 통신한다.
앵귤러는 서버와통신을 위해 클라이언트 HTTP API로 HttpClient서비스를 제공한다.
서버와 통신하려면 HttpClientModule라이브러리를 임포트하고 내장된 HttpClient서비스를 사용하면 된다.
httpClient.get()메소드는 서버에 http요청을 보내고 Observable로 Http응답을 전달하는 비동기메소드다.
get(url: string, options:{ ... } );
options: {
headers?: HttpHeaders | {[header: string]: string | string[]},
observe?: 'body' | 'events' | 'response',
params?: HttpParams|{[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>},
reportProgress?: boolean,
responseType?: 'arraybuffer'|'blob'|'json'|'text',
withCredentials?: boolean,
}
options객체를 사용해서 header를 보낼수 있고, params로 쿼리인자를 보낼 수 있고 observe로 응답범위를 지정할 수 있고 responseType으로 반환타입을 지정할 수 있다.
응답타입 지정하기
HttpClient.get메소드의 responseType을 지정하면 서버에서 받는 데이터를 좀 더 명확하게 처리할 수 있으며 컴파일할때 타입검사를 수행한다.
서버에서 내보내는 데이터가 지정된 타입임을 보장하지는 않으며 클라이언트에서 보다 안전하게 데이터를 처리하기 위한 수단이다.
인터페이스를 선언하여 응답객체의 타입을 설정하는것이 좋다.
export interface Config {
heroesUrl: string;
textfile: string;
date: any;
}
getConfig(){ // Observable<Object>를 반환한다.
return this.http.get(this.configUrl);
}
getConfig(){ // Observable<Config>를 반환한다.
return this.http.get<Config>(this.configUrl);
}
get함수를 제네릭타입으로 지정하면 반환타입도 지정되기때문에 좋다.
응답전체를 읽기
httpClient.get메소드에 두번째 옵션인자를 지정하지 않으면 responseType은 json이되고 observe는 body이 된다.
따라서 전체응답이 필요할때는 옵션인자를 지정해야 한다.
getConfigResponse(){
return this.http.get<Config>(this.configUrl,{observe:'response'});
}
이렇게 하면 응답객체의 타입이 json에서 HttpResponse타입이 된다.
showConfigResponse(){
this.configService.getConfigResponse().subscribe(
response=>{
const keys = response.headers.keys();
this.headers = keys.map(key=>`${key}:${response.headers.get(key)}`);
this.config = {...response.body!};
}
);
}
HttpResponse타입인 response객체에서 headers는 HttpHeaders
타입의 객체이며 body는 지정된 타입이 된다.
Http에러처리하기
서버로보낸 요청이 실패하면 HttpClient는 응답객체대신 에러객체를 반환하며 에러객체를 분석하면 자세한 정보를 알 수 있다.
에러원인 확인하기
에러에대한 세부정보를 확인한 후 이해하기쉬운 형태로 가공하는것이 필요하다.
에러형태
HttpClient는 두가지 에러를 모두 HttpErrorResponse로 처리하기 때문에 서버로 보낸 요청이 왜 실패했는지 확인하려면 에러가 왜 발생했는지 파악해야 한다.
private handelError(error:HttpErrorResponse){
if(error.status == 0){
console.error('An error occurred:',error.message);
}else{
console.error(
`Backend returned code ${error.status}, body was: `, error.error);
}
return throwError(()=>new Error('Something bad happened; please try again later.'));
}
서버에 데이터보내기
HttpClient로 서버에 데이터를 요청할때 사용하는 HTTP메소드가 PUT, POST, DELETE라면 서버로 추가데이터를 보낼 수 있다.
POST요청보내기
데이터는 POST방식으로 보낼 수 있다.
addHero(hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions)
.pipe(
catchError(this.handleError('addHero', hero))
);
}
DELETE요청 보내기
deleteHero(id: number): Observable<unknown> {
const url = `${this.heroesUrl}/${id}`; // DELETE api/heroes/42
return this.http.delete(url, httpOptions)
.pipe(
catchError(this.handleError('deleteHero'))
);
}
this.heroesService
.deleteHero(hero.id)
.subscribe();
PUT요청보내기
헤더추가/수정하기
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'my-auth-token'
})
};
HTTP 요청 / 응답 가로채기
인터셉터를 활용하면 서버로 보내는 HTTP요청을 가로채거나 변환할 수 있다. HTTP요청에 적용된 인터셉터는 HTTP응답에도 다시 활용할 수 있으며 인터셉터가 여러개일경우 순서대로 체이닝할 수 있다.
인터셉터는 다양한 기능을 수행할 수 있지만 일반적으로 HTTP 요청/응답에대해 사용자 인증정보를 확인하고 로그를 출력하는데 사용한다.