심화 가이드
컴포넌트

조건에 따라 컴포넌트 렌더링하기

팁: 이 가이드 문서는 핵심 가이드 이후 내용을 다룹니다. 아직 Angular에 익숙하지 않다면 해당 문서를 먼저 읽어보세요.

컴포넌트는 템플릿에 사용하는 방식 외에 동적으로 렌더링 할 수도 있습니다. 템플릿에서 NgComponentOutlet를 사용하거나 TypeScript 코드에서 ViewContainerRef를 사용하면 됩니다.

NgComponentOutlet 사용하기

NgComponentOutlet 는 템플릿에서 컴포넌트를 동적으로 렌더링하는 구조 디렉티브입니다.

      
@Component({ ... })export class AdminBio { /* ... */ }@Component({ ... })export class StandardBio { /* ... */ }@Component({  ...,  template: `    <p>Profile for {{user.name}}</p>    <ng-container *ngComponentOutlet="getBioComponent()" /> `})export class CustomDialog {  user = input.required<User>();  getBioComponent() {    return this.user().isAdmin ? AdminBio : StandardBio;  }}

이 디렉티브에 대해 자세하게 알아보려면 NgComponentOutlet API 문서를 참고하세요.

ViewContainerRef 사용하기

뷰 컨테이너 는 컴포넌트 트리에서 내용물을 담는 노드를 의미합니다. 그리고 컴포넌트나 디렉티브는 ViewContainerRef를 의존성 객체로 주입받아서 DOM에 존재하는 뷰 컨테이너를 참조할 수 있습니다.

ViewContainerRef 객체의 createComponent 메서드를 사용하면 컴포넌트를 동적으로 생성하고 렌더링 할 수 있습니다. ViewContainerRef를 사용해서 컴포넌트를 생성하면 Angular는 ViewContainerRef로 참조한 컴포넌트나 디렉티브 바로 옆에 DOM을 추가합니다.

      
@Component({  selector: 'leaf-content',  template: `    This is the leaf content  `,})export class LeafContent {}@Component({  selector: 'outer-container',  template: `    <p>This is the start of the outer container</p>    <inner-item />    <p>This is the end of the outer container</p>  `,})export class OuterContainer {}@Component({  selector: 'inner-item',  template: `    <button (click)="loadContent()">Load content</button>  `,})export class InnerItem {  private viewContainer = inject(ViewContainerRef);  loadContent() {    this.viewContainer.createComponent(LeafContent);  }}

위 예제코드에서 사용자가 "Load content" 버튼을 클릭하면 아래 DOM 구조가 화면에 렌더링 됩니다.

      
<outer-container>  <p>This is the start of the outer container</p>  <inner-item>    <button>Load content</button>  </inner-item>  <leaf-content>This is the leaf content</leaf-content>  <p>This is the end of the outer container</p></outer-container>

컴포넌트 지연 로딩

NgComponentOutlet이나 ViewContainerRef를 사용해서 컴포넌트를 렌더링하면 표준 JavaScript 동적 로딩에 따라 지연로딩됩니다.

      
@Component({  ...,  template: `    <section>      <h2>Basic settings</h2>      <basic-settings />    </section>    <section>      <h2>Advanced settings</h2>      <button (click)="loadAdvanced()" *ngIf="!advancedSettings">        Load advanced settings      </button>      <ng-container *ngComponentOutlet="advancedSettings" />    </section>  `})export class AdminSettings {  advancedSettings: {new(): AdvancedSettings} | undefined;  async loadAdvanced() {    const { AdvancedSettings } = await import('path/to/advanced_settings.js');    this.advancedSettings = AdvancedSettings;  }}

이렇게 구현하면 사용자가 버튼을 클릭했을 때 AdvancedSettings 컴포넌트가 동적으로 로딩되어 화면에 렌더링됩니다.