Flutter 튜토리얼 74편: 성능 프로파일링 도구 - DevTools로 앱 성능 분석하기

요약#

핵심 요지#

  • 문제 정의: Flutter 앱에서 UI 버벅임, 높은 CPU 사용량, 메모리 누수 등의 성능 문제가 발생할 수 있다.
  • 핵심 주장: DevTools의 성능 분석 도구를 활용하면 문제의 원인을 정확히 파악하고 최적화할 수 있다.
  • 주요 근거: Flutter DevTools는 프레임 렌더링, CPU 사용량, 메모리 할당을 시각적으로 분석하는 기능을 제공한다.
  • 한계: 프로파일링은 앱 성능에 영향을 주므로 프로덕션 환경과 결과가 다를 수 있다.

문서가 설명하는 범위#

  • Performance 뷰로 프레임 렌더링 분석
  • CPU Profiler로 코드 실행 시간 분석
  • Memory 뷰로 메모리 사용량 및 누수 탐지
  • 성능 문제 해결을 위한 실전 가이드

읽는 시간: 25분 | 난이도: 중급


참고 자료#


문제 상황#

Flutter 앱이 느리게 동작하거나 버벅거릴 때, 문제의 원인을 찾기 어렵습니다. 코드만 보고는 어느 부분이 성능 병목인지 알 수 없습니다.

기존 방식의 한계#

// 성능 문제가 있는 코드 - 원인 파악이 어려움
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 빌드가 느린 이유는?
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
// 각 아이템 빌드 시간은?
return ExpensiveWidget(items[index]);
},
);
}
}

문제는 다음과 같습니다.

  • 어떤 위젯이 느린지 알 수 없다
  • CPU를 많이 사용하는 코드를 찾기 어렵다
  • 메모리 누수 여부를 확인하기 어렵다
  • 프레임 드롭의 원인을 파악하기 어렵다

해결 방법#

챕터 1: DevTools 성능 분석 개요#

Why#

NOTE

DevTools1는 Flutter 앱의 성능을 분석하는 공식 도구입니다. 시각적인 타임라인과 그래프로 성능 문제를 쉽게 파악할 수 있습니다.

What#

NOTE

DevTools의 성능 분석 도구는 세 가지 뷰로 구성됩니다.

flowchart TD subgraph DevTools["DevTools 성능 분석"] P[Performance View] C[CPU Profiler] M[Memory View] end subgraph Analysis["분석 대상"] P --> F[프레임 렌더링] P --> T[타임라인 이벤트] C --> E[코드 실행 시간] C --> CA[호출 스택] M --> H[힙 메모리] M --> L[메모리 누수] end
분석 대상사용 시점
Performance프레임 렌더링, UI/Raster 스레드화면이 버벅거릴 때
CPU Profiler메서드 실행 시간, 호출 빈도앱이 느릴 때
Memory힙 크기, 객체 할당메모리 사용량이 높을 때

How#

TIP

DevTools를 실행하는 방법입니다.

Terminal window
# 1. 프로파일 모드로 앱 실행 (성능 분석에 최적)
flutter run --profile
# 2. DevTools 열기 (터미널에서)
flutter pub global activate devtools
flutter pub global run devtools
# 또는 VS Code에서
# Dart: Open DevTools 명령 실행
// 프로파일 모드에서만 실행되는 코드
import 'package:flutter/foundation.dart';
if (kProfileMode) {
// 프로파일링용 코드
debugPrint('Profile mode: measuring performance...');
}

Watch out#

WARNING

성능 분석은 반드시 profile 모드에서 해야 합니다. debug 모드는 최적화가 없어 실제 성능과 크게 다릅니다.

Terminal window
# 잘못된 예: debug 모드 (기본값)
flutter run # 성능 분석에 부적합
# 올바른 예: profile 모드
flutter run --profile # 성능 분석에 적합
# release 모드는 DevTools 연결 불가
flutter run --release # 프로파일링 불가

결론: DevTools의 Performance, CPU Profiler, Memory 뷰를 활용하여 다양한 성능 문제를 분석할 수 있다.


챕터 2: Performance 뷰 - 프레임 분석#

Why#

NOTE

Flutter는 60fps(또는 고주사율 디스플레이에서 120fps)로 화면을 렌더링합니다. 한 프레임을 16ms 내에 완료하지 못하면 화면이 버벅거립니다(jank2).

What#

NOTE

Performance 뷰는 프레임 렌더링 과정을 타임라인으로 보여줍니다.

flowchart LR subgraph Frame["한 프레임 (16ms)"] UI[UI Thread] R[Raster Thread] end subgraph UIWork["UI Thread 작업"] B[build] L[layout] P[paint] end subgraph RasterWork["Raster Thread 작업"] S[rasterize] C[composite] end UI --> UIWork R --> RasterWork UIWork -->|"완료"| RasterWork
스레드역할과부하 시 증상
UI ThreadWidget 빌드, 레이아웃 계산사용자 입력 지연
Raster Thread픽셀 렌더링, GPU 작업화면 버벅임

How#

TIP

Performance 뷰에서 프레임을 분석하는 방법입니다.

// DevTools Performance 뷰 사용 순서
// 1. DevTools > Performance 탭 선택
// 2. Record 버튼 클릭
// 3. 앱에서 버벅거리는 동작 수행
// 4. Stop 버튼 클릭
// 5. 타임라인에서 빨간색 프레임 확인

프레임 차트 해석 방법입니다.

Frame Chart 색상:
초록색: 정상 프레임 (16ms 이하)
노란색: 약간 느림 (16-33ms)
빨간색: jank 발생 (33ms 이상)
문제 프레임 분석: 1. 빨간색 프레임 선택
2. Frame Analysis 탭에서 상세 정보 확인
3. UI vs Raster 시간 비교
4. 병목 스레드 파악

프레임 분석 예시입니다.

// 느린 빌드를 유발하는 코드 예시
class SlowWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 문제: build 메서드에서 무거운 연산
final processedData = expensiveComputation(); // build에서 호출하면 안 됨
return ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(
title: Text(processedData[index]),
);
},
);
}
}
// 개선된 코드
class OptimizedWidget extends StatefulWidget {
@override
State<OptimizedWidget> createState() => _OptimizedWidgetState();
}
class _OptimizedWidgetState extends State<OptimizedWidget> {
late List<String> processedData;
@override
void initState() {
super.initState();
// initState에서 한 번만 계산
processedData = expensiveComputation();
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: processedData.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(processedData[index]),
);
},
);
}
}

Watch out#

WARNING

Shader compilation jank3는 첫 실행 시 발생하는 특수한 버벅임입니다. 새로운 셰이더가 컴파일될 때 일시적으로 프레임이 지연됩니다.

// Shader 워밍업으로 해결 가능
// 앱 시작 시 필요한 셰이더를 미리 컴파일
// flutter build 시 셰이더 번들 생성
// flutter build apk --bundle-sksl-path flutter_01.sksl.json

결론: Performance 뷰의 프레임 차트로 jank가 발생하는 시점과 원인을 파악할 수 있다.


챕터 3: Performance 뷰 - 타임라인 이벤트#

Why#

NOTE

프레임 차트만으로는 구체적으로 어떤 작업이 느린지 알기 어렵습니다. Timeline Events4 탭에서 각 프레임의 세부 작업을 분석할 수 있습니다.

What#

NOTE

Timeline Events는 프레임 내의 모든 작업을 계층적으로 보여줍니다.

flowchart TD subgraph Frame["Frame #42"] B[Build] L[Layout] P[Paint] end subgraph BuildDetail["Build 상세"] B1[MyApp.build] B2[HomePage.build] B3[ListView.build] end B --> BuildDetail B1 --> B2 --> B3
이벤트 유형설명최적화 대상
BuildWidget 트리 구성불필요한 rebuild
Layout크기/위치 계산복잡한 레이아웃
Paint그리기 명령 생성과도한 클리핑
RasterGPU 렌더링큰 이미지, 복잡한 효과

How#

TIP

Timeline Events 분석 방법입니다.

Timeline Events 탭 사용법: 1. Performance 뷰에서 프레임 선택
2. Timeline Events 탭 클릭
3. 계층 구조에서 가장 긴 이벤트 확인
4. 이벤트 클릭하여 소요 시간 확인
5. 소스 코드 위치 파악

Flame Chart로 시각화된 타임라인입니다.

// Flame Chart 해석
// 가로축: 시간
// 세로축: 호출 스택 깊이
// 막대 너비: 해당 작업의 소요 시간
// 넓은 막대 = 오래 걸린 작업 = 최적화 대상
// 예: Build 이벤트가 10ms 이상이면
// - 어떤 Widget.build가 오래 걸리는지 확인
// - 해당 Widget 최적화 필요

타임라인 분석을 통한 최적화 예시입니다.

// 문제: Paint가 오래 걸리는 경우
class ProblematicWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ClipPath(
// ClipPath는 성능 비용이 높음
clipper: ComplexClipper(),
child: Container(
decoration: BoxDecoration(
// 복잡한 그라데이션도 비용 높음
gradient: RadialGradient(
colors: [Colors.red, Colors.blue, Colors.green],
),
boxShadow: [
// 그림자도 Paint 비용 증가
BoxShadow(blurRadius: 20, spreadRadius: 5),
],
),
child: child,
),
);
}
}
// 개선: 복잡한 효과 최소화
class OptimizedWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
// 단순한 테두리로 대체
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
),
child: child,
);
}
}

Watch out#

WARNING

RepaintBoundary5를 무분별하게 사용하지 마세요. 필요한 곳에만 사용해야 효과적입니다.

// RepaintBoundary 적절한 사용
// 자주 다시 그려지는 위젯을 분리할 때
// 좋은 예: 애니메이션이 있는 부분만 분리
Stack(
children: [
StaticBackground(), // 정적인 배경
RepaintBoundary(
child: AnimatedWidget(), // 자주 변경되는 부분만 분리
),
],
)
// 나쁜 예: 모든 위젯에 RepaintBoundary
// 오히려 메모리 사용량만 증가

결론: Timeline Events 탭에서 프레임 내 세부 작업을 분석하여 정확한 병목 지점을 찾을 수 있다.


챕터 4: CPU Profiler - 코드 실행 분석#

Why#

NOTE

앱이 전반적으로 느리거나 특정 작업이 오래 걸릴 때, 어떤 코드가 CPU 시간을 많이 사용하는지 파악해야 합니다. CPU Profiler6는 메서드별 실행 시간을 분석합니다.

What#

NOTE

CPU Profiler는 샘플링 방식으로 코드 실행을 기록합니다.

flowchart TD subgraph Sampling["CPU 샘플링"] S[250μs 간격] C[콜스택 캡처] end subgraph Views["분석 뷰"] BU[Bottom Up] CT[Call Tree] MT[Method Table] FC[Flame Chart] end S --> C --> Views
설명사용 시점
Bottom Up가장 많이 호출된 메서드부터핫스팟 찾기
Call Tree호출 계층 구조호출 경로 추적
Method Table메서드별 통계전체 현황 파악
Flame Chart시간순 시각화실행 흐름 이해

How#

TIP

CPU Profiler 사용 방법입니다.

Terminal window
# CPU 프로파일링 단계
# 1. DevTools > CPU Profiler 탭 선택
# 2. Record 버튼 클릭
# 3. 앱에서 느린 작업 수행
# 4. Stop 버튼 클릭
# 5. 결과 분석

Bottom Up 뷰 분석입니다.

Bottom Up 뷰 해석:
Self Time: 해당 메서드 자체 실행 시간
Total Time: 하위 호출 포함 전체 시간
정렬 기준:
- Self Time 높은 순 → 직접적인 병목
- Total Time 높은 순 → 전체적인 영향
예시:
jsonDecode (Self: 15%, Total: 15%)
_parseList (Self: 10%, Total: 10%)
→ JSON 파싱이 CPU 시간의 25% 차지

Call Tree 분석으로 호출 경로를 추적합니다.

// Call Tree 예시 해석
// main() → 100%
// └── MyApp.build() → 80%
// └── HomePage.build() → 70%
// └── _loadData() → 60%
// └── jsonDecode() → 50%
// → jsonDecode가 병목이지만
// 실제 문제는 _loadData가 build에서 호출되는 것
// 개선 전
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = jsonDecode(rawJson); // build에서 파싱하면 안 됨
return DataView(data: data);
}
}
// 개선 후
class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Future<Data> _dataFuture;
@override
void initState() {
super.initState();
_dataFuture = _loadAndParseData();
}
Future<Data> _loadAndParseData() async {
// 별도 작업으로 분리
return compute(jsonDecode, rawJson);
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _dataFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
return DataView(data: snapshot.data!);
}
return CircularProgressIndicator();
},
);
}
}

Watch out#

WARNING

CPU 샘플링 레이트를 조절할 수 있습니다. 높은 레이트는 정확도가 높지만 오버헤드도 증가합니다.

샘플링 레이트 설정:
Low (250μs): 기본값, 일반적인 분석에 적합
Medium (125μs): 더 정밀한 분석 필요 시
High (62.5μs): 매우 짧은 작업 분석 시
주의: 높은 레이트는 앱 성능에 영향

결론: CPU Profiler로 가장 많은 CPU 시간을 사용하는 코드를 찾아 최적화할 수 있다.


챕터 5: Memory 뷰 - 메모리 분석 기초#

Why#

NOTE

Flutter 앱의 메모리 사용량이 계속 증가하면 앱이 느려지거나 강제 종료될 수 있습니다. Memory 뷰7로 메모리 사용 패턴과 누수를 분석합니다.

What#

NOTE

Memory 뷰는 Dart 힙 메모리를 실시간으로 모니터링합니다.

flowchart LR subgraph Memory["Dart 메모리"] H[Heap] O[Objects] GC[GC] end subgraph Metrics["측정 항목"] U[Used] C[Capacity] E[External] end H --> O O --> GC Memory --> Metrics
메트릭설명
Used현재 사용 중인 힙 메모리
Capacity할당된 힙 크기
External외부 메모리 (이미지 등)
GC가비지 컬렉션 발생

How#

TIP

Memory 뷰 기본 사용법입니다.

Memory Chart 읽기:
파란색 영역: 사용 중인 힙
점선: 힙 용량
스파이크: 일시적인 메모리 증가
정상 패턴:
- 사용량이 증가 → GC 발생 → 감소 반복
- 기준선이 일정하게 유지
문제 패턴:
- 사용량이 계속 증가 (메모리 누수)
- GC 후에도 기준선이 높아짐

메모리 차트 분석 예시입니다.

// 메모리 누수 패턴 확인
// 1. Memory 뷰 열기
// 2. 특정 화면 진입/이탈 반복
// 3. 메모리 그래프 관찰
// 정상: 화면 이탈 후 메모리 감소
// 누수: 화면 이탈 후에도 메모리 유지/증가
// 누수 의심 코드 예시
class LeakyWidget extends StatefulWidget {
@override
State<LeakyWidget> createState() => _LeakyWidgetState();
}
class _LeakyWidgetState extends State<LeakyWidget> {
late StreamSubscription subscription;
@override
void initState() {
super.initState();
// 구독 시작
subscription = someStream.listen((data) {
setState(() {
// 데이터 처리
});
});
}
// 문제: dispose에서 구독 해제 안 함
// Widget이 제거되어도 구독이 유지되어 메모리 누수
@override
void dispose() {
subscription.cancel(); // 이 줄이 없으면 누수!
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}

Watch out#

WARNING

BuildContext를 비동기 콜백에서 사용할 때 주의하세요. Widget이 dispose된 후에도 콜백이 실행되면 문제가 됩니다.

// 문제: async 콜백에서 context 사용
class ProblematicWidget extends StatefulWidget {
@override
State<ProblematicWidget> createState() => _ProblematicWidgetState();
}
class _ProblematicWidgetState extends State<ProblematicWidget> {
Future<void> loadData() async {
final data = await fetchData();
// Widget이 이미 dispose 되었을 수 있음!
Navigator.of(context).push(...);
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: loadData,
child: Text('Load'),
);
}
}
// 해결: mounted 체크
class SafeWidget extends StatefulWidget {
@override
State<SafeWidget> createState() => _SafeWidgetState();
}
class _SafeWidgetState extends State<SafeWidget> {
Future<void> loadData() async {
final data = await fetchData();
// mounted 체크
if (!mounted) return;
Navigator.of(context).push(...);
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: loadData,
child: Text('Load'),
);
}
}

결론: Memory 뷰의 실시간 차트로 메모리 사용 패턴을 모니터링하고 누수를 탐지할 수 있다.


챕터 6: Memory 뷰 - 스냅샷 비교#

Why#

NOTE

메모리 차트에서 누수가 의심되면, 구체적으로 어떤 객체가 메모리에 남아있는지 확인해야 합니다. 힙 스냅샷8을 비교하면 누수된 객체를 찾을 수 있습니다.

What#

NOTE

Diff Snapshots 기능으로 두 시점의 메모리 상태를 비교합니다.

flowchart LR subgraph Before["스냅샷 1"] A1[화면 진입 전] end subgraph After["스냅샷 2"] A2[화면 이탈 후] end subgraph Diff["차이 분석"] D[새로 생성된 객체] R[유지된 객체] end Before --> Diff After --> Diff Diff --> D Diff --> R
용어설명
Shallow Size객체 자체의 크기
Retained Size객체 + 참조하는 객체들의 크기
Instances해당 클래스의 인스턴스 수

How#

TIP

Diff Snapshots 사용 방법입니다.

스냅샷 비교 절차:
1. 앱을 초기 상태로 만듦
2. Memory 뷰에서 "Take Heap Snapshot" 클릭 (스냅샷 1)
3. 의심되는 작업 수행 (예: 화면 진입/이탈)
4. "Take Heap Snapshot" 다시 클릭 (스냅샷 2)
5. "Diff Snapshots" 탭에서 비교
6. 인스턴스 수가 증가한 클래스 확인

누수 객체 찾기 예시입니다.

// Diff Snapshots 결과 해석
//
// Class Name | Instances | Shallow Size
// ---------------------------------------------------
// _MyWidgetState | +5 | +2,048 bytes
// StreamSubscription | +5 | +1,280 bytes
// Timer | +5 | +960 bytes
//
// → 화면을 5번 진입/이탈했는데 State가 5개 남아있음
// → StreamSubscription과 Timer도 함께 누수
// 원인: dispose에서 정리 안 함
class _MyWidgetState extends State<MyWidget> {
late Timer _timer;
late StreamSubscription _subscription;
@override
void initState() {
super.initState();
_timer = Timer.periodic(Duration(seconds: 1), (_) {
// 주기적 작업
});
_subscription = stream.listen((data) {
// 데이터 처리
});
}
@override
void dispose() {
_timer.cancel(); // 타이머 취소
_subscription.cancel(); // 구독 취소
super.dispose();
}
@override
Widget build(BuildContext context) => Container();
}

Trace Instances 기능으로 객체 참조 경로를 추적합니다.

Trace Instances 사용: 1. 누수된 클래스 선택
2. "Trace Instances" 체크
3. 새 스냅샷 캡처
4. 해당 인스턴스의 참조 경로 확인
5. 어디서 참조를 유지하는지 파악

Watch out#

WARNING

힙 스냅샷 캡처는 앱을 잠시 멈추게 합니다. 대규모 앱에서는 몇 초가 걸릴 수 있습니다.

// 스냅샷 캡처 시 주의사항
// - 앱이 일시 정지됨
// - 메모리가 많을수록 오래 걸림
// - 분석 중에는 앱을 조작하지 말 것

결론: Diff Snapshots으로 두 시점의 메모리를 비교하여 누수된 객체를 정확히 찾을 수 있다.


챕터 7: 실전 성능 최적화 팁#

Why#

NOTE

프로파일링 도구로 문제를 찾았다면 실제로 최적화해야 합니다. Flutter 앱에서 자주 발생하는 성능 문제와 해결 방법을 알아봅니다.

What#

NOTE

Flutter 성능 최적화의 주요 영역입니다.

flowchart TD subgraph Optimization["최적화 영역"] B[Build 최적화] R[Render 최적화] M[Memory 최적화] A[Async 최적화] end subgraph Techniques["기법"] B --> B1[const 생성자] B --> B2[Widget 분리] R --> R1[RepaintBoundary] R --> R2[이미지 캐싱] M --> M1[dispose 정리] M --> M2[약한 참조] A --> A1[compute] A --> A2[Isolate] end

How#

TIP

주요 최적화 기법들입니다.

1. Build 최적화

// const 생성자 사용
class MyWidget extends StatelessWidget {
const MyWidget({super.key}); // const 생성자
@override
Widget build(BuildContext context) {
return Column(
children: const [
Icon(Icons.star), // const
Text('Hello'), // const
SizedBox(height: 10), // const
],
);
}
}
// Widget 분리로 rebuild 범위 최소화
class ParentWidget extends StatefulWidget {
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
// ExpensiveWidget은 rebuild 안 됨
const ExpensiveWidget(),
// CounterWidget만 rebuild
CounterWidget(count: counter),
ElevatedButton(
onPressed: () => setState(() => counter++),
child: const Text('Increment'),
),
],
);
}
}

2. 리스트 최적화

// ListView.builder 사용 (필수!)
// 보이는 항목만 빌드
ListView.builder(
itemCount: 10000,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
// itemExtent 지정으로 성능 향상
ListView.builder(
itemCount: 10000,
itemExtent: 56.0, // 고정 높이
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)

3. 무거운 연산 분리

// compute 함수로 Isolate에서 실행
Future<List<Item>> loadAndParseData() async {
final rawData = await fetchRawData();
// 메인 스레드가 아닌 별도 Isolate에서 파싱
final items = await compute(parseData, rawData);
return items;
}
List<Item> parseData(String rawData) {
// 무거운 JSON 파싱
final json = jsonDecode(rawData);
return (json as List).map((e) => Item.fromJson(e)).toList();
}

4. 이미지 최적화

// 적절한 크기로 이미지 로드
Image.network(
imageUrl,
cacheWidth: 200, // 캐시 크기 제한
cacheHeight: 200,
)
// 이미지 캐싱
CachedNetworkImage(
imageUrl: imageUrl,
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)

Watch out#

WARNING

과도한 최적화는 오히려 해로울 수 있습니다. 항상 프로파일링으로 문제를 확인한 후 최적화하세요.

// 시기상조 최적화 피하기
// 문제가 확인되기 전까지는 단순하게 유지
// 나쁜 예: 모든 곳에 const, RepaintBoundary 추가
// - 코드 복잡성 증가
// - 실제 효과 미미할 수 있음
// 좋은 예: 프로파일링 → 병목 확인 → 해당 부분만 최적화

결론: 프로파일링으로 찾은 병목에 적절한 최적화 기법을 적용하여 성능을 개선한다.


한계#

  • 프로파일 모드 차이: 프로파일 모드와 릴리스 모드의 성능이 다를 수 있다
  • 오버헤드: 프로파일링 자체가 앱 성능에 영향을 준다
  • 플랫폼 차이: iOS와 Android에서 성능 특성이 다르므로 각각 테스트해야 한다
  • 실제 기기 필요: 에뮬레이터/시뮬레이터의 성능은 실제 기기와 다르다

Footnotes#

  1. DevTools(데브툴즈): Flutter와 Dart 앱을 분석하고 디버깅하는 공식 도구 모음이다.

  2. Jank(쟁크): 프레임 렌더링이 지연되어 화면이 버벅거리는 현상이다.

  3. Shader Compilation(셰이더 컴파일): GPU가 그래픽을 렌더링하기 위해 셰이더 프로그램을 컴파일하는 과정이다.

  4. Timeline Events(타임라인 이벤트): 프레임 렌더링 과정에서 발생하는 개별 작업들이다.

  5. RepaintBoundary(리페인트 바운더리): 하위 위젯의 repaint를 상위로 전파하지 않도록 분리하는 위젯이다.

  6. CPU Profiler(CPU 프로파일러): 코드 실행 시간과 호출 빈도를 분석하는 도구이다.

  7. Memory View(메모리 뷰): 앱의 메모리 사용량과 할당을 분석하는 도구이다.

  8. Heap Snapshot(힙 스냅샷): 특정 시점의 힙 메모리 상태를 캡처한 것이다.

공유

이 글이 도움이 되었다면 다른 사람과 공유해주세요!

Flutter 튜토리얼 74편: 성능 프로파일링 도구 - DevTools로 앱 성능 분석하기
https://moodturnpost.net/posts/flutter/flutter-performance-profiling-tools/
작성자
Moodturn
게시일
2026-01-08
Moodturn

목차