@Input과 @Output은 부모와 자식 컴포넌트가 통신하는 표준 방법입니다. **@Input**은 데이터를 아래로 전달하고(부모 → 자식), **@Output**은 이벤트를 위로 보냅니다(자식 → 부모). 이는 보편적인 "props down, events up" 패턴을 반영합니다.
// 자식: UserCardComponent
import { Component, Input } from "@angular/core";
@Component({ selector: "app-user-card", template: `<h2>{{ user.name }}</h2>` })
export class UserCardComponent {
@Input() user!: User; // 부모로부터 데이터를 받는다
@Input() showEmail = false; // 기본값과 함께
}
<!-- 부모는 속성 바인딩을 통해 데이터를 전달한다 -->
<app-user-card [user]="currentUser" [showEmail]="true"></app-user-card>
// 자식은 부모가 수신할 수 있는 이벤트를 방출한다
import { Component, Output, EventEmitter } from "@angular/core";
@Component({
selector: "app-user-card",
template: `<button (click)="onDelete()">Delete</button>`,
})
export class UserCardComponent {
@Output() deleted = new EventEmitter<number>(); // 출력 이벤트 선언
onDelete() {
this.deleted.emit(this.user.id); // 페이로드와 함께 방출
}
}
<!-- 부모는 이벤트 바인딩을 통해 수신한다 -->
<app-user-card [user]="u" (deleted)="removeUser($event)"></app-user-card>
자식은 EventEmitter를 통해 방출하고, 부모는 (eventName)으로 바인딩하여 페이로드를 $event로 받습니다. 자식은 부모의 데이터를 직접 수정하지 않고, 방출을 통해 동작을 요청합니다.
부모 ──[user]──────────────→ 자식 (@Input: 데이터 아래로)
부모 ←──(deleted)=removeUser─ 자식 (@Output: 이벤트 위로)
name = input<string>(); // signal 기반 @Input (최신 Angular)
deleted = output<number>(); // signal 기반 @Output
최근 Angular는 대안으로 signal 기반 input()/output() 함수를 추가했습니다.
@Input/@Output은 Angular에서 부모-자식 통신과 재사용 가능한 컴포넌트의 핵심입니다. 데이터를 예측 가능하게 유지하고 컴포넌트를 분리시키는 단방향 데이터 흐름(입력으로 아래로, 이벤트로 위로)을 강제합니다.
이 쌍을 이해하는 것은 자명하지 않은 모든 Angular UI를 구성하는 데 필수적입니다. 관련 없는 컴포넌트 간 통신에는 대신 공유 서비스나 상태 라이브러리를 사용합니다.