본문 바로가기
프로그래밍/Angular

앵귤러 기초(Angular basic) 24. Http서비스 만들기2

by 신나요 2022. 2. 2.

지난 포스트에 이어 Http 서비스에 에러 핸들링을 추가한 뒤  Observerble을 구독함으로써 Http 통신을 해보겠습니다.

 

이번 포스트에서는 아래의 내용을 다루고 있습니다.

  1. 예외처리 Error handling 
  2. pipe연산자(tap, catchError)
  3. 옵저버블 구독하기(Subscribe Observable)

예외처리 Error handling

http통신을 할 때는 적절한 예외처리가 이루어져야 합니다.

지난 포스트에서 만들었던 MovieService는 아래와 같습니다.

예외처리 전

소스를 수정해 보겠습니다.

예외처리 수정 후

두 가지 연산자를 사용하여 소스를 수정하였습니다.

tap

연산자를 사용하기 위해서는 Observable의 pipe메서드를 사용해야 합니다.

tap Observable 스트림에서 방출된 값을 볼 수 있도록 해줍니다.

따라서 tap은 디버깅 또는 로깅에 사용하기에 좋습니다. 예시에서는 tap연산자에서 데이터를 콘솔에 기록하고 있습니다.

콘솔 로그 출력 시 호출하는 JSON.stringify는 객체 또는 객체 배열을 JSON문자열로 변환하는 자바스크립트 메서드입니다.

 

catchError

두 번째 연산자는 catchError입니다. pipe에 쉼표를 한 후 두 번째 연산자인 catchError를 추가하고 있습니다.

catchError는 Error를 탐지해주는 연산자입니다.

코드에서는 catchError 연산자는 에러가 검출됐을 시 다시 handleError메서드를 이용해 에러 처리에 관련된 로직을 수행하게 만들었습니다.

handleError는 매개변수 ErrorResponse를 건네받게 됩니다.

그리고 ErrorResponse를 이용하여 원격 로깅 인프라로 보내거나 에러코드를 붙여 다시 에러를 throw 할 수 있습니다.

예제 코드에서는 간단히 에러 메시지를 만들어서 에러를 던지고 있습니다.


http통신을 하기 위해선 이제 컴포넌트에서 Observable를 구독하는 일만 남았습니다.

 

다시 한번 머릿속에 상기해두세요. Observable은 구독(subscribe) 할 때까지 아무 일도 하지 않습니다.

따라서 컴포넌트에서 값을 받을 준비가 됐을 때 구독을 호출해야 합니다.

구독 역할인 subscribe메서드는 선택적 인수를 가지는 옵저버 객체를 사용합니다.

Observer객체는 스트림을 관찰하고, "next", "error", complete 세 가지 유형의 알림에 응답합니다.

이러한 알림에서 실행되는 핸들러 함수를 정의하기 위해 Observer객체를 사용하는 것입니다.

// {nextFunc, errorFunc, completeFunc} <- 옵저버 객체
testObservable.subscribe({
	nextFunc,
	errorFunc,
	completeFunc
});

 

Observable은 시간이 지남에 따라 여러 값을 처리할 수 있고, Observable이 방출하는 각 값에 대해 nextFunc가 호출됩니다.

errorFunc는 에러가 있으면 실행됩니다.

completeFunc는 Observable이 완료 시 실행되는 핸들러입니다.

 

subscribe함수는 Subscription을 반환합니다.

const testSubscription = testObservable.subscribe({
	nextFunc,
	errorFunc,
	completeFunc
});

해당 subscription를 사용하여 필요한 경우 구독을 취소할 수 있습니다.

testSubscription.unsubscribe(); // 구독취소

코드에서 확인해 보겠습니다.

 

1.movieService.getMovies()를 호출하면 Observable이 리턴되고, 구독(subscribe)을 할 수 있습니다.

subscribe을 하게 되면 http get요청이 시작됩니다. 그런 다음 Observable에서 데이터와 알림을 비동기적으로 수신합니다.

subscribe를 할 때 Observer객체를 전달해야 합니다.

Observer객체는 property(키)와 value(값)의 쌍으로 정의합니다. 여기서 키는 함수 이름이고 값은 함수이여 위 예에서는 화살표 함수를 사용하여 지정하였습니다.

 

2.next에서는 Obseservable이 항목을 방출할 때마다 취할 조치를 지정합니다. 이때 메소드 매개변수는 방출된 항목입니다. http호출은 단 한 번의 비동기 작업이므로 movie배열에 매핑된 http response개체인 항목 하나만을 배출하게 됩니다.

받은 movie데이터를 this.movies에 할당 후, 다시 filteredMoivies에 할당함으로 화면에 표시하도록 하였습니다.

 

3.error함수는 Observable이 실패하면 실행되고, 여기서는 단순히 콘솔 로그를 출력하고 있습니다.

 

4.complete함수는 Observable이 완료될 때 취할 조치를 지정할 수 있습니다. 여기에선 로그를 출력하고 있습니다. http는 단일 비동기 작업 이므로 next가 한번 호출된 후, 바로 complete가 호출될 것입니다. 보통 http요청 작업 시에는 complete는 거의 사용되지 않습니다.

 

5.구독한 Observable은 항상 구독취소를 하는 것이 좋습니다.

구독 취소는 일반적으로  subscription을 변수에 저장한 후, OnDestroy생명주기 훅에서 구독을 취소하게 됩니다.

위의 코드에서 Observable 구독 후 리턴되는 subscription을 클래스의 변수에 저장해 놓은 후, ngOnDestroy에서 취소를 하고 있습니다.

 

컴포넌트의 전체 코드는 아래와 같습니다.

import { Component, OnDestroy, OnInit } from "@angular/core";
import { Subscription } from "rxjs";
import { Movie } from "./movie.model";
import { MovieService } from "./movie.service";

@Component({
    selector: 'app-movies',
    templateUrl: './movie-list.component.html',
    styleUrls: ['./movie-list.component.scss']
})
export class MovieListComponent implements OnInit, OnDestroy {
    subTitle: string = '영화리스트';
    imgWidth: number = 55;
    imgMargin: number = 2;
    isImgDisplayed: boolean = false;

    subscription!: Subscription;

    private _filterText = '';
    get filterText(): string {
        return this._filterText;
    }
    set filterText(v: string) {
        this._filterText = v;
        this.filteredMovies = this.performFilter(v);
    }

    filteredMovies: Movie[] = [];
    movies: Movie[] = [];

    constructor(private movieService: MovieService) {
    }

    public ngOnInit(): void {
        this.subscription = this.movieService.getMovies().subscribe({
            next: (data) => {
                this.movies = data;
                this.filteredMovies = this.movies;
            },
            error: (error) => console.log(error),
            complete: () => console.log('complete'),
        });
    }

    public ngOnDestroy(): void {
        this.subscription.unsubscribe();
    }

    public toggleImg(): void {
        this.isImgDisplayed = !this.isImgDisplayed;
    }

    public performFilter(filterBy: string): Movie[] {
        filterBy = filterBy.toLocaleLowerCase();
        return this.movies.filter((movie: Movie) => {
            return movie.name.toLocaleLowerCase().includes(filterBy);
        });
    }

    public callFromStar(rating: number) {
        console.log('from star : ', rating);
    }

}

 

 

이제 브라우저에서 살펴보겠습니다.

데이터도 잘 가져오고, 화면에 출력도 원활히 되네요.🎉

로그를 보시면, Observable이 compelte 알림을 보낸 것도 확인해 보실 수 있을 겁니다.


수고하셨습니다. 이것으로 Http service 만들기가 끝났습니다.

다음 포스트에서는 앵귤러 라우팅에 대해 이야기해보겠습니다.

댓글