[Angular] 성능 최적화(Performance optimization)

Angular는 개발자가 고성능 웹 애플리케이션을 구축하는 데 도움을 줄 수 있는 강력한 프런트 엔드 프레임워크입니다. 그러나 애플리케이션이 복잡해짐에 따라 원하는 수준의 성능을 유지하는 것이 더욱 어려워질 수 있습니다.

이 글에서는 Angular 성능을 최적화하는 몇 가지 기술을 살펴보겠습니다.

1. 지연 로딩 모듈(Lazy Loading Modules)

애플리케이션 성능이 저하되는 주요 이유 중 하나는 애플리케이션을 로드하는 데 걸리는 시간입니다. 이 문제를 해결하는 한 가지 방법은 지연 로딩을 사용하는 것입니다. 지연 로딩은 특정 경로에 필요한 모듈만 로드하는 기술입니다. 즉, 초기 로드 시간이 줄어들고 애플리케이션의 응답 속도가 빨라집니다.

다음은 Angular 애플리케이션에서 지연 로딩을 구현하는 방법에 대한 예입니다.

1
2
3
4
5
6
const routes: Routes = [
{
path: 'admin',
loadChildren: () => import('./admin/admin.module').then((m) => m.AdminModule),
},
];

이 예에서는 admin 경로에 액세스할 때 AdminModule 모듈을 지연 로딩합니다. 이 모듈은 필요할 때만 로드되므로 애플리케이션의 초기 로드 시간을 줄이는 데 도움이 됩니다.

2. 변화 감지 전략(Change Detection Strategies)

Angular는 변경 감지를 사용하여 데이터 변경 사항을 추적하고 그에 따라 뷰를 업데이트합니다. 기본적으로 Angular는 모든 변경 감지 주기에서 모든 컴포넌트를 확인하는 Default 라는 전략을 사용합니다. 특히 컴포넌트가 많은 대규모 애플리케이션의 경우 비용이 매우 많이 들 수 있습니다.

이 문제를 해결하기 위해 Angular는 몇 가지 변경 감지 전략을 제공합니다. 가장 일반적으로 사용되는 전략은 OnPush 입니다. 이 전략을 사용하면 컴포넌트의 입력 속성이 변경되거나 이벤트가 트리거 될 때만 변경 감지가 실행됩니다. 이를 통해 불필요한 변경 감지 주기 수를 크게 줄일 수 있습니다.

다음은 OnPush 변경 감지 전략을 사용하는 방법에 대한 예입니다.

1
2
3
4
5
6
7
8
9
10
11
12
@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MyComponentComponent implements OnInit {
@Input() myData: any;

constructor() {}

ngOnInit(): void {}
}

이 예에서는 MyComponentComponent 에 대한 OnPush 변경 감지 전략을 사용하고 있습니다. 즉, 변경 감지는 myData 입력 속성이 변경되거나 이벤트가 트리거 될 때만 실행됩니다.

3. 변경 감지 최적화(Change Detection Optimization)

OnPush 변경 감지 전략을 사용하더라도 불필요한 변경 감지 주기로 인해 성능 문제가 발생할 수 있습니다. 이 문제를 해결하기 위해 여러 가지 최적화 기술을 사용할 수 있습니다.

a. Immutable Objects

불변 객체(Immutable Objects)는 생성된 후에는 변경할 수 없는 객체입니다. 애플리케이션에서 불변 객체를 사용함으로써 불필요한 변경 감지 주기 수를 줄일 수 있습니다. 변경 감지는 기존 객체가 업데이트될 때가 아니라 새 객체가 생성될 때만 실행되어야 하기 때문입니다.

다음은 Angular 애플리케이션에서 불변 객체를 사용하는 방법에 대한 예입니다.

1
2
3
4
5
export interface User {
readonly id: number;
readonly name: string;
readonly email: string;
}

이 예에서는 readonly 키워드를 사용하여 User 인터페이스의 속성을 변경할 수 없게 만듭니다.

b. TrackBy Function

trackBy 함수는 Angular에 내장된 최적화 기술입니다. 항목 목록의 변경 사항을 추적하는 방법을 Angular에 알려주는 데 사용됩니다. 기본적으로 Angular는 목록에 있는 각 항목의 ID를 비교하여 변경 사항을 추적합니다. 그러나 이는 특히 큰 목록의 경우 비용이 매우 많이 들 수 있습니다.

다음은 Angular 애플리케이션에서 trackBy 함수를 사용하는 방법에 대한 예입니다.

1
2
3
4
5
<ul>
<li *ngFor="let user of users; trackBy: trackByUserId">
{{ user.name }}
</li>
</ul>

이 예에서는 trackBy 함수를 사용하여 Angular 에 id 속성으로 users 목록의 변경 사항을 추적하도록 지시합니다. 이는 목록에 있는 항목의 id 속성이 변경될 때만 변경 감지가 실행되어야 함을 의미합니다.

1
2
3
trackByUserId(index: number, user: User): number {
return user.id;
}

이 예제에서는 인덱스와 사용자 개체를 가져와 사용자 개체의 id 속성을 반환하는 trackByUserId 함수를 구현합니다.

4. NgZone

NgZone 은 Angular 영역 외부에서 코드를 실행하는 방법을 제공하는 Angular 에 내장된 서비스입니다. Angular 영역은 변경 감지 및 기타 Angular 관련 작업을 담당하는 실행 컨텍스트입니다. Angular 영역 외부에서 코드를 실행하면 애플리케이션 성능을 향상시킬 수 있습니다.

다음은 Angular 애플리케이션에서 NgZone을 사용하는 방법에 대한 예입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Component, NgZone } from '@angular/core';

@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
})
export class MyComponentComponent {
constructor(private ngZone: NgZone) {}

runOutsideAngular(): void {
this.ngZone.runOutsideAngular(() => {
// Code to run outside of the Angular zone
});
}
}

이 예에서는 NgZone 서비스를 사용하여 Angular 영역 외부에서 코드를 실행합니다. runOutsideAngular 메서드를 호출하고 Angular 영역 외부에서 실행되는 코드가 포함된 콜백 함수를 전달하여 이를 수행합니다.

외부 API 에서 일부 데이터를 가져와서 화면에 표시하는 컴포넌트가 있다고 가정해 보겠습니다. API 호출을 완료하는 데 오랜 시간이 걸릴 수 있으며, 이로 인해 애플리케이션이 정지되고 응답하지 않게 될 수 있습니다. 이러한 일이 발생하지 않도록 하려면 NgZone을 사용하여 Angular 영역 외부에서 API 호출을 실행하면 애플리케이션이 계속해서 원활하게 실행될 수 있습니다.

컴포넌트의 코드는 다음과 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import { Component, NgZone } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
})
export class MyComponentComponent {
data: any;

constructor(private http: HttpClient, private ngZone: NgZone) {}

fetchData(): void {
// Run the API call outside of the Angular zone
this.ngZone.runOutsideAngular(() => {
// Make the API call
this.http.get('https://api.example.com/data').subscribe(
(data) => {
// Update the data property with the fetched data
this.ngZone.run(() => {
this.data = data;
});
},
(error) => {
console.error(error);
}
);
});
}
}

이 예에서는 HttpClient 서비스를 사용하여 https://api.example.com/data에 대한 API 호출을 만듭니다. 또한 NgZone 서비스를 사용하여 Angular 영역 외부에서 API 호출을 실행한 다음 Angular 영역 내부에서 가져온 데이터로 data 속성을 업데이트합니다. 이렇게 하면 API 호출이 진행되는 동안 애플리케이션의 응답성이 유지됩니다.

또한 API 호출 중에 발생할 수 있는 모든 오류를 콘솔에 기록하여 처리하고 있습니다.

템플릿에서 이 컴포넌트를 사용하려면 다음과 같이 할 수 있습니다.

1
2
3
4
5
6
7
8
9
<button (click)="fetchData()">Fetch Data</button>

<div *ngIf="data">
<ul>
<li *ngFor="let item of data">
{{ item.name }}
</li>
</ul>
</div>

결론

Angular 성능을 최적화하기 위한 몇 가지 기술을 살펴보았습니다. 지연 로딩, 변경 감지 전략, 변경 감지 최적화 기술 및 NgZone을 사용하여 애플리케이션 성능을 향상하고 더 나은 사용자 경험을 제공할 수 있습니다. 성능 최적화는 지속적인 프로세스라는 점을 명심하는 것이 중요하며 잠재적인 개선 영역이 있는지 애플리케이션을 지속적으로 평가해야 합니다.

Share