스마트 로더 구현: Angular에서 UX 개선을 위한 RxJS 패턴
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
- Angular 개발자 : API 로딩 상태 관리 및 UX 개선에 관심 있는 중급 이상 개발자
- 난이도 : 중급 (RxJS와 Angular 결합 개념 필요)
핵심 요약
- 로더 표시 지연 시간 :
200ms
이전에는 로더 표시 금지 (timer(200)
) - 최소 표시 시간 보장 : 로더가 보여진 후
2초
동안은 반드시 표시 (timer(2000)
) - API 완료 후 로더 숨기기 :
combineLatest
로isLoading$
과 타이머 조합하여 조건 처리 - 핵심 API :
timer()
,combineLatest()
,distinctUntilChanged()
섹션별 세부 요약
1. 문제 정의: 로더의 UX 문제점
- 불쾌한 플래시 효과 : 너무 빠르게 로더 표시 시 발생
- 불안정한 UX : API 처리 완료 전에 로더 숨기면 사용자 혼란 유발
- 해결 방향 : 로더 표시/숨김 조건을 타이머와 API 상태 결합
2. RxJS 기반 솔루션 구현
- 200ms 지연 타이머
```ts
const _passed200ms = timer(200).pipe(
map(() => true),
startWith(false)
);
```
- 2초 최소 표시 시간 타이머
```ts
const _passed2sDisplay = timer(2000).pipe(
map(() => true),
startWith(false)
);
```
- Observable 결합 로직
```ts
function uiLoading$(isLoading$: Observable
return combineLatest([_passed200ms, _passed2sDisplay, isLoading$]).pipe(
map(([passed200ms, passed2sDisplay, isApiStillLoading]) => {
if (!passed200ms) return false;
if (isApiStillLoading) return true;
if (isApiStillLoading === false && passed2sDisplay) return false;
return false;
}),
distinctUntilChanged()
);
}
```
3. 예제 사용 시나리오
- 5초 지연 API 호출
```ts
uiLoading$(
of('data').pipe(
delay(5000),
map(() => false),
startWith(true)
)
).subscribe(result => console.log('result', result));
```
- 50ms, 1.5초 지연 시 테스트
```ts
uiLoading$(
of('data').pipe(
delay(50),
map(() => false),
startWith(true)
)
).subscribe(result => console.log('result', result));
```
결론
- 템플릿에서 직접 observable 구독을 권장 (로더 자동 반응)
combineLatest
+distinctUntilChanged
패턴으로 반응형 로더 구현 가능- UX 개선 효과 : 플래시 방지 및 로딩 시간 인식 향상
- 확장성 : 앵귤러 컴포넌트 내 재사용 가능 (stateless 구조)