운영자 매뉴얼: v17.3에서 v21까지 Angular Signals 탐색
I’m ready to translate the article for you, but I’ll need the text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link at the top exactly as you provided and preserve all formatting, markdown, and code blocks.
버전 1.0
| Section | Title |
|---|---|
| 1.1 | Signal‑Based Components: The Full Toolkit |
| 1.2 | Operating with output() and RxJS Interop |
| 2.1 | From Preview to Prime Time: Graduating to Stable |
| 2.2 | The Signal‑Powered Service Pattern |
| 2.3 | Enabling the Zoneless Future |
| 3.1 | Introducing Signal Forms: A Paradigm Shift |
| 3.2 | Advanced Operations: Async Data and Linked State |
| 4.1 | Core Principles of Signal‑Based Code |
| 4.2 | Upgrading Your Machinery: The Migration Path |
| 4.3 | Migration Checklist: A Step‑by‑Step Guide |
| 4.4 | Adopt signal components – Replace async pipes with direct signal calls |
| 4.5 | Refactor services from BehaviorSubject to signals |
| Conclusion | A New Era of Angular Reactivity |
| References | — |
Introduction
환영합니다, 운영자님. 여러분은 깊은 변화를 겪은 기계의 열쇠를 받았습니다. Angular에서 새로운 반응형 원시 요소로 시작된 것이 이제는 애플리케이션 상태를 구축하고 관리하며 생각하는 방식을 재정의하는 완전 통합 시스템으로 진화했습니다. 이 매뉴얼은 v17.3의 기본 API부터 v21의 실험적 최전선까지 Angular Signals의 진화를 마스터하기 위한 안내서입니다. 반응성에 대한 이해를 재조정할 준비를 하세요.
1️⃣ Angular 17.3 – 최초의 완전 데코레이터‑없는 릴리스
Angular 17.3은 완전 데코레이터‑없는, 시그널 기반 컴포넌트를 만들기 위한 퍼즐의 마지막 조각을 제공했습니다.
- 17.3 이전에도 Angular는 inputs(
input())와 queries(viewChild())에 대한 시그널 기반 대안을 이미 제공하고 있었습니다. - 컴포넌트 outputs는 여전히 전통적인
@Output()데코레이터와EventEmitter에 의존했습니다.
1.1 output() – 새로운 기본형
Angular 17.3은 output() 함수를 도입하여, 모든 공개 API—inputs, outputs, queries—가 함수로 정의되는 컴포넌트를 작성할 수 있게 했습니다. 이는 일관된 데코레이터‑없는 경험을 제공하고, 다른 시그널 기반 API와 개념적으로 일치합니다.
// Before: Angular ();
onClick() {
this.clicked.emit();
}
// After: Angular 17.3+
import { Component, output } from '@angular/core';
@Component({ /* … */ })
export class SignalButtonComponent {
clicked = output();
onClick() {
this.clicked.emit();
}
}
output()은 가볍고 RxJS에 의존하지 않는 이벤트 방출 방식을 제공합니다. EventEmitter가 RxJS의 Subject를 확장한 반면, output()이 반환하는 새로운 OutputEmitterRef는 더 단순하고 목적에 맞게 설계된 기본형입니다.
2️⃣ RxJS Interop
Angular 팀은 방대한 RxJS‑기반 코드 생태계를 위한 브리지를 @angular/core/rxjs-interop 패키지를 통해 제공했으며, 현재 다음을 포함합니다:
| Utility | Purpose |
|---|---|
outputFromObservable() | RxJS 스트림을 컴포넌트 출력으로 변환 |
outputToObservable() | 컴포넌트 출력을 다시 RxJS 옵저버블로 변환 |
이 유틸리티들은 기존 반응형 로직을 완전히 재작성할 필요 없이 원활하고 점진적인 마이그레이션을 가능하게 합니다.
3️⃣ Angular 18 – 20 – 신호 강화 및 새로운 아키텍처 패턴
Angular 18부터 20까지의 기간은 신호 API를 안정화하고 새로운 아키텍처 패턴을 구축하는 데 초점을 맞췄습니다.
- 안정적인 프리미티브:
input(),model()(양방향 바인딩) 및 신호 기반 쿼리(viewChild(),contentChildren())가 개발자 프리뷰에서 안정 버전으로 승격되었습니다. - v20 마일스톤: 모든 기본 반응성 프리미티브가 안정화되어 기업이 장기적으로 신호를 도입할 수 있는 신뢰를 얻었습니다.
3.1 Signal‑In‑A‑Service 패턴
서비스에서 BehaviorSubject를 사용하는 대신, 개발자는 이제 signal‑in‑a‑service 접근 방식을 채택합니다:
import { Injectable, signal, computed } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class ItemService {
// Private, writable signal
private _items = signal([]);
// Public, readonly signal
readonly items = this._items.asReadonly();
// Computed signal for derived state
readonly total = computed(() => this._items().length);
// Public method to mutate state
addItem(item: string) {
this._items.update(items => [...items, item]);
}
}
이점
- 깔끔한 단방향 데이터 흐름 – 서비스가 단일 진실 소스가 됩니다.
- 소비자는 데이터를 변형하지 않고 상태 변화에 반응합니다.
- 신호의 동기식 특성 덕분에 테스트 용이성이 향상되고 RxJS Subject와 구독에 수반되는 보일러플레이트가 사라집니다.
3.2 Zoneless 미래
전통적인 Angular는 Zone.js에 의존해 비동기 작업 후 변경 감지를 트리거합니다. 편리하지만 비효율적일 수 있습니다.
- 신호는 세분화된 의존성 그래프를 제공 – Angular는 어떤 컴포넌트/계산값이 변경된 신호에 의존하는지 정확히 파악하고 해당 부분만 업데이트합니다.
- Zoneless 모드는 Angular v20.2에서 안정화되었으며 Angular v21에서는 기본값이 되었습니다.
장점
- 번들 크기 감소.
- 런타임 성능 향상.
- 애플리케이션 동작이 보다 예측 가능해짐.
4️⃣ Angular 21 – 다음 진화
핵심 프리미티브가 안정화된 상태에서, Angular 21은 복잡한 웹 개발 과제(예: 시그널 폼, 비동기 데이터 처리, 연결된 상태)를 해결하는 시그널 기반 도구들의 풍부한 생태계를 탐구합니다. 이러한 도구들은 단순한 상태 관리 이상으로 시그널 패러다임을 확장하여, 개발자들이 통합된 리액티브 모델을 사용해 고성능·유지보수가 쉬운 애플리케이션을 구축할 수 있게 합니다.
5️⃣ 마이그레이션 체크리스트 – 단계별 가이드
| ✅ 단계 | 작업 |
|---|---|
| 1 | 모든 컴포넌트에서 @Input()을 input()으로 교체합니다. |
| 2 | @Output()을 output()으로 교체합니다. |
| 3 | EventEmitter 기반 출력들을 output()으로 변환하고, RxJS 연동이 필요할 경우 outputFromObservable() / outputToObservable()를 사용합니다. |
| 4 | 서비스를 리팩터링: BehaviorSubject/ReplaySubject를 private writable signals(signal())로 교체하고 readonly/computed signals를 노출합니다. |
| 5 | 템플릿 업데이트: async 파이프를 직접 신호 호출({{ mySignal() }})로 교체합니다. |
| 6 | zoneless 모드를 활성화(enableProdMode(); setZoneEnabled(false);)하고 변경 감지 동작을 테스트합니다. |
| 7 | Angular 마이그레이션 스키매틱을 실행합니다(ng update @angular/core@21). |
| 8 | 단위 및 통합 테스트를 검증하고, RxJS 구독 부수 효과에 의존하던 테스트를 조정합니다. |
| 9 | 성능 지표를 검토하고, 번들 크기 감소 및 CD 사이클 개선을 보장합니다. |
| 10 | 팀을 위한 새로운 패턴을 문서화하고 온보딩 자료를 업데이트합니다. |
결론
Signals는 Angular를 zone‑centric, RxJS‑heavy framework에서 fine‑grained, declarative, and performant platform으로 변모시켰습니다. signal‑based API를 수용하고, signal‑in‑a‑service 패턴을 채택하며, zoneless mode를 활성화함으로써 여러분은 애플리케이션을 차세대 웹 개발을 위한 위치에 놓게 됩니다.
References
- Angular 공식 문서 – Signals (v17‑v21)
- Angular 로드맵 – 반응성 및 Zoneless 업데이트
@angular/core/rxjs-interopAPI 문서- 데모 저장소: https://github.com/leolanese/Angular-Zoneless-Signals
Signals in Angular – A Glimpse of the Future
Experimental signals offer a preview of a future where reactivity is seamlessly integrated into every part of the framework.
The New Signal Forms API (Angular 21)
Available experimentally via
@angular/forms/signals.
Signal Forms flip the script: instead of building a form structure to match your data, you start with your data model and let the form derive itself reactively.
Model‑First Approach
// Define the data model as a signal
user = signal({ firstName: '', email: '' });
// Create the form from the model
profileForm = form(this.user, (path) => [
// …validation rules
]);
Declarative Validation
Validation rules are defined as functions inside the form’s schema:
- Built‑in validators (
required,minLength,email) - Conditional validation (
whenproperty) - Cross‑field validation
This replaces the imperative logic of adding/removing validators in traditional forms.
Simplified Template Binding
The old formControlName is replaced by a new [field] directive, creating a direct, type‑safe link between the template and the form‑field signal.
Built‑in Submission Handling
submit() manages the submission process, automatically handling loading states (submitting()) and server‑side errors, which can be mapped directly back to form fields.
Result: Drastically reduced boilerplate, improved type safety, and more intuitive, maintainable validation logic.
Other Experimental Signal‑Based Tools
| Tool | Description |
|---|---|
Resource API (resource, rxResource) | Declarative async data fetching. A resource re‑fetches when dependent signals (e.g., params) change and provides built‑in signals for loading, error, and value states. |
linkedSignal() | An advanced primitive that is writable (unlike a read‑only computed()). It derives its initial value from a source signal but can also be updated manually—useful for scenarios such as a dropdown that resets when its options change yet still allows manual selection. |
Chapter 4 – The Operator’s Field Guide: Best Practices & Migration
새 시스템을 마스터하려면 그 시스템의 작동 규칙을 이해해야 합니다. 이 장에서는 기존 장비를 업그레이드하기 위한 핵심 원칙과 전략적 계획을 제공합니다. 이러한 모범 사례를 따르면 신호 기반 애플리케이션을 성능 좋게, 예측 가능하게, 그리고 유지 보수하기 쉽게 만들 수 있습니다.
Core Rules
- 파생 상태에는
computed()사용 – 가장 중요한 규칙입니다. 값이 하나 이상의 신호에서 계산되는 경우 항상computed()를 사용하세요. 다른 신호를 설정하기 위해effect()를 사용하는 것은 성능 문제와 예기치 않은 동작을 초래할 수 있는 안티패턴이므로 피합니다. - 부수 효과에는
effect()만 사용 – 신호가 아닌 세계(예: 로깅,localStorage동기화, 커스텀 DOM 조작)와 연결할 때 사용합니다. 효과는 비동기적으로 실행된다는 점을 기억하세요. - 상태는 평탄하게 유지 – 신호를 다른 신호 안에 중첩하거나 깊은 객체 구조에 넣지 마세요. 평탄한 상태 구조는 추적이 쉽고 변경 감지 효율도 높아집니다.
4.2 Upgrading Your Machinery & Migration Path
Generate Migration Schematics
# Migrate @Input() to signal inputs
ng generate @angular/core:signal-input-migration
# Migrate @Output() to signal outputs
ng generate @angular/core:signal-output-migration
# Migrate @ViewChild/@ContentChild queries
ng generate @angular/core:signal-queries-migration
Adopt the Experimental Signal Forms API
-
마이그레이션하려는 기존 Reactive Form을 식별합니다.
-
데이터 모델에 대한 신호를 정의합니다:
user = signal({ name: '', email: '' }); -
신호 폼을 생성합니다:
profileForm = form(this.user, /* schema */); -
템플릿을 업데이트합니다 –
formControlName을[field]디렉티브로 교체합니다. -
명령형 검증을
form()함수 내부의 선언형 규칙으로 대체합니다.
Angular 17.3의 새로운 기능 – Gergely Szerovay 작성
- 새로운
output()API - RxJS 인터옵 헬퍼 (
outputFromObservable,outputToObservable) HostAttributeToken- TypeScript 5.4 지원
Angular Signal‑Based Architecture: 더 똑똑한 쇼핑 카트 만들기
“signal‑in‑a‑service” 패턴을 사용해 상태가 무거운 기능을 리팩터링하는 실용적인 가이드로, 더 깔끔하고 테스트하기 쉬우며 성능이 뛰어난 애플리케이션을 구현합니다.
Angular Signal‑Based Forms: 폼 처리에 대한 모든 인식을 바꿀 이유
Angular 21의 실험적인 Signal Forms API를 미리 살펴보며, 모델‑우선 설계, 선언적 검증, 타입‑안전 템플릿 바인딩을 강조합니다.
리소스
- Reactive Angular: Loading Data with the Resource API – 실험적인
resource와httpResource프리미티브를 소개하며, 로딩, 오류, 값 상태를 위한 내장 시그널을 사용해 비동기 데이터 스트림을 관리합니다. - Dependent state with
linkedSignal– Angular Official Guide –linkedSignal()에 대한 문서로, 소스가 변경될 때 리셋되는 쓰기 가능한 계산형 시그널이며, 종속 드롭다운 같은 동적 UI 컨트롤에 이상적입니다. - Angular Signals
Effect(): Why 90% of Developers Use It Wrong –effect()와 관련된 흔한 안티패턴을 명확히 하고, 로깅,localStorage, DOM 변형 등 부수 효과에만 사용해야 함을 강조합니다. - Angular Roadmap – Official angular.dev – Angular의 전략적 우선순위에 대한 정식 출처로, Signals, zoneless Angular, Signal Forms, HMR, 테스트 도구 및 향후 탐색에 대한 상태 업데이트를 포함합니다.
- Meet Angular’s new
output()API – Angular Blog – Angular 17.3에서 도입된output()함수에 대한 공식 발표로, 타입 안전성, 시그널 입력과의 정렬,outputFromObservable()및outputToObservable()을 통한 RxJS 인터옵을 설명합니다. - Angular v21 Goes Zoneless by Default: What Changes, Why It’s Faster, and How To – Angular v21에서 기본으로 zoneless 변경 감지가 적용되는 심층 분석으로, 성능 향상, 번들 크기 감소, 마이그레이션 단계 및 주의사항을 다룹니다.
연결해요!
- LinkedIn: LeoLanese
- Twitter: @LeoLanese
- Blog: Dev.to
- Contact: developer@leolanese.com