Today I Learned

[2024.10.19] Angular에서 ngOnChanges() 훅 제대로 이해하기

monkeykim 2024. 10. 19. 00:08

Angular는 컴포넌트 간의 상호작용을 효과적으로 관리하기 위해 다양한 생명주기 훅(Lifecycle Hook)을 제공한다. 그 중 하나가 바로 ngOnChanges()인데, 이 훅은 @Input() 속성 값이 변경될 때마다 호출되며, 컴포넌트가 부모로부터 전달받은 데이터가 변했을 때 적절한 처리를 할 수 있도록 도와준다.


ngOnChanges()란?

ngOnChanges()는 Angular 컴포넌트의 생명주기 훅 중 가장 먼저 실행되는 메서드이다. 이 훅은 @Input() 데코레이터로 부모 컴포넌트로부터 전달받은 값이 변경될 때마다 호출된다. 변경된 값뿐만 아니라 이전 값도 확인할 수 있어, 값이 변할 때마다 원하는 로직을 수행할 수 있다.

ngOnChanges()가 호출될 때

ngOnChanges()는 다음과 같은 상황에서 호출된다:

  1. 부모 컴포넌트가 자식 컴포넌트에 새로운 값을 전달할 때.
  2. 부모 컴포넌트에서 전달한 @Input() 값이 변경될 때.
  3. 컴포넌트가 처음 초기화될 때도 한 번 호출된다.(초기 값 설정 시).

단, ngOnChanges()는 @Input()에만 반응하며, @Output()과는 관련이 없다. 이는 자식 컴포넌트가 부모에게 이벤트를 전달하는 메커니즘과는 다른 동작이다.


ngOnChanges()의 작동 예시

다음은 ngOnChanges()가 어떻게 동작하는지를 보여주는 간단한 예시이다. 이 예에서는 부모 컴포넌트가 자식 컴포넌트에 값을 전달하고, 그 값이 변경될 때마다 ngOnChanges()가 호출되어 변화를 감지한다.

1. 자식 컴포넌트 (ChildComponent)

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>현재 값: {{ currentValue }}</p>`
})
export class ChildComponent implements OnChanges {
  @Input() currentValue: string;

  ngOnChanges(changes: SimpleChanges): void {
    console.log('변경 사항:', changes);
    if (changes.currentValue) {
      console.log('이전 값:', changes.currentValue.previousValue);
      console.log('새로운 값:', changes.currentValue.currentValue);
    }
  }
}

여기서 @Input()으로 부모 컴포넌트로부터 currentValue를 전달받는다. 그리고 ngOnChanges()는 이 값이 변경될 때마다 호출된다. changes 객체를 통해 변경 전 값변경 후 값을 확인할 수 있다.

 

2. 부모 컴포넌트 (ParentComponent)

import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h1>부모 컴포넌트</h1>
    <button (click)="changeValue()">값 변경</button>
    <app-child [currentValue]="parentValue"></app-child>
  `
})
export class ParentComponent {
  parentValue = '초기 값';

  changeValue() {
    this.parentValue = '변경된 값';
  }
}

부모 컴포넌트에서는 버튼을 클릭하면 parentValue가 변경된다. 이 변경이 발생할 때마다 자식 컴포넌트의 ngOnChanges()가 호출되어 값을 감지하고, 콘솔에 이전 값과 새로운 값을 출력하게 된다.


Angular 생명주기(Lifecycle) 훅들

Angular는 컴포넌트가 생성되고 소멸되기까지의 과정을 여러 단계로 나누어 관리한다. 각 단계에서 Angular는 특정한 생명주기 훅(Lifecycle Hook)을 호출하며, 이를 통해 개발자는 각 시점에서 컴포넌트의 상태를 제어할 수 있다.

주요 생명주기 훅들

  1. ngOnChanges(changes: SimpleChanges)
    • 언제: 컴포넌트의 @Input() 바인딩 값이 변경될 때마다 호출
    • 설명: 부모 컴포넌트로부터 전달된 값이 변경될 때 이를 감지하여 처리
  2. ngOnInit()
    • 언제: 컴포넌트가 초기화될 때 한 번 호출(DOM은 아직 렌더링되지 않음.)
    • 설명: 컴포넌트가 처음으로 초기화될 때 필요한 로직을 실행함. 주로 데이터 초기화나 서비스 호출에 사용됨.
  3. ngDoCheck()
    • 언제: Angular의 변경 감지(detection) 주기가 시작될 때마다 호출
    • 설명: Angular의 자동 변경 감지 외에 수동으로 변경된 사항을 처리하고 싶을 때 사용됨. 성능에 주의해서 사용해야 한다.
  4. ngAfterContentInit()
    • 언제: 부모 컴포넌트로부터 전달된 <ng-content>가 처음으로 삽입될 때 호출
    • 설명: ng-content가 DOM에 삽입된 직후에 필요한 로직을 처리할 수 있음
  5. ngAfterContentChecked()
    • 언제: Angular가 <ng-content>를 체크한 후 매번 호출
    • 설명: 부모 컴포넌트로부터 전달된 <ng-content>가 변경되었을 때 처리할 수 있음
  6. ngAfterViewInit()
    • 언제: 컴포넌트의 뷰가 처음으로 렌더링된 후 호출
    • 설명: 컴포넌트의 자식 뷰(템플릿)가 초기화된 후에 호출되므로, DOM에 대한 조작이 필요할 경우 이 훅을 사용함
  7. ngAfterViewChecked()
    • 언제: Angular가 컴포넌트의 뷰를 체크한 후 매번 호출
    • 설명: 컴포넌트의 뷰가 변경되었을 때 처리할 수 있음
  8. ngOnDestroy()
    • 언제: 컴포넌트가 파괴되기 직전에 호출
    • 설명: 메모리 누수를 방지하기 위해 리소스를 해제하거나, 구독(subscriptions)을 해지하는 데 사용됨

Angular 생명주기 훅의 실행 순서

  1. ngOnChanges()
  2. ngOnInit()
  3. ngDoCheck()
  4. ngAfterContentInit()
  5. ngAfterContentChecked()
  6. ngAfterViewInit()
  7. ngAfterViewChecked()
  8. ngOnDestroy()

ngOnChanges()는 이 생명주기 중에서 가장 먼저 호출되며, 이후 ngOnInit() 등 다른 훅들이 이어서 실행된다.