Angular 20에서 21로 마이그레이션: 가이드

발행: (2025년 12월 13일 오후 04:47 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

Angular 20에서 21로 업데이트하기 위한 직관적인 가이드입니다. Karma 제거, 기본 Zoneless 모드, 자동 HttpClient 및 빌드 오류 해결 방법을 다룹니다.

Angular 20이 큰 변화라고 생각했다면, Angular 21에 오신 것을 환영합니다.
버전 20이 Signals 안정화에 집중했다면, 버전 21은 개발자 경험을 향상시킵니다: zone.js가 선택 사항이 되고, Karma는 사라졌으며 RxJS가 서서히 대체되고 있습니다. 단순한 업데이트가 아니라 전체 생태계가 새로워진 느낌입니다.

모든 것을 멈추게 하는 핵심 문제

ng update를 실행하기 전에, 아래 레거시 패턴에 의존하고 있다면 빌드가 실패할 가능성이 높습니다.

1. Karma 종말 이벤트 (Vitest가 기본)

많은 팀에게 가장 즉각적인 충격은 ng test일 것입니다. Angular 21은 공식적으로 Karma를 Vitest로 교체하여 기본 테스트 러너로 지정했습니다.

깨지는 부분

  • 커스텀 karma.conf.js 파일이 있거나 Karma 전용 플러그인/리포터에 의존하고 있다면, 테스트 스위트가 이제 레거시 코드가 됩니다.

해결 방법

  • 새 프로젝트: 처음부터 Vitest를 사용합니다. 더 빠르고 깔끔하며 Vite를 사용합니다.
  • 기존 프로젝트: 즉시 변경할 필요는 없지만, 곧 종료됩니다. CLI가 계속 알릴 것입니다.
  • 마이그레이션: ng generate @angular/core:karma-to-vitest를 실행해 자동 마이그레이션을 시도합니다. 표준 설정은 변환하지만, 테스트 설정에 있는 Webpack 커스텀 트릭은 Vite용으로 수동 재작성해야 합니다.

2. HttpClient가 “그냥 있다”

app.config.tsprovideHttpClient()를 추가하거나 HttpClientModule을 임포트하던 기억이 있나요?

변경 사항
HttpClient가 이제 루트 인젝터에 기본으로 제공됩니다.

깨지는 부분

  • HttpClient가 존재하지 않을 것이라고 가정한 테스트가 실패할 수 있습니다.
  • 혼합된 NgModule/Standalone 애플리케이션에서 복잡한 인터셉터 순서를 HttpClientModule에 의존하고 있다면 미묘한 동작 변화가 나타날 수 있습니다.

해결 방법
옵션을 전달하지 않는 한(withInterceptors, withFetch 등) provideHttpClient() 호출을 제거하세요. 설정을 정리하되, 인터셉터 실행 순서를 확인하세요.

3. zone.js가 사라졌다 (새 앱에만)

ng new로 생성된 새 애플리케이션은 기본적으로 zone.js를 포함하지 않습니다.

깨지는 부분
기존 애플리케이션에는 영향을 주지 않습니다(아직). polyfills.ts는 여전히 Zone을 임포트합니다.

주의
v21의 새로운 튜토리얼 코드를 v20 기존 앱에 복사·붙여넣기 하면 Zoneless 동작(더 적은 ChangeDetectorRef 사용, Signals 의존)이라고 가정할 수 있습니다. 두 패러다임을 섞으면 “changed after checked” 오류나 화면이 업데이트되지 않는 문제가 발생할 수 있습니다.

새로운 장난감: 실제로 사용할 기능들

빌드를 정리한 뒤, v21은 개발 경험(DX)을 크게 향상시킵니다.

1. Signal Forms (실험적이지만 안정)

import { form, field } from '@angular/forms/signals';
import { Validators } from '@angular/forms';

// 정의형 반응형 폼 모델
const loginForm = form({
  email: field('', [Validators.required, Validators.email]),
  password: field('', [Validators.required])
});

// 값에 바로 signal처럼 접근!
console.log(loginForm.value().email);

왜 사용할까
타입 안전이 기본이며 RxJS 숙련도가 필요 없습니다.

상태
실험 단계. 새로운 기능에 사용해 보되, 결제 흐름 전체를 아직 재작성하지는 마세요.

2. Angular Aria (Developer Preview)

  Opción 1
  Opción 2

접근성을 위한 “headless” 프리미티브 라이브러리로, aria-expandedrole="button" 같은 속성을 수동으로 관리할 필요가 없습니다.

3. 템플릿 내 Regex

@if (email() | match: /@company\.com$/) {
  Empleado
}

템플릿에서 정규식 리터럴을 직접 사용할 수 있어, 보조 함수 없이도 조건 로직을 구현할 수 있습니다.

업데이트 체크리스트

1. 백업

모두 커밋하세요. 진심입니다.

2. 전역 CLI 업데이트

# 선택 사항: 충돌 방지를 위해 오래된 전역 버전 먼저 제거
npm uninstall -g @angular/cli

# npm 캐시 검증
npm cache verify

# 최신 전역 CLI 설치
npm install -g @angular/cli@latest

3. 로컬 프로젝트 업데이트

ng update @angular/cli@21 @angular/core@21

4. 진단 실행

Angular 21은 더 스마트한 진단을 제공합니다. ngClass가 점진적으로 [class.my‑class]로 대체되는 경고와 standalone 마이그레이션 기회를 주의 깊게 살펴보세요.

5. 테스트 확인

ng test를 실행하세요. 오류가 발생하면 다음 중 선택:

  • 경로 A: Karma 유지 (@angular/build:karma를 수동으로 추가하면 됩니다).
  • 경로 B: Vitest로 마이그레이션 (권장).

6. 선택 사항: Zoneless 전환

용기가 있다면 실험적 마이그레이션을 실행:

ng generate @angular/core:zoneless-migration

노트
이것은 “에이전시” 영역입니다. 복잡한 리팩터링을 AI에게 맡기려면 우리의 Guía MCP를 참고하세요.

요약

Angular 21은 “새 출발”이라는 슬로건을 실현합니다. 지난 10년간 축적된 무게(Zone, Karma, Modules)를 없애고 Svelte와 Solid 같은 최신 프레임워크와 경쟁하도록 설계되었습니다. 테스트 관련 변경 때문에 업데이트가 다소 까다로울 수 있지만, 더 빠르고 간결하며 Signals 기반의 프레임워크를 얻는 가치는 충분합니다.

Back to Blog

관련 글

더 보기 »