독립형 컴포넌트는 Angular 애플리케이션을 더 간단하게 만드는 방법을 제공합니다. 독립형 컴포넌트, 디렉티브, 파이프는 NgModule의 필요성을 줄여 개발 과정을 간소화하는 것을 목표로 합니다. 기존 애플리케이션도 호환성을 깨뜨리지 않고 필요에 따라 점진적으로 새로운 독립형 방식을 도입할 수 있습니다.
이 스키매틱은 기존 프로젝트의 컴포넌트, 디렉티브, 파이프를 독립형으로 변환하도록 돕습니다. 가능한 한 많은 코드를 자동으로 변환하는 것을 목표로 하지만, 프로젝트 개발자가 일부 코드를 직접 수정해야 할 수도 있습니다.
다음 명령어로 스키매틱을 실행하세요.
ng generate @angular/core:standalone
업데이트 전 확인 사항
스키매틱을 사용하기 전에 프로젝트가 다음 조건을 만족하는지 확인하세요.
- Angular 15.2.0 이상을 사용합니다.
- 컴파일 오류 없이 빌드됩니다.
- 작업 트리가 깨끗한 Git 브랜치에 있으며 모든 작업을 저장했습니다.
스키매틱 옵션
| 옵션 | 설명 |
|---|---|
mode |
수행할 변환입니다. 사용 가능한 옵션의 자세한 내용은 아래 마이그레이션 모드를 참고하세요. |
path |
프로젝트 루트 기준으로 마이그레이션할 상대 경로입니다. 이 옵션으로 프로젝트의 일부를 점진적으로 마이그레이션할 수 있습니다. |
마이그레이션 단계
마이그레이션 과정은 세 단계로 구성됩니다. 마이그레이션을 여러 번 실행하고 프로젝트가 예상대로 빌드되고 동작하는지 직접 확인해야 합니다.
NOTE: 스키매틱은 대부분의 코드를 자동으로 업데이트할 수 있지만 일부 예외적인 경우에는 개발자가 직접 개입해야 합니다. 각 마이그레이션 단계 이후에 수동으로 수정하는 작업을 계획하세요. 또한 스키매틱이 생성하는 새 코드가 프로젝트의 코드 서식 규칙과 일치하지 않을 수 있습니다.
다음 순서대로 마이그레이션을 실행하고 각 단계 사이에 코드가 빌드되고 실행되는지 확인하세요.
ng g @angular/core:standalone을 실행하고 "Convert all components, directives and pipes to standalone"(모든 컴포넌트, 디렉티브, 파이프를 독립형으로 변환)을 선택합니다.ng g @angular/core:standalone을 실행하고 "Remove unnecessary NgModule classes"(불필요한 NgModule 클래스 제거)를 선택합니다.ng g @angular/core:standalone을 실행하고 "Bootstrap the application using standalone APIs"(독립형 API로 애플리케이션 부트스트래핑)를 선택합니다.- 린트와 서식 검사를 실행하고 오류를 수정한 뒤 결과를 커밋합니다.
마이그레이션 이후
축하합니다. 애플리케이션을 독립형으로 변환했습니다 🎉. 필요에 따라 다음 작업을 진행할 수 있습니다.
- 남아 있는
NgModule선언을 찾아 제거합니다. "불필요한 NgModule 제거" 단계는 모든 모듈을 자동으로 제거할 수 없으므로 남은 선언을 직접 제거해야 할 수 있습니다. - 프로젝트의 단위 테스트를 실행하고 실패한 테스트를 수정합니다.
- 자동 서식 지정을 사용하는 프로젝트라면 코드 포매터를 실행합니다.
- 프로젝트의 린터를 실행하고 새 경고를 수정합니다. 일부 린터는 경고를 자동으로 해결할 수 있는
--fix플래그를 지원합니다.
마이그레이션 모드
이 마이그레이션에는 다음 모드가 있습니다.
- 선언을 독립형으로 변환합니다.
- 불필요한 NgModule을 제거합니다.
- 독립형 부트스트래핑 API로 전환합니다. 이 순서대로 마이그레이션을 실행해야 합니다.
선언을 독립형으로 변환하기
이 모드에서는 standalone: false를 제거하고 imports 배열에 의존성을 추가하여 모든 컴포넌트, 디렉티브, 파이프를 독립형으로 변환합니다.
HELPFUL: 이 단계에서 스키매틱은 컴포넌트를 부트스트래핑하는 NgModule을 무시합니다. 이러한 모듈은 독립형을 지원하는 bootstrapApplication 대신 bootstrapModule에서 사용하는 루트 모듈일 가능성이 높기 때문입니다. 스키매틱은 "독립형 부트스트래핑 API로 전환" 단계에서 이러한 선언을 자동으로 변환합니다.
이전:
shared.module.ts
@NgModule({
imports: [CommonModule],
declarations: [Greeter],
exports: [Greeter],
})
export class SharedModule {}
greeter.ts
@Component({
selector: 'greeter',
template: '<div *ngIf="showGreeting">Hello</div>',
standalone: false,
})
export class Greeter {
showGreeting = true;
}
이후:
shared.module.ts
@NgModule({
imports: [CommonModule, Greeter],
exports: [Greeter],
})
export class SharedModule {}
greeter.ts
@Component({
selector: 'greeter',
template: '<div *ngIf="showGreeting">Hello</div>',
imports: [NgIf],
})
export class Greeter {
showGreeting = true;
}
불필요한 NgModule 제거하기
모든 선언을 독립형으로 변환하면 많은 NgModule을 안전하게 제거할 수 있습니다. 이 단계는 해당 모듈 선언과 관련 참조를 가능한 한 많이 삭제합니다. 참조를 자동으로 삭제할 수 없으면 다음 TODO 주석을 남기므로 직접 NgModule을 삭제할 수 있습니다.
/* TODO(standalone-migration): clean up removed NgModule reference manually */
마이그레이션은 다음 조건을 만족하는 모듈을 안전하게 제거할 수 있다고 판단합니다.
declarations가 없습니다.providers가 없습니다.bootstrap컴포넌트가 없습니다.ModuleWithProviders심벌이나 제거할 수 없는 모듈을 참조하는imports가 없습니다.- 클래스 멤버가 없습니다. 빈 생성자는 무시합니다.
이전:
importer.module.ts
@NgModule({
imports: [FooComponent, BarPipe],
exports: [FooComponent, BarPipe],
})
export class ImporterModule {}
이후:
importer.module.ts
// Does not exist!
독립형 부트스트래핑 API로 전환하기
이 단계는 모든 bootstrapModule 사용을 새로운 독립형 기반 bootstrapApplication으로 변환합니다. 루트 컴포넌트의 standalone: false도 제거하고 루트 NgModule을 삭제합니다. 루트 모듈에 providers나 imports가 있으면 해당 설정을 새로운 부트스트랩 호출로 최대한 복사하려고 시도합니다.
이전:
./app/app.module.ts
import {NgModule} from '@angular/core';
import {App} from './app';
@NgModule({
declarations: [App],
bootstrap: [App],
})
export class AppModule {}
./app/app.ts
@Component({
selector: 'app',
template: 'hello',
standalone: false,
})
export class App {}
./main.ts
import {platformBrowser} from '@angular/platform-browser';
import {AppModule} from './app/app.module';
platformBrowser()
.bootstrapModule(AppModule)
.catch((e) => console.error(e));
이후:
./app/app.module.ts
// Does not exist!
./app/app.ts
@Component({
selector: 'app',
template: 'hello',
})
export class App {}
./main.ts
import {bootstrapApplication} from '@angular/platform-browser';
import {App} from './app/app';
bootstrapApplication(App).catch((e) => console.error(e));
자주 발생하는 문제
스키매틱의 정상 동작을 방해할 수 있는 일반적인 문제는 다음과 같습니다.
- 컴파일 오류: 프로젝트에 컴파일 오류가 있으면 Angular가 코드를 올바르게 분석하고 마이그레이션할 수 없습니다.
- tsconfig에 포함되지 않은 파일: 스키매틱은 프로젝트의
tsconfig.json파일을 분석하여 마이그레이션할 파일을 결정합니다. tsconfig에 포함되지 않은 파일은 제외합니다. - 정적으로 분석할 수 없는 코드: 스키매틱은 정적 분석으로 코드를 이해하고 수정할 위치를 결정합니다. 빌드 시점에 정적으로 분석할 수 없는 메타데이터를 가진 클래스는 건너뛸 수 있습니다.
제약 사항
마이그레이션의 규모와 복잡성 때문에 스키매틱이 처리할 수 없는 경우가 있습니다.
- 단위 테스트는 사전(AoT) 컴파일되지 않으므로 단위 테스트의 컴포넌트에 추가되는
imports가 완전히 정확하지 않을 수 있습니다. - 스키매틱은 Angular API를 직접 호출하는 코드를 기준으로 동작합니다. Angular API를 감싼 사용자 정의 래퍼는 인식할 수 없습니다. 예를 들어
TestBed.configureTestingModule을 감싼customConfigureTestModule함수를 정의하면 해당 함수에서 선언한 컴포넌트를 인식하지 못할 수 있습니다.