Angular에서는 이미 RxJS의 기술을 사용하고 있습니다. RxJS는 관찰이 가능한 Observable 시퀀스를 사용해서 데이터와 이벤트를 관찰하고 반응(처리)해주는 라이브러리 입니다. 그리고 앵귤러에서 처음 Observable을 접하는 곳은 아마도 http 통신일 것입니다.
이번 포스트는 옵저버블을 사용해서 절차적으로 http 통신을 통해 데이터를 조회하는 순서를 따라가보고, 이것을 다시 async 파이프를 사용을 시작으로 코드를 점점 리액티브 하게 개선해보도록 하겠습니다.
http 통신 절차적 데이터 조회 패턴
여기 아래에 상품목록을 http 통신을 통해 데이터를 가져와 테이블로 표시하는 상품 목록 화면이 있습니다. 아래의 화면을 만든다는 이미지를 머릿속에 넣으시고 코드를 따라와 주세요.
1. 데이터모델 정의하기
데이터를 검색하는 코드를 작성할 때 작업의 첫 번째 단계는 데이터의 모델 정의하는 일입니다. 파일명을 product.ts라고 했고 아래와 같이 정의해 주었습니다.
인터페이스를 사용하여 검색하는 데이터의 구조에 맞게 각 필드를 정의합니다. ?(물음표) 표시는 검색된 데이터에 존재하지 않을 수도 있는 선택적 필드를 식별할 때 사용됩니다. 이러한 필드를 null값이 들어갈 수 있는 nullable 필드라고 합니다.
2. http 통신 메소드 정의하기
서비스 클래스인 ProdcutService에서 제품 목록을 가져오는 메소드를 정의하겠습니다.
get메서드를 호출할 때 get<Product[]>와 같이 타입을 설정해서 get 메서드가 우리가 만들 모델인 Product[]로 자동으로 매핑되도록 하고 있습니다. get은 옵저버블을 반환하게 됩니다. 옵저버블의 pipe를 사용하여 디버깅 정보를 표시하는 tap연산자와 오류를 처리하는 catchError연산자를 설정해 주었습니다. 최종적으로 getProducts메소드는 Observable<Product[]>를 리턴하게 됩니다.
3. 컴포넌트에서 옵저버블 구독하기
위에서 만든 메소드를 제품 목록 컴포넌트에서 사용하여 데이터를 출력하는 일을 하겠습니다.
- 1) 컴포넌트의 생성자에서 ProdcutService를 인젝션하여 getProducts메소드를 사용할 수 있게 하였습니다.
- 2) 페이지가 초기화 될때마다 호출되는 ngOnInit메소드에서 getProducts메소드를 호출하고 있습니다. getProducts를 호출하는 것만으론 데이터를 방출하지 않으므로 옵저버블 시작을 위해 subscirbe메소드를 호출합니다.
- 3) 서비스에서 http응답을 수신하면 관찰자에게 알림이 전송되고 next 메서드가 실행되며 옵저버블이 완료됩니다. next 메서드 안에서는 response에서 반환된 Product 배열을 로컬 프로퍼티 products에 할당해 줍니다. 만약 에러가 발생한다면 errorMessage에 할당하게 됩니다.
- 4) OnDestroy 라이프사이클 후크에서 페이지가 파괴될 때 구독했던 옵저버블을 구독 취소합니다. 구독 취소는 프로그램 내에서 많은 옵저버블이 존재한다면 복잡해질 수 있습니다.
4. 템플릿에서 데이터 표시
화면의 뷰를 담당하는 제품 목록 템플릿에서 ngIf지시문을 사용하여 테이블을 표시하기 전에 표시할 데이터가 있는지 확인합니다. products에 데이터가 존재한다면 ngFor지시문을 사용하여 product 배열의 각 product를 반복하여 테이블 행에 표시하게 됩니다.
여기까지가 옵저버블을 사용한 데이터 검색에 자주 사용되는 기본적인 패턴입니다. 메서드를 호출하는 이 기술은 간단하고 매우 잘 작동하지만 이러한 절차적 접근 방식은 크고 복잡한 프로그램에서 사용하기에는 제한될 수 있습니다. 이제 비동기 파이프를 사용을 시작으로 코드를 더 리액티브 하게 만들어 보도록 하겠습니다.
Async 파이프
async 파이프는 컴포넌트가 초기화될 때 자동으로 옵저버블을 구독하고 해당 옵저버블에서 방출된 각 값을 반환합니다. 새 항목이 방출되면 컴포넌트가 변경사항을 확인하도록 표시되고 변경을 감지가 실행되고 UI가 갱신됩니다. 또한 async 파이프는 잠재적인 메모리 누수를 방지하기 위해 컴포넌트가 파괴될 때 자동으로 구독을 취소합니다.
async로 변경하기
async파이프를 사용한다고 해서 서비스 코드를 변경할 필요는 없고 컴포넌트와 템플릿만 변경하면 사용이 가능합니다. 코드를 수정해 보도록 하겠습니다.
ngOnInit메소드에서 이제 subscribe 하는 부분이 사라졌습니다. 대신에 getProducts를 호출하여 가져온 옵저버블을 products$ 프로퍼티에 할당해 주고 있습니다. $달러 표시는 Stream의 약자로 옵저버블을 나타내는 코딩 관례입니다.
다음은 템플릿 부분 수정입니다.
템플릿에서 ngIf를 사용하여 products$를 체크하고 async 파이프를 사용하여 products 변수에 데이터를 할당해 주고 있습니다. 이제 async 파이프가 자동으로 products$ 옵저버블을 구독합니다. 구독자로서 async 파이프는 방출된 항목을 수신하여 제공된 변수 products에 할당하고 제품이 UI에 표시됩니다.
여기까지 수고하셨습니다. async로 바꾸고 나서 에러 처리가 없어졌다는거에 대해 눈치 채셨을 겁니다. 에러 핸들링에 대해 다음 포스트에서 다루도록 하겠습니다.
'프로그래밍 > Angular' 카테고리의 다른 글
[RxJS / angular] 11. 옵저버블 에러 처리 전략 (0) | 2022.07.12 |
---|---|
[RxJS / angular] 10. 옵저버블 에러 처리 (catchError, throwError, EMPTY) (0) | 2022.07.08 |
[RxJS / angular] 8. take 연산자 (0) | 2022.07.05 |
[RxJS / angular] 7. tap 연산자, 디버그에 사용하기 (0) | 2022.07.03 |
[RxJS / angular] 6. map 연산자, 마블 다이어그램 읽는 법 (0) | 2022.07.01 |
댓글