switchMap을 사용하여 데이터 로딩 상태를 나타내는 방법은 무엇인가요?
_____A1: switchMap 내부에서 데이터 요청 Observable을 실행하기 전에 로딩 상태를 true로 설정하고, 데이터가 반환되거나 에러가 발생하거나 완료되었을 때 로딩 상태를 false로 설정하면 됩니다. 이를 위해 `tap` 연산자나 `finalize` 연산자를 함께 사용하는 것이 일반적입니다.
---
Q2: 간단한 예제 코드를 보여줄 수 있나요?
A2: 네, 다음과 같이 작성할 수 있습니다.
```typescript
import { BehaviorSubject, Subject, of } from 'rxjs';
import { switchMap, tap, finalize, catchError } from 'rxjs/operators';
// 로딩 상태를 나타내는 BehaviorSubject
const loading$ = new BehaviorSubject
// 데이터 요청 트리거
const loadTrigger$ = new Subject
loadTrigger$.pipe(
tap(() => loading$.next(true)), // 요청 시작 시 로딩 true 설정
switchMap(() =>
fetchData().pipe(
catchError(error => {
// 에러 처리 후 빈 Observable 반환 or 다른 처리
console.error(error);
return of(null);
}),
finalize(() => loading$.next(false)) // 요청 종료 시 로딩 false 설정
)
)
).subscribe(data => {
// 받은 데이터 처리
console.log(data);
});
// 데이터 요청 함수 예시
function fetchData() {
return of('데이터').pipe(
// 실제 HTTP 요청 Observable 대체
);
}
```
---
Q3: 왜 finalize를 사용하는 것이 좋은가요?
A3: `finalize` 연산자는 Observable이 완료되거나 에러가 발생해 종료될 때 항상 실행되므로, 로딩 상태를 해제하는 코드를 중복 없이 한곳에서 관리할 수 있어 실수를 줄여줍니다.
---
Q4: tap으로만 처리하면 안 되나요?
A4: `tap`만 사용하면 데이터 요청이 성공했을 때만 로딩 상태를 변경할 수 있고, 에러나 완료에도 로딩 상태를 false로 만들어 주려면 분기 처리를 여러군데 해야 하므로 코드가 복잡해집니다. 따라서 `finalize`와 같이 종료 시점을 한꺼번에 처리하는 연산자가 더 효과적입니다.
---
Q5: Angular에서 HttpClient와 switchMap을 사용할 때도 동일하게 적용할 수 있나요?
A5: 네, Angular의 HttpClient로 반환되는 Observable에도 동일하게 `switchMap`, `tap`, `finalize` 조합을 적용해 로딩 표시를 쉽게 구현할 수 있습니다.
---
Q6: UI에서는 어떻게 로딩 상태를 구독하나요?
A6: 로딩 상태를 관리하는 `loading$` Observable을 Angular 템플릿에서 `*ngIf="loading$ | async"` 같은 형태로 바인딩해서 로딩 스피너 등을 보여줄 수 있습니다.
---
요약:
switchMap 사용 시, 데이터 요청 직전에 로딩 상태를 true로 바꾸고 (`tap`), 요청 완료/에러 시 항상 false로 변경하는 (`finalize`) 패턴을 사용하면 깔끔하고 안정적으로 로딩 상태를 관리할 수 있습니다.
비동기 데이터 로딩 작업을 처리할 때도 자주 활용되죠. 데이터 로딩 상태(예: 로딩 중, 성공, 실패 등)를 `switchMap`과 함께 표현하는 방법에 대해 자세히 설명드리겠습니다.
--- 상황 설명 예를 들어, 사용자가 입력한 검색어를 기반으로 API 데이터를 요청한다고 가정해볼게요. 이때 사용자는 빠르게 여러 번 입력할 수 있고, 각 요청이 비동기로 처리되기 때문에 가장 최근 입력에 대한 요청 결과만 보여줘야 합니다.
또한 요청이 시작되면 "로딩 중" 표시를 하고, 요청이 완료되면 데이터를 화면에 보여주며, 만약 에러가 발생하면 에러 메시지를 출력해야 합니다.
이 상황에서 `switchMap`과 로딩 상태 표현을 어떻게 조합할지 설명합니다.
1. 기본 아이디어 - 로딩 시작 : 새로운 입력이 들어오고 API 호출이 시작되면 로딩 상태를 `true`로 설정한다.
- 응답 도착 / 실패 : 요청 완료 시(성공/실패)에 로딩 상태를 `false`로 변경한다.
---
2. 구현 방법 방법 A: 별도의 상태 관리 (예: BehaviorSubject) 사용하기 - `loading$` 라는 별도의 Subject나 BehaviorSubject를 만든다. - 검색어 스트림이 새로운 값이 들어올 때마다 로딩 상태를 `true`로 변경한다.
- `switchMap` 내부 API 호출 Observable이 완료되거나 에러 시 `loading$` 를 `false`로 변경한다.
```typescript import { Subject, BehaviorSubject, of } from 'rxjs'; import { switchMap, tap, catchError } from 'rxjs/operators'; const searchTerms$ = new Subject
--- 방법 B: 상태를 객체 형태로 묶어서 반환하기 Observable 데이터가 `{ loading, data, error }` 같은 객체 형태로 값을 내보내도록 만들어 컴포넌트가 구독하면 한 주체로 상태 관리가 가능합니다.
```typescript import { of } from 'rxjs'; import { switchMap, startWith, catchError, map } from 'rxjs/operators'; const searchTerms$ = new Subject
이 방식은 하나의 스트림에서 로딩 상태, 데이터, 에러를 관리할 수 있다는 장점이 있습니다.
---
3. 요약 및 주의사항 - `switchMap` 사용 시 내부 Observable이 전환될 때 이전 호출이 취소되므로, 항상 가장 최신 API 요청 결과만 처리한다.
- 로딩 상태는 `switchMap` 직전에 변경하거나, API 호출 Observable 내부에서 상태를 갱신한다.
- 에러 상황도 반드시 처리하여 로딩 상태가 무한히 로딩 중인 상태로 빠지지 않도록 주의해야 한다.
- 상황에 따라 별도의 상태 스트림(`loading$`)을 두거나 하나의 상태 객체를 내보내는 방식 중 선택한다.
--- 이와 같이 `switchMap`을 활용하면 사용자 입력에 따른 빠른 비동기 처리와 상태 관리가 간결하게 구현 가능합니다.
작성자:
정하린 [비회원]
| 작성일자: 1년 전
2025-05-25 12:51:51
조회수: 187 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
조회수: 187 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.