Angular에서 상태 공유나 이벤트 전달을 위해 RxJS의 Subject 계열을 자주 사용합니다.
그중에서도 Subject와 BehaviorSubject는 사용 빈도가 높지만, 동작 방식이 미묘하게 달라서 쓰는 목적에 맞게 선택해야 합니다.
Subject: 과거는 필요 없고 지금부터가 중요
Subject는 가장 기본적인 RxJS의 멀티캐스트 스트림입니다.
- 멀티캐스트 가능한 Observable
- subscribe() 하기 전까지는 값을 받을 수 없음
- 마지막 값을 저장하지 않음
import { Subject } from 'rxjs';
const subject = new Subject<number>();
subject.next(1); // 구독자 없음 → 아무 일도 일어나지 않음
subject.subscribe(value => console.log('구독자1:', value));
subject.next(2); // 구독자1: 2
- Subject는 구독자가 생기기 전의 값은 전달하지 않아요.
- 즉, 과거 값이 필요한 상황에서는 적합하지 않습니다.
BehaviorSubject: 항상 마지막 값을 기억해요
BehaviorSubject는 Subject를 확장한 형태로, 항상 가장 최신 값을 기억하고, 새로 구독한 구독자에게도 그 값을 즉시 전달합니다.
- Subject를 확장한 것
- 초기값 필수
- 항상 가장 최근 값을 저장하고, 신규 구독자에게 마지막 값 자동 전송
const behavior = new BehaviorSubject<number>(0); // 초기값 0
behavior.next(1); // 값 변경
behavior.subscribe(val => console.log('구독자1:', val)); // 구독자1: 1
behavior.next(2); // 구독자1: 2
- 새로운 구독자라도 항상 가장 최신 값을 받을 수 있음
차이점
| 항목 | Subject | BehaviorSubject |
| 초기값 | 없음 | 필수 |
| 최근 값 저장 | 안함 | 저장함 |
| 신규 구독자 | 과거 값 못 받음 | 최신 값 즉시 수신 |
| 주로 쓰는 곳 | 이벤트 스트림 | 상태 공유 (유저 상태, 폼 등) |
언제 어떤 걸 써야 할까?
| 상황 | 추천 객체 | 이유 |
| 버튼 클릭, 마우스 이벤트 | Subject | 이벤트는 현재만 중요함 |
| 로그인 사용자 정보, 설정값 유지 | BehaviorSubject | 새로운 컴포넌트도 최신 상태 필요 |
| 라우팅된 페이지마다 상태 공유 | BehaviorSubject | 상태를 기억하고 유지해야 함 |
예시: 사용자 로그인 상태 관리
user.service.ts
@Injectable({ providedIn: 'root' })
export class UserService {
private userSubject = new BehaviorSubject<User | null>(null);
get user$(): Observable<User | null> {
return this.userSubject.asObservable();
}
login(user: User) {
this.userSubject.next(user);
}
logout() {
this.userSubject.next(null);
}
}
header.component.ts
export class HeaderComponent implements OnInit {
user$ = this.userService.user$;
constructor(private userService: UserService) {}
ngOnInit() {
this.user$.subscribe(user => {
console.log('로그인된 사용자:', user);
});
}
}
- BehaviorSubject 덕분에 컴포넌트가 중간에 구독하더라도 상태를 놓치지 않습니다.
'개발 공부 > Angular' 카테고리의 다른 글
| Angular의 내장 파이프(Built-in Pipes) (1) (0) | 2025.07.25 |
|---|---|
| Angular 20 - *ngIf, *ngFor, *ngSwitch Deprecation (0) | 2025.07.18 |
| Angular 동적 라우팅 vs 쿼리 파라미터 (0) | 2025.06.01 |
| 앵귤러 동적 라우팅(Dynamic Routing) (0) | 2025.05.31 |
| RxJS 연산자 debounceTime, switchMap, mergeMap (1) | 2025.05.29 |