효율적인 Angular 렌더링, 재렌더링, 변경 감지 이해하기
2025-04-08 01:19:19Angular 렌더링 및 재렌더링 이해하기
Angular는 웹 애플리케이션 개발에 있어 강력한 프레임워크입니다. React와는 다르게 Angular는 실시간으로 DOM을 사용하고, 변경 감지 메커니즘을 통해 UI가 최신 데이터를 반영하는지 확인합니다. React에서 Angular로 전환하거나 Angular를 처음 시작하는 분들에게는 이 과정이 다소 복잡하게 느껴질 수 있습니다. 이번 글에서는 Angular의 렌더링 프로세스, 변경 감지 메커니즘, 재렌더링 전략에 대해 자세히 설명드리겠습니다.
Angular의 렌더링 및 재렌더링 과정
Angular의 렌더링 과정은 다음과 같이 요약할 수 있습니다:
- 초기 렌더링: Angular가 컴포넌트를 처음 생성할 때, 템플릿을 처리하고 컴포넌트의 데이터와 템플릿을 바인딩합니다.
- 변경 감지: 컴포넌트가 초기화되면, Angular는 데이터 변경을 감지하기 시작합니다. 데이터 바인딩된 속성이 변경될 때마다 Angular는 전체 컴포넌트 트리를 루트에서부터 점검합니다.
- 재렌더링: 컴포넌트의 데이터가 변경되면, Angular는 변경 감지 주기를 다시 실행하여 DOM을 직접 재렌더링합니다.
하지만, 변경 감지가 전체 컴포넌트 트리를 점검하는 과정이 효율적인지 의문이 들 수 있습니다. 이 과정의 효율성을 높이기 위한 방법들을 살펴보겠습니다.
전체를 재렌더링하는가, 바뀐 부분만 재렌더링하는가?
Angular는 사실상 데이터가 일부만 변경되더라도 모든 바인딩을 점검합니다. 이는 React의 가상 DOM 차등화(differing) 메커니즘보다 비효율적으로 보일 수 있습니다. React는 변경된 요소만 재렌더링하지만, Angular는 전체 바인딩을 체크합니다. 하지만 Angular는 OnPush 변경 감지 전략이나 *ngFor의 TrackBy 기능과 같은 최적화 방안을 제공합니다.
Angular의 변경 감지 메커니즘 살펴보기
Angular의 변경 감지는 컴포넌트 트리를 순회하면서 각 바인딩이 변경되었는지 확인합니다. 변경이 감지되면, Angular는 DOM을 업데이트합니다.
OnPush란 무엇인가?
OnPush 변경 감지는 특정 조건에서만 컴포넌트를 체크합니다:
- 컴포넌트의 Input 속성이 변경될 때
- 이벤트가 발생할 때 (예: 버튼 클릭)
- 옵저버블이 새로운 값을 방출할 때
이는 대규모 애플리케이션에서 성능을 향상시킬 수 있습니다. 변경되지 않은 컴포넌트에 대해 불필요한 체크를 피할 수 있습니다.
@Component({
selector: 'app-my-component',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './my-component.component.html',
})
export class MyComponent {
@Input() data: any;
}
왜 Angular는 모든 컴포넌트를 체크할까?
Angular의 기본 변경 감지는 전체 컴포넌트 트리를 순회합니다. 변경된 데이터를 확인하기 위해 만들어진 디자인이지만, 이는 대규모 애플리케이션에서는 비효율적일 수 있습니다. React의 가상 DOM처럼 이전 DOM의 스냅샷을 유지하지 않아, 세밀한 수준에서 변경을 감지하긴 어렵습니다.
템플릿에서 함수 사용의 문제점
Angular는 양방향 데이터 바인딩 메커니즘을 가지고 있으며, 이는 반응성을 보장합니다. 그러나, 템플릿에서 함수를 호출하는 것은 주의해야 합니다. 템플릿 내 함수는 변경 감지 주기마다 재평가되기 때문에 성능에 부정적인 영향을 미칠 수 있습니다.
{{ computeValue() }}
위와 같은 함수 호출은 비효율적일 수 있습니다. 대신, 계산된 프로퍼티(getter)나 시그널(Signal, Angular 16.2+)을 사용하여 상태를 효율적으로 추적하는 것이 좋습니다.
get computedValue(): number {
return this.data * 10;
}
이렇게 하면 값이 한 번 계산되고, Angular는 재렌더링을 최적화할 수 있습니다.
Angular의 성능 최적화 전략
렌더링과 변경 감지 최적화를 위해 사용할 수 있는 전략들을 알아봅시다.
OnPush 변경 감지 사용
앞서 언급했듯이, OnPush 전략은 불필요한 재렌더링을 크게 줄입니다. 컴포넌트의 입력값이나 옵저버블 변경, 이벤트 발생 시에만 체크하므로, 최적화가 가능합니다.
*ngFor와 TrackBy 사용
*ngFor를 사용할 때, Angular는 리스트의 모든 항목에 대해 새 DOM 요소를 생성합니다. 리스트가 클 경우 비효율적입니다. TrackBy를 사용해 변한 항목만 재생성하도록 최적화할 수 있습니다.
<div *ngFor="let item of items; trackBy: trackById">
{{ item.name }}
</div>
trackById(index: number, item: any): number {
return item.id;
}
템플릿 내 함수 사용 지양
함수를 직접 호출하지 말고, 계산된 프로퍼티나 시그널(Signal)을 사용하여 상태 변화를 효율적으로 관리하세요.
ngOnChanges와 Input Setter 활용
입력 값 변경을 효율적으로 처리하기 위해 Angular는 Input Setter와 ngOnChanges를 제공합니다. 수동으로 변경 여부를 체크하기보다는 이러한 라이프사이클 훅을 사용해 반응성을 최적화하세요.
@Input() set data(value: any) {
this._data = value;
}
ngOnChanges 대신 이를 사용하여 입력 속성 변경을 효율적으로 관리하세요.
결론
Angular의 렌더링, 재렌더링, 변경 감지 메커니즘을 이해하는 것은 효율적인 애플리케이션을 구축하기 위한 열쇠입니다. OnPush 변경 감지, *ngFor의 TrackBy 사용, 템플릿에서 함수 호출을 피하고 시그널(Signal)을 활용하는 등의 전략을 통해 성능을 최적화할 수 있습니다.
비록 Angular는 React와 달리 가상 DOM을 사용하지 않지만, 강력한 변경 감지 시스템을 통해 최적화가 가능합니다. 이러한 전략들을 구현하여 앱의 반응성을 향상시키고, 사용자 경험을 더욱 부드럽고 효율적으로 만들어 보세요.