팁: 이 가이드 문서는 핵심 가이드 이후 내용을 다룹니다. 아직 Angular에 익숙하지 않다면 해당 문서를 먼저 읽어보세요.
컴포넌트 셀렉터와 매칭되는 HTML 엘리먼트마다 컴포넌트 인스턴스가 생성됩니다. 이때 컴포넌트 셀렉터와 매칭된 DOM 엘리먼트를 호스트 엘리먼트(host element) 라고 합니다. 컴포넌트 템플릿은 호스트 엘리먼트 안에 렌더링된다고 이해하면 됩니다.
// 컴포넌트 코드
@Component({
selector: 'profile-photo',
template: `<img src="profile-photo.jpg" alt="Your profile photo" />`,
})
export class ProfilePhoto {}
<!-- 컴포넌트 사용 코드 -->
<h3>Your profile photo</h3>
<profile-photo />
<button>Upload a new profile photo</button>
<!-- 렌더링 된 DOM -->
<h3>Your profile photo</h3>
<profile-photo>
<img src="profile-photo.jpg" alt="Your profile photo" />
</profile-photo>
<button>Upload a new profile photo</button>
위 예제에서 ProfilePhoto 컴포넌트의 호스트 엘리먼트는 <profile-photo> 입니다.
호스트 엘리먼트 바인딩하기
컴포넌트는 프로퍼티나 어트리뷰트, 스타일, 이벤트를 호스트 엘리먼트와 바인딩할 수 있습니다.
호스트 바인딩은 컴포넌트 템플릿 내부 엘리먼트의 바인딩과 동작 방식은 같지만, @Component 데코레이터의 host 프로퍼티에서 정의합니다:
@Component({
...,
host: {
'role': 'slider',
'[attr.aria-valuenow]': 'value',
'[class.active]': 'isActive()',
'[style.background]' : `hasError() ? 'red' : 'green'`,
'[tabIndex]': 'disabled ? -1 : 0',
'(keydown)': 'updateValue($event)',
},
})
export class CustomSlider {
value: number = 0;
disabled: boolean = false;
isActive = signal(false);
hasError = signal(false);
updateValue(event: KeyboardEvent) { /* ... */ }
/* ... */
}
참고: 전역 대상의 이름은 document:, window:, body:를 사용할 수 있습니다.
참고: '(keydown.enter)'와 같은 키 이름은 KeyboardEvent.key와 비교하며, 이 값은 사용자의 키보드 배열과 입력 언어에 따라 달라집니다.
키보드 배열과 관계없이 물리적인 키를 식별하려면 '(keydown.code.Enter)'처럼 code 변경자를 사용하세요.
자세한 내용은 키 변경자 사용하기를 참고하세요.
@HostBinding, @HostListener 데코레이터
@HostBinding 이나 @HostListener 데코레이터를 사용해서 호스트 엘리먼트와 클래스 멤버를 바인딩하는 방법도 있습니다.
@HostBinding을 사용하면 호스트 엘리먼트의 프로퍼티와 어트리뷰트를 클래스 프로퍼티와 게터에 바인딩할 수 있습니다:
@Component({/* ... */})
export class CustomSlider {
@HostBinding('attr.aria-valuenow')
value: number = 0;
@HostBinding('tabIndex')
get tabIndex() {
return this.disabled ? -1 : 0;
}
/* ... */
}
그리고 @HostListener 를 사용하면 호스트 엘리먼트와 이벤트 리스너를 바인딩할 수 있습니다.
이 데코레이터는 이벤트 이름을 인자로 받고, 인자 배열을 옵션 인자로 받습니다:
export class CustomSlider {
@HostListener('keydown', ['$event'])
updateValue(event: KeyboardEvent) {
/* ... */
}
}
데코레이터 대신 host 프로퍼티 사용을 권장합니다.
@HostBinding 이나 @HostListener 보다는 host 프로퍼티를 사용하세요.
이 데코레이터들은 이전 버전과 호환성을 유지하기 위해 사용됩니다.
바인딩 우선순위
템플릿에 컴포넌트를 사용할 때 컴포넌트 인스턴스와 엘리먼트를 바인딩할 수 있습니다. 그런데 컴포넌트는 같은 프로퍼티나 어트리뷰트에 대해 호스트 바인딩을 정의할 수도 있습니다.
@Component({
...,
host: {
'role': 'presentation',
'[id]': 'id',
}
})
export class ProfilePhoto { /* ... */ }
<profile-photo role="group" [id]="otherId" />
이 경우, 다음 규칙에 따라 어떤 값이 사용되는지 결정됩니다:
- 두 값이 모두 정적이면 인스턴스 바인딩의 우선순위가 높습니다.
- 한 값은 정적이고 다른 값은 동적이면, 동적인 값이 사용됩니다.
- 두 값이 모두 동적이면, 컴포넌트 호스트 바인딩의 우선순위가 높습니다.
CSS 커스텀 프로퍼티 스타일 지정하기
CSS 커스텀 프로퍼티를 사용한다면 컴포넌트 스타일을 좀 더 유연하게 지정할 수 있습니다. 커스텀 프로퍼티로 호스트 엘리먼트에 스타일을 바인딩 해봅시다.
@Component({
/* ... */
host: {
'[style.--my-background]': 'color()',
},
})
export class MyComponent {
color = signal('lightgreen');
}
이 예제를 보면, color 시그널에는 --my-background CSS 커스텀 프로퍼티가 바인딩되어 있습니다.
이 커스텀 프로퍼티의 값은 color 시그널 값이 변경되면 자동으로 변경됩니다.
현재 컴포넌트와 이 커스텀 프로퍼티를 활용하는 모든 자식 컴포넌트가 영향을 받습니다.
자식 컴포넌트에 커스텀 프로퍼티 설정하기
아니면, 스타일 바인딩로 자식 컴포넌트의 호스트 엘리먼트에 CSS 커스텀 프로퍼티를 지정할 수도 있습니다.
@Component({
selector: 'my-component',
template: `<my-child [style.--my-background]="color()" />`,
})
export class MyComponent {
color = signal('lightgreen');
}
호스트 엘리먼트 어트리뷰트 주입하기
컴포넌트나 디렉티브는 HostAttributeToken과 inject 함수를 사용해서 호스트 엘리먼트의 정적 어트리뷰트를 참조할 수 있습니다.
import { Component, HostAttributeToken, inject } from '@angular/core';
@Component({
selector: 'app-button',
...,
})
export class Button {
variation = inject(new HostAttributeToken('variation'));
}
<app-button variation="primary">Click me</app-button>
참고: HostAttributeToken을 사용할 때 의존성 객체가 옵션으로 지정되지 않은 채로 어트리뷰트가 존재하지 않으면 오류가 발생합니다.