Angular | Restful api 통신 / Observables

권기현·2020년 8월 30일
0

Angular

목록 보기
3/4
post-thumbnail

HTTPClient클래스

(@angular/common/http)

주입가능한 클래스(?) -> @Injectable() 데코레이터를 사용한...
HTTP요청을 위한 메소드를 갖는다.
각 메소드에는 URL을 전달받기 위한 url파라미터와
옵션을 사용하기위한 options파라미터등...

httpClient의 메소드(get,post....등)는 옵져버블을 반환한다. HttpClient는 RxJS의 옵저버블 객체를 기반으로 작성되어 있다.

HTTPClientModule을 루트 모듈 임포트

httpClient 를 전역에서 사용할 수 있도록 루트모듈에 임포트 한다.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
// @angular/common/http 패키지의 HttpClientModule을 임포트한다.
import {HttpClientModule} from '@angular/common/http'
import { AppComponent } from './app.component';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    // HttpClientModule을 임포트한다.
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

이제 애플리케이션 전역에 HttpClient를 사용할(주입할) 수 있다.

GET요청(예시)

import { Component, OnInit } from '@angular/core';
// HttpClient 임포트
import { HttpClient } from "@angular/common/http";

@Component({
  selector: 'app-home',
  template: '<div class="home">Home</div>',
  styles: ['.home{font-size:2em; padding: 60px;}']
})
export class HomeComponent implements OnInit {

  url = "https://jsonplaceholder.typicode.com/todos";

  // HttpClient를 해당 컴포넌트에 주입
  constructor(public http: HttpClient) {}

  
  ngOnInit(): void {
    //HTTP GET 요청
    this.http.get(this.url)
      /*요청결과를 프로퍼퍼티에 할당한다.
      get메소드는 Observable<Object>를 반환한다.
      이때 타입이 일치하지 않기 때문에 컴파일 에러가 발생할 수 있다.
      아래 코드는 any[]라는 타입을 부여하여 있어서 발생하지 않는다.
      */
      .subscribe((res: any[]) => {console.log(res);
    });
  }

}
  • 모든 리소스 또는 특정 리소스를 조회할 때 사용, 옵저버블로 반환된다.(?) -> p.401
  • 리턴된 옵저버블 데이터를 subscribe를 통해서 사후처리한다.
  • HttpClient는 메소드는 기본적으로 응답 데이터 타입을 Object로 해석한다.
  • 응답 데이터의 타입을 알리려면 제네릭을 사용하여 타입 파라미터(형식 매개변수)를 설정해주어야한다.

➡️ 제네릭?

제네릭 타입이란,
: 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다

  • 선언시 클래스 또는 인터페이스 이름 뒤에 "< >"부호가 붙는다.
  • "< >" 사이에는 타입 파라미터가 위치한다.

제네릭을 사용하므로서 얻는 이점

  • 컴파일시 강한 타입체크를 할 수 있다.
    : 실행시 타입 에러가 나는 것보다는 컴파일시에 미리 타입을 강하게 체크해서 에러를 사전에 방지한다.

  • 타입변환을 제거할 수 있다.
    : 타입 변환이 많이 생길수록 전체 애플리케이션 성능이 떨어지게 된다.

출처: https://ict-nroo.tistory.com/42 [개발자의 기록습관]

reponse Type

json이 아닌 데이터를 요청할 때에 reponseType을 사용한다.

✔️ responseType을 사용하지 않으면 기본으로 JSON데이터를 반환한다.

      // HTTP GET 요청:텍스트를 요철
      this.http.get('textfile.txt',{ reponseType 'text'})
        // GET 메소드는 Observable<string>를 반환한다.
      .subscribe((res) => {console.log(res);
    });

에러 핸들링

  ngOnInit(): void {
    //HTTP GET 요청
    this.http.get<RES[]>(this.url)
      .subscribe(
        //요청 성공 처리 콜백 함수(Observer의 next 메소드)
        res => console.log(res),
        //요청 실패 처리 콜백 함수(Observer의 error 메소드)
        (error: HttpErrorResponse)=> console.error(error)
      );
  }

error: HttpErrorResponse
HttpErrorResponse타입의 err파라미터는 에러에 관련한 정보(클라이언트 측의 에러, 백엔드 측의 에러)를 담고있다.

클라이언트 에러, 백엔드 측의 에러

  • 클라이언트 측의 에러
    • error 파라미터는 ErrorEvent 객체의 인스턴스
    • RxJS 오퍼레이터 exception을 throw했거나 네트워크 에러로 인해 요청이 성공적으로 완료되지 못한 경우이다.
  • 백엔드 측의 에러
    • error 파라미터는 ErrorEvent 객체의 인스턴스가 아니다.
    • 백엔드가 요청 처리에 실패하여 404,500 등의 상태 코드를 응답한 경우

➡️ 여기서 중요한 것은 error 파라미터가 인스턴스인지 아닌지 이다. 이를 통해서 경우에 따른 처리가 가능하기 때문이다.

import { throwError } from 'rxjs';
...
private handleError(error: HttpErrorResponse){
  let message = '';
  
  // 1. 에러 유형 구분
  if(error.error instanceof ErrorEvent){
    //클라이언트 측의 에러
    console.error(`클라이언트 측 에러: ${error.error.message}`);
    message = error.error.message;
  }else{
  //백엔드 측의 에러
    console.error(`서버 측 에러: ${error.status}`);
    message = error.message;
  }
  
  // 2. 사용자에게 전달할 메세지를 담은 옵저버블 반환
  return throwError({
  	title: 'Something wrong! please try again later',message
  })
}
  1. 에러의 유형을 구분
    클라이언트 측 에러인지 서버 측 에러인지를 구분하여 전달할 메세지를 생성한다.

  2. throwError 오퍼레이터는 옵저버에게 데이터 방출을 중지하고 즉시 에러 노티피케이션을 방출하는 옵저버블을 생성한다. 따라서 위 핸들러 함수가 호출되면 옵저버의 error메소드로 에러 노티피케이션이 전파된다.

Observables

옵저버블은 시간이 지남에 따라 여러값을 가질 수 있는 지연 콜렉션이다.

1. Observables는 lazy하다.

지연 옵저버블을 뉴스 레터로 생각할 수 있다. 각 구독자(subscriber)마다 새로운 뉴스 레터가 만들어진다. 그 뉴스레터들은 구독자들에게만 보내고 다른 사람에게는 보내지 않는다.

2. Observables는 시간이 지남에 따라 여러 값을 가질 수 있다.

뉴스 레터 구독을 계속 열어두면, 매번 새로운 뉴스 레터를 받게된다. 발신자(sender)는 받은 시간을 결정하지만 받은 편지함에 곧바로 올 때까지 기다려야한다.

옵저버블과 프로미스간의 다른 중요한 차이점이 있는데, promise은 항상 오직 하나의 값만을 반환한다는 점이다. 또 하나는 옵저버블의 구독을 취소 할 수 있다는 점이다. 뉴스 레터를 더 이상 원하지 않으면 구독을 취소하면된다. 프로미스를 사용하면 이점이 다른건데, 프로미스는 취소 할 수 없다. 프라미스가 당신에게 건네지면, 그 프라미스의 resolve가 이미 진행되고 있으며, 일반적으로 프라미스의 resolve가 실행되는 것을 막을 수 있는 권한이 없다.

Angular - Observable을 구독하기

Angular에서 우리는 두 가지 방식으로 Observable을 구독 할 수 있다.

  • 비동기 파이프를 사용하여 템플릿의 옵저버블을 구독하는 방법
  • subscribe() 메소드를 이용하여 구독하는 방법

위의 두가지 방법이 있다. 하지만 보통 "subscribe()"를 많이 사용하였다.

옵저버블에 대한 더 자세한 설명

#TIL

OnInit

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


export class AppComponent implements OnInit {
...
} 

라이프 사이클을 쓰기 위해서는 OnInit을 implement 해주어야한다. 그렇지 않으면 라이프사이클 메소드에서

Lifecycle interface OnInit should be implemented for method ngOnInit. (https://angular.io/styleguide#style-09-01) (use-lifecycle-interface)

위와 같은 에러가 생성된다.

https://skout90.github.io/2017/07/12/Angular/7.%20Angular%20%EB%9D%BC%EC%9A%B0%ED%84%B0/

profile
함께 일하고 싶은 개발자를 목표로 매일을 노력하고, 옷을 좋아하는 권기현 입니다.

0개의 댓글