Angular Signals와 Effects

Angular는 반응성(reactivity)을 처리하는 방식을 변경했습니다. 이제 모든 작은 변화를 감지하기 위해 Zone.js를 사용할 필요가 없습니다. Signals를 사용하면 Angular가 변경된 UI의 특정 부분만 업데이트할 수 있습니다. 이를 통해 앱의 속도가 빨라지고 zoneless 모드를 사용할 수 있습니다.

Signals란 무엇인가요?

Signal은 반응형 값을 담는 컨테이너입니다. 값이 변경되면 Angular는 템플릿의 어느 부분을 업데이트해야 하는지 정확히 알 수 있습니다.

  • signal(): 새로운 signal을 생성합니다. 값을 교체하려면 .set()을 사용하고, 현재 값을 기반으로 값을 변경하려면 .update()를 사용합니다.
  • computed(): 읽기 전용(read-only) signal을 생성합니다. 다른 signal로부터 값을 유도합니다. Angular는 이 값을 읽을 때만 계산하며 결과를 캐싱합니다.
  • effect(): signal이 변경될 때 코드를 실행합니다. 로깅이나 수동 DOM 변경과 같은 사이드 이펙트(side effects)를 위해 사용합니다.

Signals vs RxJS: 언제 무엇을 사용해야 할까요?

하나만 선택할 필요는 없습니다. 서로 다른 작업을 위해 두 가지를 모두 사용해야 합니다.

Signals 사용 권장 상황:

  • UI 상태 유지.
  • 템플릿 렌더링 제어.
  • @Input()@Output() 대체.
  • zoneless 앱 개발.

RxJS 사용 권장 상황:

  • HTTP나 WebSockets와 같은 비동기 스트림 처리.
  • 디바운싱(debouncing)이나 스트림 전환과 같은 복잡한 로직.
  • 여러 이벤트 시퀀스 결합.

rxjs-interop을 사용하여 두 방식을 연결할 수 있습니다:

  • toSignal(): Observable을 Signal로 변환합니다.
  • toObservable(): Signal을 Observable로 변환합니다.

새로운 데코레이터 없는(Decorator-Free) API

Angular 17+ 버전에서는 데코레이터를 사용하지 않고 데이터 흐름을 처리하는 새로운 방식이 도입되었습니다.

  • input(): 부모로부터 전달되는 데이터를 위한 읽기 전용 signal입니다.
  • model(): 양방향 바인딩을 위한 쓰기 가능한(writable) signal입니다. 기존의 @Input()@Output() 패턴을 대체합니다.
  • output(): 자식에서 부모로 이벤트를 방출하는 방법입니다. Signal은 아니지만 코드를 단순화해 줍니다.

React보다 나은 점

React를 알고 있다면 개념은 비슷하지만 실행 방식은 다릅니다.

  • 자동 추적(Automatic Tracking): React에서는 의존성을 배열에 직접 나열해야 합니다. Angular에서는 시스템이 사용 중인 signal을 자동으로 추적합니다. 따라서 의존성을 누락할 일이 없습니다.
  • 정밀한 업데이트(Precision Updates): React는 종종 컴포넌트 전체를 다시 렌더링합니다. Angular signal은 해당 값에 의존하는 특정 DOM 노드만 업데이트합니다.
  • Stale Closure 문제 없음: Signal은 호출 시 항상 최신 값을 제공합니다.

Source: https://dev.to/atilla_baspinar_c5c68ec63/angular-signals-and-effects-35mn