Angular의 @Input 데이터 전달 문제에 대해 자세히 설명해드리겠습니다.
@Input은 Angular에서 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용하는 데코레이터입니다. React의 props와 비슷한 개념이라고 생각하시면 됩니다.
페이지 새로고침이나 라우팅 없이 같은 페이지 내에서 데이터를 업데이트할 때 발생하는 문제입니다.
동일한 데이터를 전달하려고 할 때:
// 부모 컴포넌트
@Component({
template: '<child-component [data]="someData"></child-component>'
})
class ParentComponent {
someData = "Hello";
updateData() {
this.someData = "Hello"; // 같은 값을 다시 할당
}
}
이 경우 자식 컴포넌트는 변화를 감지하지 못합니다.
배열 데이터 변경 시:
// 부모 컴포넌트
@Component({
template: '<child-component [items]="itemList"></child-component>'
})
class ParentComponent {
itemList = [];
addItem() {
this.itemList.push('new item'); // 배열에 새 항목 추가
}
}
단순히 배열에 push만 하면 변화가 감지되지 않을 수 있습니다.
데이터가 같더라도 새로운 참조를 만들어 전달합니다:
updateData() {
this.someData = new String("Hello"); // 새로운 문자열 객체 생성
// 또는 배열의 경우
this.itemList = [...this.itemList, 'new item']; // 새로운 배열 생성
}
자식 컴포넌트에서 변화를 직접 감지:
// 자식 컴포넌트
@Component({
...
})
class ChildComponent implements OnChanges {
@Input() data: any;
ngOnChanges(changes: SimpleChanges) {
if (changes['data']) {
// 데이터가 변경될 때마다 실행될 코드
console.log('데이터가 변경됨:', changes['data'].currentValue);
}
}
}
Input을 활용하지 않고 서비스를 통해 데이터 스트림을 전달하는 방법도 있습니다.
이 경우 이 service를 사용하는 모든 Component가 동일한 데이터를 공유하게 되므로 유의하여야 합니다.
// 데이터 서비스
@Injectable({
providedIn: 'root'
})
class DataService {
private dataSubject = new BehaviorSubject<any>(null);
data$ = this.dataSubject.asObservable();
updateData(newData: any) {
this.dataSubject.next(newData);
}
}
// 자식 컴포넌트
@Component({
...
})
class ChildComponent implements OnInit {
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.data$.subscribe(data => {
// 데이터가 변경될 때마다 실행될 코드
});
}
}
객체나 배열을 전달할 때는 항상 불변성(Immutability)을 유지하는 것이 좋습니다.
복잡한 데이터 흐름이 필요한 경우 NgRx나 RxJS와 같은 상태 관리 라이브러리 사용을 고려해보세요.
ChangeDetectionStrategy.OnPush를 사용하면 성능은 향상되지만, 데이터 변화 감지에 더 주의해야 합니다.