Zoneless Angular 설명 — Zone.js 없이 Change Detection이 작동하는 방식
Source: Dev.to
Introduction
수년간 Angular는 Zone.js에 의존해 자동으로 변경 감지를 트리거했습니다. UI를 동기화해 주었지만, 성능이 예측하기 어려워지고 디버깅이 복잡해졌습니다. 특히 Signals가 도입되면서 현대 Angular는 이제 Zone.js 없이도 동작할 수 있습니다.
What Zone.js Actually Did
Zone.js는 다음과 같은 비동기 API들을 몽키패치합니다:
setTimeoutPromisefetch- DOM 이벤트
비동기 작업이 발생할 때마다 Angular는 자동으로 변경 감지를 실행했습니다. 이는 다음을 의미했습니다:
- UI가 항상 동기화됨.
- 관련 없는 컴포넌트라도 모든 비동기 이벤트가 변경 감지를 트리거할 수 있음.
- 특히 대규모 애플리케이션에서 성능 튜닝이 추측에 의존하게 됨.
How Angular Works Without Zone.js
Zone.js를 제거하면 Angular는 더 이상 모든 비동기 이벤트마다 자동으로 변경 감지를 수행하지 않습니다. 대신 애플리케이션 상태가 변경되었을 때 직접 Angular에 알려야 합니다. 변경 감지는 Angular가 데이터가 바뀌었다는 것을 알 때만 실행됩니다. 방법은 다음과 같습니다:
- Signals
- Input 프로퍼티 변경
- 명시적 트리거(예:
ChangeDetectorRef)
Signals Overview
Signals는 Angular가 의존성을 자동으로 추적하도록 하는 반응형 원시 타입입니다.
// signal.ts
import { signal, computed, effect } from '@angular/core';
export class CounterComponent {
count = signal(0);
increment() {
this.count.update(v => v + 1);
}
doubleCount = computed(() => this.count() * 2);
constructor() {
effect(() => {
console.log('Count changed:', this.count());
});
}
}
Count: {{ count() }}
Double: {{ doubleCount() }}
- Signal 업데이트: Angular는 정확히 무엇이 바뀌었는지 알고, 의존하는 뷰만 다시 렌더링합니다.
- 전역 변경 감지 없음: Zone.js가 관여하지 않습니다.
Comparing the Old Zone‑Based Approach with the Zoneless Approach
Zone‑Based Example
// old.component.ts
setTimeout(() => {
this.value = 10; // Angular이 UI를 언제 업데이트할지 추측해야 함
}, 1000);
Zoneless Example Using Signals
// new.component.ts
value = signal(0);
setTimeout(() => {
this.value.set(10); // Signal 업데이트 → Angular 반응 → UI 업데이트
}, 1000);
Bootstrapping Without Zone.js
import { bootstrapApplication } from '@angular/platform-browser';
import { provideZoneChangeDetection } from '@angular/core';
bootstrapApplication(AppComponent, {
providers: [
provideZoneChangeDetection({
eventCoalescing: true,
runCoalescing: true
})
]
});
Zone.js를 완전히 제거하려면:
- 프로젝트에서
zone.jsimport를 삭제합니다. - 상태 변화에는 signals와 명시적 트리거를 사용합니다.
- 필요에 따라
ChangeDetectorRef메서드를 호출해 수동으로 변경 감지를 수행합니다.
Zone.js가 없어도 Angular는 다음을 통해 반응성을 유지합니다:
- Signal 업데이트
- Input 바인딩
- 이벤트 핸들러
- 수동
ChangeDetectorRef호출
When to Go Zoneless
- 대규모 애플리케이션: 결정론적 렌더링과 불필요한 재렌더링 감소가 성능 디버깅을 용이하게 합니다.
- RxJS 사용이 많은 레거시 앱: 트레이드오프를 고려하세요; Zoneless는 선택 사항이며 강제는 아닙니다.
Benefits of the Zoneless + Signals Model
- 결정론적 렌더링 – 실제 데이터가 변한 곳에서만 업데이트가 발생합니다.
- 재렌더링 감소 – 런타임 성능이 향상됩니다.
- 성능 디버깅이 쉬워짐 – 숨겨진 Zone.js 부작용이 없습니다.
- 현대적인 반응형 사고 모델 – 함수형 반응형 프로그래밍 개념과 일치합니다.
Conclusion
Zoneless Angular는 기능을 없애는 것이 아니라 추측을 없애는 것입니다.
- Zone.js는 자동이지만 잡음이 많은 변경 감지를 제공합니다.
- Signals + 명시적 트리거는 명확하고 빠르며 예측 가능한 업데이트를 제공합니다.
모든 곳에서 완전히 Zoneless하게 전환할 필요는 없지만, 그 작동 방식을 이해하면 더 나은 Angular 개발자가 될 수 있습니다.