앵귤러 22: 보일러플레이트의 종말? 진짜 반응형 시대가 온다!
2026. 8. 12.
앵귤러 22: 보일러플레이트의 종말? 진짜 반응형 시대가 온다!
지난 몇 년간 구글 앵귤러 프레임워크의 변화를 꾸준히 지켜봐 왔다면, 여러분도 아마 조용하지만 꾸준한 재구축 과정이 진행 중이었다는 걸 알고 계실 겁니다. 2026년 6월 3일, 앵귤러 22가 마침내 공개되면서 이 재구축은 더 이상 미래의 약속이 아니라 새로운 표준으로 자리 잡았습니다. 단순히 몇 가지 실험적인 기능이 추가된 수준이 아닙니다. 완전히 새롭게 재고된 생태계가 이제야 비로소 견고하게 자리 잡았다는 의미입니다.
엔터프라이즈 애플리케이션, 클린 아키텍처, 그리고 마이크로프론트엔드 생태계 속에서 살아 숨 쉬는 개발자들에게 앵귤러 22는 앵귤러 16부터 약속했던 바를 마침내 실현한 버전입니다. 즉, 진정한 종단간 반응형 프레임워크이자, 본질적으로 Zone.js에 의존하지 않으며, 개발 과정에서 불필요한 의식(ceremony)이 훨씬 줄어든 모습으로 돌아온 거죠.
이제 실험은 끝났습니다. 아래에서는 어떤 것들이 실제로 바뀌었는지, 그리고 ng update를 실행하기 전에 여러분이 무엇을 해야 할지 자세히 알아보겠습니다.
📖 앵귤러가 처음이라면: 이 글에 등장하는 여러 기술 용어(변경 감지, 시그널, SSR, 의존성 주입, 마이크로프론트엔드 등)는 글 마지막의 용어집에서 설명되어 있습니다. 글을 처음부터 끝까지 읽고, 궁금한 점이 생길 때마다 용어집을 참고하세요.
앵귤러 22에 추가된 주요 변경 사항
OnPush가 새로운 기본 변경 감지 전략이 되었습니다 (기존Default는Eager로 이름이 바뀌었으며 이제 사용이 권장되지 않습니다).- 안정화된 리소스 API:
resource,rxResource,httpResource가 프로덕션 환경에 바로 투입될 준비를 마쳤습니다. - 안정화된 시그널 폼: 서브미션 API, 동적 스키마 (Zod/Valibot 지원), 그리고 반응형 폼과의 상호 운용성을 자랑합니다.
- 새로운
@Service()데코레이터:@Injectable({ providedIn: 'root' })를 더 간결하게 사용할 수 있게 합니다. injectAsync: 지연(lazy) 의존성 주입을 위한 기능으로,onIdle을 통한 사전 가져오기(prefetch)를 지원합니다.debounced: 시그널/리소스에 네이티브 디바운스 기능을 제공합니다.- 점진적 하이드레이션: 기본적으로 활성화됩니다.
HttpClient: 기본적으로FetchBackend를 사용합니다 (withFetch()는 이제 사용이 권장되지 않습니다).- 마이크로프론트엔드를 위해 설계된 라우터 및 부트스트랩 기능의 중요한 개선 사항이 포함되었습니다.
1. OnPush, 새로운 기본 변경 감지 전략으로 등극
커뮤니티가 항상 원해왔던 순간이 드디어 왔습니다. 이제 ChangeDetectionStrategy.OnPush는 모든 새 컴포넌트의 기본 동작이 됩니다. 시그널 중심의 세상에서 이 결정은 완벽하게 합리적입니다. 시그널을 사용하는 개발자는 무엇이 변경되었는지에 대한 정밀한 알림을 이미 받고 있으며, OnPush는 이 이점을 최대한 활용하여 전체 트리를 스캔하는 대신 실제로 영향을 받은 컴포넌트만 확인합니다.
기존의 Default 전략 (전체 트리를 검사하는 방식)은 Eager로 이름이 바뀌었고 이제 사용이 권장되지 않습니다. 만약 컴포넌트에서 이전 동작이 여전히 필요하다면, 명시적으로 선언해야 합니다.
import { ChangeDetectionStrategy, Component } from '@angular/core';
@Component({
selector: 'app-legacy',
changeDetection: ChangeDetectionStrategy.Eager, // 기존 'Default' 대체
template: `...`,
})
export class LegacyComponent {}
마이그레이션을 위한 중요 사항: ng update 과정에서 앵귤러가 명시적인 전략을 찾지 못하면, 아무것도 망가지지 않도록 자동으로 Eager를 적용합니다. 즉, 성능 향상이 "공짜"로 주어지는 것은 아닙니다. OnPush의 이점을 누리려면 컴포넌트별로 직접 마이그레이션해야 합니다. 실제로 제가 수백 개의 컴포넌트를 OnPush로 전환하며 겪었던 고생을 생각하면, 이번 ng update의 Eager 자동 적용은 개발자에게 엄청난 심리적 안전망이 되어줄 겁니다.
2. 안정화된 리소스 API 및 httpResource
리소스 API는 시그널 퍼즐의 마지막 조각이었습니다. 시그널이 변경될 때 주로 HTTP 요청을 트리거하여 비동기 데이터를 반응적으로 파생시키는 역할을 합니다. 이제 resource, rxResource, httpResource가 안정화되어 프로덕션 환경에 사용될 수 있습니다.
가장 편리한 진입점은 httpResource입니다. 요청을 반환하는 반응형 람다를 인자로 받는데, 람다 내에서 사용된 시그널이 변경되면 요청이 자동으로 다시 실행됩니다.
import { httpResource } from '@angular/common/http';
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { Flight } from './flight';
@Component({
selector: 'app-flight-search',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
@if (flightsResource.isLoading()) {
<div>로딩 중…</div>
} @else if (flightsResource.error()) {
<div>에러: {{ flightsResource.error() }}</div>
} @else {
@for (flight of flightsResource.value(); track flight.id) {
<app-flight-card [item]="flight" />
}
}
`,
})
export class FlightSearch {
protected readonly filter = signal({ from: '서울', to: '부산' }); // 예시 지역명 변경
protected readonly flightsResource = httpResource<Flight[]>(
() => ({
url: 'https://api.example.io/flight',
params: { from: this.filter().from, to: this.filter().to },
}),
{ defaultValue: [] }, // 초기화 시 `undefined` 처리 방지
);
protected reload(): void {
this.flightsResource.reload();
}
}
리소스는 value, error, isLoading과 같은 시그널을 통해 자체 상태를 관리하며, 더 자세한 상태 (idle, loading, reloading, error, resolved, local)도 제공합니다. 가장 좋은 점은 경쟁 조건(race conditions)이 자동으로 처리된다는 것입니다. 여러 요청이 연달아 들어와도 가장 최근 요청의 결과만 사용됩니다. 이는 RxJS의 switchMap과 정확히 같지만, 여러분이 단 한 줄의 파이프 코드도 작성할 필요가 없습니다. 실제로 제가 switchMap을 활용해 복잡한 리소스 관리 로직을 구현했던 프로젝트를 돌이켜보면, httpResource는 개발자의 머리를 훨씬 가볍게 해줄 겁니다.
특정 조건에서 요청을 건너뛰고 싶다면, 람다에서 undefined를 반환하기만 하면 됩니다.
3. 시그널 폼, 프로덕션 준비 완료
반응형 폼과 템플릿 기반 폼 사이의 오랜 논쟁은 이제 끝났습니다. 시그널 폼이 실험적인 단계를 벗어나 폼을 다루는 권장 접근 방식으로 자리 잡았습니다. 선언적이고, 강력한 타입 검사를 지원하며, 시그널을 통해 반응적으로 동작합니다.
API의 핵심은 form 함수이며, 데이터 시그널과 유효성 검사 스키마를 인자로 받습니다.
import { form, minLength, required } from '@angular/forms/signals';
protected readonly flightForm = form(this.flight, (path) => {
required(path.from);
required(path.to);
required(path.date);
minLength(path.from, 3);
});
결과물은 FieldTree입니다. 이는 중첩된 시그널 구조로, 각 필드는 value, dirty, invalid, errors를 노출합니다. 템플릿에서는 FormField 디렉티브를 사용합니다.
<input [formField]="flightForm.from" id="flight-from" />
<div>{{ flightForm.from().errors() | json }}</div>
여기서 끝이 아닙니다. 앵귤러 22는 (21.1, 21.2 버전에서 추가된 기능들과 함께) 놀랍도록 완벽한 폼 스택을 가져왔습니다.
- 서브미션 API (
FormRoot+ submit): 서버로부터의 유효성 검사 오류를 폼 상태로 다시 매핑하는 기능을 포함하여, 모든 제출 로직이 폼 자체 내에 포함됩니다. - Zod 및 Valibot과 호환되며 시그널이 변경될 때 재평가되는
validateStandardSchema를 통한 동적 스키마 지원. provideSignalFormsConfig를 통한 조건부 CSS 클래스 (ng-valid,ng-invalid,ng-dirty...) 지원.compatForm및SignalFormControl을 통한 반응형 폼과의 상호 운용성, 전면적인 재작성 없이 점진적으로 마이그레이션할 수 있습니다.
4. 새로운 @Service() 데코레이터
매일 감사하게 될 인체공학적 개선 중 하나입니다. @Service()는 가장 흔한 주입 케이스인 @Injectable({ providedIn: 'root' })의 반복적인 작성을 간결하게 줄여줍니다.
import { Service } from '@angular/core';
@Service()
export class FlightClient {
// 기본적으로 root에 제공됩니다. 의도가 명확해집니다.
}
자동으로 루트에 제공되는 것을 원하지 않는다면, autoProvided: false로 비활성화하고 수동으로 프로바이더를 제공할 수 있습니다 (예: app.config.ts, 컴포넌트, 또는 라우트에서).
@Service({ autoProvided: false })
export class TabRegistry {}
중요: @Service()는 @Injectable()를 대체하지 않습니다. 이는 가장 빈번한 케이스를 위한 단축키입니다. 더 복잡한 프로바이더 설정이 필요한 곳에서는 여전히 @Injectable()이 올바른 도구입니다. 클린 아키텍처에서는 @Service()가 인프라 어댑터 계층을 훨씬 간결하게 만들 수 있지만, 맹목적인 대체재가 아닌 신중하게 사용해야 합니다.
5. injectAsync: 지연 의존성 주입
이 기능은 번들 사이즈와 초기 로딩 시간으로 고통받는 모든 개발자에게 선물과 같습니다. injectAsync를 사용하면 실제로 필요할 때만 의존성을 주입할 수 있습니다. 무거운 라이브러리를 로드하고 특정 사용자 동작 이후에만 개입하는 서비스에 이상적입니다.
import { injectAsync } from '@angular/core';
@Component({ /* ... */ })
export class CheckinPage {
private readonly upgradeService = injectAsync(() =>
import('./upgrade-service').then((m) => m.UpgradeService),
);
protected async upgrade(): Promise<void> {
const service = await this.upgradeService();
service.upgrade(/* ... */);
}
}
임포트, 즉 번들 로딩은 첫 번째 호출 시에만 발생합니다. 첫 호출의 지연을 피하려면 prefetch 옵션을 onIdle (브라우저가 유휴 상태일 때 로드)과 함께 사용하여 미리 로드할 수 있습니다. 개인적으로 대규모 엔터프라이즈 앱에서 초기 번들 사이즈 최적화로 밤새워 씨름했던 경험이 많은데, injectAsync는 그런 개발자들에게 가뭄의 단비와 같은 존재가 될 것입니다.
import { injectAsync, onIdle } from '@angular/core';
private readonly upgradeService = injectAsync(
() => import('./upgrade-service').then((m) => m.UpgradeService),
{ prefetch: onIdle }, // 브라우저가 유휴 상태일 때 로드
);
한 가지 기억할 점은, 지연 로딩이 작동하려면 주입될 서비스가 자동 제공되어야 한다는 것입니다 (예: @Service() 또는 @Injectable({ providedIn: 'root' })를 통해).
6. debounced: 시그널을 위한 네이티브 디바운스
시그널은 본질적으로 시간에 대한 개념이 없습니다. debounceTime이나 throttle 같은 기능이 없죠. 앵귤러 22는 debounced 함수로 이 문제를 해결했습니다. 이 함수는 정의된 지연 시간 이후에 값이 업데이트되는 리소스를 생성합니다.
import { debounced } from '@angular/core';
const filter = signal('');
const debouncedFilter = debounced(filter, 300); // 300ms
effect(() => console.log(debouncedFilter.value()));
폼의 경우, 디바운스는 이미 시그널 폼에 내장되어 있습니다. debounced는 그 외의 모든 상황을 커버합니다.
7. 점진적 하이드레이션 기본 활성화
성능에 초점을 맞춰, 이제 점진적 하이드레이션은 provideClientHydration()을 통해 기본적으로 활성화됩니다. SSR을 사용하는 애플리케이션의 경우, 이는 초기 로딩에서 실질적인 이득을 가져다줍니다. 모든 것을 한 번에 하이드레이션하는 대신 필요에 따라 컴포넌트를 하이드레이션하기 때문입니다. 어떤 이유로든 이 기능을 원하지 않는다면, withNoIncrementalHydration()을 통해 명시적으로 비활성화할 수 있으며, 이를 돕는 마이그레이션 스키마도 제공됩니다.
8. HttpClient, 이제 FetchBackend를 기본으로 사용
눈에 띄지 않지만 마이그레이션에 실제 영향을 미치는 변화입니다. HttpClient는 이제 Fetch API를 기본적으로 사용합니다. 이는 withFetch()가 이제 사용이 권장되지 않으며 제거될 수 있다는 것을 의미합니다.
주의할 점은 요청 진행 상황 추적에 있습니다. 기존의 reportProgress는 두 가지 전용 옵션으로 대체되었으며, 업로드 진행 상황은 XHR을 필요로 합니다.
// 다운로드 (Fetch와 함께 작동)
http.get('/large-file', { reportDownloadProgress: true, observe: 'events' });
// 업로드 (withXhr() 필요)
http.post('/upload', file, { reportUploadProgress: true, observe: 'events' });
FetchBackend와 함께 reportUploadProgress를 사용하면 앵귤러는 의도적으로 예외를 발생시켜 withXhr()이 필요하다는 것을 알려줍니다. 다행히 ng update는 기존 동작을 유지하기 위해 자동으로 withXhr()을 추가해줍니다.
9. 마이크로프론트엔드 개발자들을 위한 선물
이 섹션은 일반적인 요약에서는 잘 다뤄지지 않지만, 모듈 연합(Module Federation) 및 분산된 셸(shell)을 조율하는 개발자들에게는 정확히 중요한 부분입니다. 앵귤러 22는 이 시나리오에 특화된 개선 사항들을 가져왔습니다.
-
ApplicationRef.bootstrapwith config:bootstrap()은 이제createComponent와 유사한 설정 객체를 인자로 받습니다. 이를 통해 페이지의 특정 영역에서 필요에 따라 마이크로프론트엔드를 구동할 수 있습니다.appRef.bootstrap(MyComponent, { hostElement: document.querySelector('#root')! }); -
섀도우 루트 내부 부트스트랩: 섀도우 루트 내부에서 직접 앵귤러를 시작할 수 있으며, 스타일도
SharedStylesHost에 올바르게 등록됩니다. 웹 컴포넌트와의 깔끔한 통합을 향한 또 한 걸음입니다. -
세그먼트를 앞뒤로 포함하는 와일드카드 라우트 (
'foo/**/bar'): 이전에는 커스텀 경로 매처로만 가능했던 기능입니다. URL 패턴을 기반으로 올바른 마이크로프론트엔드를 로드해야 하는 셸에 완벽합니다. -
경로별 환경 인젝터 자동 정리 (
withExperimentalAutoCleanupInjectors): 라우트 수준에서 제공된 서비스가 애플리케이션 종료 시까지 남아있던 것이 아니라, 이제 해당 라우트를 떠나면 마침내 파괴됩니다. 아직 실험적 기능이지만, 인스턴스 누수(메모리 누수)에 대한 오래된 고충을 해결해 줍니다.
안전한 마이그레이션을 위한 실전 전략
확장 가능한 애플리케이션을 마이그레이션하려면 전략이 필요합니다. 실용적인 로드맵은 다음과 같습니다.
OnPush에 대한 두려움 없이ng update를 실행하세요. 명시적인 전략이 없던 곳에는Eager를 적용하므로 아무것도 망가지지 않습니다. 그 후에, "가장 뜨거운" 프레젠테이션 레이어부터 시작하여 컴포넌트별로OnPush와 시그널로 마이그레이션하세요.- 의존성 주입 계층을 정리하세요. IDE의 리팩토링 도구를 사용하여 더 간단한
@Injectable({ providedIn: 'root' })데코레이터를@Service()로 교체하고, 커스텀 프로바이더가 있는 곳에는@Injectable()을 유지하세요. injectAsync+onIdle을 채택하여 초기 번들을 줄이세요. 시작 시에는 필요 없는 무거운 서비스를 식별하고, 유휴 상태일 때 미리 가져오는 방식으로 필요에 따라 로드하세요.- 간단한 RxJS GET 요청을
httpResource로 마이그레이션하세요. 이전에는 단순히 GET 요청을 해결하기 위해 RxJS를 사용했다면,httpResource는 경쟁 조건 처리 능력을 잃지 않으면서 인지 복잡성을 획기적으로 줄여줍니다. HttpClient를 확인하세요.withFetch()는 이제 중복되므로 제거하고, 업로드 진행 상황에 의존하는 곳에는withXhr()이 있는지 확인하세요.ng update가 도움을 주지만, 반드시 검토해야 합니다.- SSR에서 하이드레이션을 검증하세요. 점진적 하이드레이션은 기본적으로 활성화됩니다. 동작을 테스트하고, 특정 플로우에서 이전 모드가 필요한 경우
withNoIncrementalHydration()을 사용하세요.
처음 시작하는 분들을 위한 조언: 모든 것을 한 번에 마이그레이션하려고 하지 마세요. ng update를 실행하고 앱이 계속 작동하는지 확인한 후 (Eager 폴백 덕분입니다), 그때 간단한 컴포넌트를 선택하여 시그널 + OnPush로 전환해 보세요. 얻는 이점을 느끼고, 자신감을 얻은 다음, 반복하세요. 좋은 마이그레이션은 영웅적인 작업이 아니라 지루하고 점진적인 과정입니다.
최종 결론
앵귤러 22는 구글의 프레임워크가 내부부터 재구축되었음을 증명합니다. "무겁고", "장황하다"는 옛 명성은 이제 과거의 이야기가 되었습니다. 오늘날 우리는 정교한 반응성, 진정한 zone-less 기능, 그리고 최고 수준의 개발자 경험을 누릴 수 있게 되었습니다. 최근 몇 달 동안 업데이트를 미뤄왔던 개발자들은 이제 실험적인 API에 의존하지 않고도 시그널 기반 개발 플로우로 마이그레이션할 수 있는 안정적인 기반을 받게 된 셈입니다.
만약 지금 앵귤러를 시작한다면, 몇 년 전보다 훨씬 더 간단하고 직관적인 앵귤러를 경험하게 될 것입니다. 그리고 이미 복잡하고 확장 가능한 제품을 구축하고 있는 개발자라면, 이처럼 강력한 도구들이 우리 손에 들어온 적은 드물었습니다.
이 분석이 마음에 드셨나요? 다음 리팩토링에 이 아이디어를 적용해 보고 결과가 어땠는지 저에게 알려주세요. 프론트엔드 아키텍처, 기술 콘텐츠, 그리고 개발 세계에 대한 더 많은 이야기를 나누고 싶다면, 제 블로그와 소셜 채널을 구독해 주세요.
즐거운 코딩 되세요! 💻🚀
📚 용어집 — 이 글의 기술 용어
앵귤러가 처음이거나 복습하고 싶은 분들을 위해 (알파벳 순서).
onIdle/prefetch: "사전 가져오기(Prefetch)"는 필요하기 전에 조용히 무언가를 로드하는 것을 의미합니다.onIdle은 브라우저가 유휴 상태일 때 (requestIdleCallback API를 사용하여) 이 작업을 수행합니다. 이렇게 하면 사용자가 클릭할 때 모든 것이 준비되어 있게 됩니다.OnPush: "경제적인" 변경 감지 전략입니다. 앵귤러는 컴포넌트가 새로운 입력을 받거나, 이벤트가 발생하거나, 시그널이 변경될 때만 해당 컴포넌트를 확인합니다. 결과적으로 성능이 향상됩니다.providedIn: 'root': 서비스의 단일 인스턴스가 전체 앱에 존재한다는 것을 나타냅니다 (싱글턴 패턴). 이전에는 수동으로 작성했지만, 이제@Service()는 기본적으로 이를 가정합니다.- SSR (Server-Side Rendering): 서버가 완성된 HTML을 만들어서 브라우저로 보냅니다. 사용자는 자바스크립트가 로드되기도 전에 페이지를 빠르게 볼 수 있습니다. 성능과 SEO에 좋습니다.
switchMap/ RxJS: RxJS는 스트림(시간에 따라 데이터가 흐름) 기반의 반응형 프로그래밍 라이브러리입니다.switchMap은 새로운 요청이 들어올 때 이전 요청을 취소하는 오퍼레이터 중 하나로, 혼란스러운 결과를 방지하는 데 정확히 효과적입니다.- Web Components / Shadow Root: 웹 컴포넌트는 모든 프레임워크에서 작동하는 UI 컴포넌트입니다. 섀도우 루트는 컴포넌트의 스타일이 외부로 유출되거나 (또는 간섭받지 않도록) 보호하는 격리된 "버블"입니다. 여러 팀이 코드를 섞어 사용할 때 매우 유용합니다.
- **
Wildcard(**): 라우트 정의에서 모든 경로를 일치시키는 "조커"입니다. 정확한 URL을 미리 알 수 없고 패턴만 아는 경우에 유용합니다. Zone-less/ Zone.js: Zone.js는 과거에 애플리케이션에서 발생하는 모든 것을 "감시"하여 화면을 언제 업데이트할지 알게 해주는 라이브러리였습니다.Zone-less는 앵귤러가 Zone.js 없이 작동하는 것을 의미하며, 시그널 덕분에 가능해졌고 훨씬 빠릅니다.- 강력한 타입 검사 (Strongly typed): 타입스크립트는 데이터의 정확한 형태를 "알고" 있으며, 실행 전에 필드를 잘못 사용하면 에디터에서 경고를 줍니다. 프로덕션에서 버그를 줄여줍니다.
- 경쟁 조건 (Race condition): 사용자가 빠르게 타이핑하여 여러 검색을 연속으로 실행할 때, 오래된 검색의 응답이 나중에 도착하여 올바른 결과를 잘못된 것으로 덮어쓸 수 있습니다.
httpResource는 이를 자체적으로 해결합니다. - 계약 (Schema): 폼의 유효성 검사 규칙(어떤 필드, 어떤 제한)을 설명하는 "청사진"입니다. Zod와 Valibot은 이를 위한 인기 있는 라이브러리입니다.
- 구조 (Framework): 라우팅, 폼, 요청과 같은 일반적인 문제를 이미 해결해 주는 구조화된 "도구 상자"로, 개발자가 바퀴를 재발명할 필요가 없도록 합니다.
- 끌어올리기 (Bootstrap): 앵귤러 애플리케이션을 "시작"하는 과정입니다. 프레임워크가 초기화되고 페이지에 첫 컴포넌트를 렌더링하는 순간입니다.
- 네트워크 요청 (HTTP Request): 앱이 서버에 데이터를 요청하는 것 ("항공편 목록을 주세요"). 서버는 데이터로 응답합니다.
- 데코레이터 (Decorator): 클래스 앞에 붙는
@기호 (@Component,@Service). 앵귤러에게 "이 클래스를 특별한 방식으로 처리해 줘"라고 알려주는 주석입니다. - 디바운스 (Debounce): 사용자가 작업을 멈출 때까지 기다렸다가 반응하는 기술입니다. 예를 들어, 검색에서 글자 하나하나를 입력할 때마다 API를 호출하는 대신, 300ms 동안의 정적 상태를 기다린 후에 검색을 실행합니다. 요청을 줄이고 사용자 경험을 향상시킵니다.
- 디펜던시 인젝션 (DI - Dependency Injection): 클래스가 필요한 것(예: API 서비스)을 스스로 생성하는 대신, 단순히 요청하면 앵귤러가 이를 제공해 주는 방식입니다. 코드를 테스트하고 유지보수하기 쉽게 만듭니다.
- 더티 (dirty): 사용자가 폼 필드와 상호작용했는지 여부를 표시합니다. 폼이 아직 비어있는 상태에서 오류를 표시하는 대신, 사용자가 상호작용한 후에만 "필수 필드" 오류를 표시하는 데 유용합니다.
- 렌더링 (Hydration / Incremental Hydration): 서버에서 오는 정적 HTML에 "생명"을 불어넣는 과정입니다. 앵귤러가 이벤트와 상호작용성을 추가합니다. 점진적 하이드레이션은 사용자가 보거나 사용하는 부분에만 조금씩 이 작업을 수행하여, 모든 것을 한 번에 처리하지 않습니다.
- 메모리 누수 (Memory leak): 더 이상 필요하지 않은데도 무언가가 메모리를 계속 차지하고 있는 현상입니다. 장시간 실행되는 앱에서는 누수가 쌓여 모든 것을 느리게 만듭니다.
- 모듈 연합 (Module Federation): 이러한 미니 앱들이 코드를 공유하고 런타임에 로드될 수 있도록 하는 기술 (Webpack에서 유래).
- 마이크로프론트엔드 (Microfrontends): 거대한 애플리케이션을 여러 독립적인 "미니 앱"으로 분할하여, 각 미니 앱을 다른 팀이 관리하고 단일 화면에서 통합하는 방식입니다. 프론트엔드 세계의 "마이크로서비스"와 같습니다.
ng update: 앵귤러 CLI 명령어로, 가능한 경우 자동 마이그레이션을 적용하여 프로젝트를 한 버전에서 다음 버전으로 업데이트합니다.- 번들 (Bundle): 브라우저가 앱을 실행하기 위해 다운로드하는 최종 자바스크립트 패키지입니다. 클수록 초기 로딩이 느려집니다.
- 보일러플레이트 (Boilerplate): 실제 로직을 추가하지 않으면서 끊임없이 반복해서 작성해야 하는 정형화되고 의례적인 코드입니다. 보일러플레이트가 적을수록 지루한 코딩이 줄어듭니다.
- 비동기 (Asynchronous): 즉시 발생하지 않는 어떤 것. 서버에 데이터를 요청하면 응답이 "나중에" 도착합니다. 코드는 기다리는 방법을 알아야 합니다.
- 선언적 (Declarative): "이 필드는 필수입니다"와 같이 원하는 것을 설명하는 방식이지, 단계별로 어떻게 해야 하는지 작성하는 방식이 아닙니다. 더 읽기 쉽습니다.
- 서비스 (Service): 재사용 가능하며 뷰와 관련 없는 로직(예: 데이터 가져오기, 계산, 상태 유지)을 집중시키는 클래스입니다. 여러 컴포넌트가 동일한 서비스를 공유할 수 있습니다.
- 시그널 (Signals): 앵귤러가 값을 보유하는 현대적인 방법으로, 값이 변경될 때 종속된 모든 곳에 자동으로 알림을 보냅니다. 마치 A셀이 변경되면 B셀이 스스로 재계산되는 스프레드시트와 같습니다.
- 시작 시간 (Startup): 사용자가 페이지를 열고 페이지를 사용할 수 있게 되기까지의 시간입니다.
- 스키마 (Schematic): 마이그레이션 중에 코드에 변경 사항(이름 변경, 구성 이동 등)을 자동으로 적용하는 앵귤러 자동화 스크립트입니다.
- 셸 (Shell): 마이크로프론트엔드를 조율하고 로드하는 "셸" 앱입니다.
Eager/Default: "오래되고 비싼" 변경 감지 전략입니다. 앵귤러는 모든 주기에 걸쳐 변경 사항을 찾기 위해 전체 컴포넌트 트리를 스캔합니다. 작동은 하지만, 처리 능력을 낭비합니다. 앵귤러 22에서는Eager로 이름이 바뀌었고 이제 사용이 권장되지 않습니다.- 엔터프라이즈 (Enterprise): 여러 팀이 참여하고 수년간 유지보수해야 하는 대규모 기업 애플리케이션입니다.
- 인터롭 / 점진적 마이그레이션 (Interop / Incremental migration): "인터롭"은 새 코드가 이전 코드와 통신할 수 있는 능력입니다. "점진적 마이그레이션"은 모든 것을 한 번에 위험하게 재작성하지 않고, 프로젝트를 한 번에 한 부분씩 점진적으로 업데이트하는 것입니다.
- 변경 감지 (Change detection): 데이터가 변경된 후 앵귤러가 화면을 언제, 어디서 다시 렌더링할지 결정하는 메커니즘입니다.
- 클린 아키텍처 (Clean Architecture): 코드를 잘 분리된 계층(중앙에 비즈니스 규칙, 가장자리에 데이터베이스 및 API와 같은 세부 사항)으로 구성하는 방법입니다. 목표는 기술을 변경하더라도 나머지 부분에 영향을 미치지 않도록 하는 것입니다.
- 페치 vs XHR (Fetch vs. XHR): 브라우저가 HTTP 요청을 만드는 두 가지 방법입니다. XHR (XMLHttpRequest)은 구식 방법이고, Fetch는 Promise 기반의 현대적인 방법(더 깔끔함)으로 스트리밍에 더 적합합니다. Fetch가 아직 잘 못하는 유일한 것은 업로드 진행 상황을 보고하는 것입니다.
- 반응형 / 반응성 (Reactive / Reactivity): 데이터가 변경될 때 "화면을 업데이트하라"고 수동으로 명령하지 않아도 UI가 스스로 반응하는 것입니다.
- 반응형 폼 vs 템플릿 기반 폼 (Reactive Forms vs. Template-Driven): 앵귤러에서 폼을 만드는 두 가지 기존 방법입니다. 반응형 폼은 타입스크립트에서 폼을 구축하고(더 많은 제어, 더 장황함), 템플릿 기반 폼은 HTML에서 구축합니다(더 간단함, 덜 강력함). 시그널 폼은 둘의 장점을 통합합니다.
- 리소스 (Resource): 요청을 만들고, 결과를 저장하고, 로딩, 에러, 최종 값의 세 가지 상태를 제공하는 "스마트 패키지"입니다.
기술 출처: 앵귤러 공식 v22 발표 (angular.dev) 및 Manfred Steyer (ANGULARarchitects)의 상세 분석 (모두 2026년 6월).
원문: https://dev.to/ghabryel/angular-22-the-end-of-boilerplate-and-the-consolidation-of-the-reactive-era-3a8n 수집일: 2026-08-12 00:53:21