iBetter Books
수정

디버깅과 분석 도구 활용

코드를 작성하다 보면 예상치 못한 오류와 마주칩니다. print()로 찍어보는 방식은 한계가 있습니다. VS Code 디버거와 dart analyze, Dart DevTools를 제대로 활용하면 문제를 훨씬 빠르게 찾아낼 수 있습니다.


VS Code 디버거 기본 사용

디버그 실행

Dart 파일을 열고 F5를 누르면 디버그 모드로 실행됩니다. 또는 상단 메뉴 Run → Start Debugging을 선택합니다.

일반 실행(dart run)과 다른 점은 다음과 같습니다.

구분 dart run 디버그 실행 (F5)
브레이크포인트 지원 안 함 지원
변수 검사 print() 필요 사이드바에서 바로 확인
스택 추적 에러 시 출력 실시간 콜 스택 확인
성능 빠름 약간 느림

launch.json 설정

.vscode/launch.json이 없으면 VS Code가 자동으로 제안합니다. 수동으로 만들 때는 다음 내용을 사용합니다.

{  "version": "0.2.0",  "configurations": [    {      "name": "Debug Dart",      "type": "dart",      "request": "launch",      "program": "bin/main.dart",      "args": [],      "env": {        "APP_ENV": "development"      }    },    {      "name": "Debug Tests",      "type": "dart",      "request": "launch",      "program": "test/"    }  ]}

브레이크포인트

브레이크포인트는 코드 실행을 특정 줄에서 일시 중지하는 기능입니다.

설정 방법

줄 번호 왼쪽 영역을 클릭합니다. 빨간 점이 나타나면 브레이크포인트가 설정된 것입니다.

예제

다음 코드에서 result가 올바른지 확인해봅니다.

// bin/main.dart
void main() {
  final numbers = [1, 2, 3, 4, 5];
  var result = 0;

  for (final n in numbers) {
    result += n;  // ← 이 줄에 브레이크포인트 설정
  }

  print('합계: $result');
}

F5로 실행하면 브레이크포인트 줄에서 멈춥니다. 이때 왼쪽 Variables 패널에서 n, result 값을 실시간으로 확인할 수 있습니다.

디버그 단계 조작

단축키 동작
F5 계속 실행 (다음 브레이크포인트까지)
F10 한 줄 실행 (Step Over)
F11 함수 안으로 진입 (Step Into)
Shift+F11 함수 밖으로 나오기 (Step Out)
Shift+F5 디버그 중단

조건부 브레이크포인트

빨간 점을 오른쪽 클릭 후 Edit Breakpoint를 선택하면 조건을 지정할 수 있습니다.

조건 예시: n == 3

n이 3일 때만 멈추므로, 특정 조건에서만 발생하는 버그를 찾을 때 유용합니다.


변수와 감시 패널

디버그 중단 상태에서 확인할 수 있는 패널입니다.

Variables

현재 스코프의 모든 변수와 값을 보여줍니다. 중첩된 객체는 트리 구조로 펼쳐볼 수 있습니다.

Watch

특정 표현식을 계속 감시합니다. 왼쪽 패널의 Watch 섹션에서 + 버튼을 누르고 표현식을 입력합니다.

감시 표현식 예시:
  result * 2
  numbers.length
  numbers.reduce((a, b) => a + b)

Debug Console

디버그 중단 상태에서 임의의 Dart 표현식을 직접 실행할 수 있습니다.

// Debug Console에서 바로 입력
numbers.where((n) => n > 2).toList()
// 결과: [3, 4, 5]

dart analyze

정적 분석 도구입니다. 실행 전에 코드 오류, 경고, 스타일 위반을 찾아냅니다.

기본 사용

# 현재 프로젝트 전체 분석dart analyze# 특정 파일만 분석dart analyze lib/my_module.dart# 자세한 출력dart analyze --verbose

출력 형식

Analyzing my_project...
  error   • lib/src/calculator.dart:15:5   • The variable 'x' is declared but never used.
  warning • lib/src/calculator.dart:22:12  • Avoid 'print' in production code.
  info    • lib/src/calculator.dart:30:1   • Prefer 'const' constructors.
3 issues found.
수준 의미
error 컴파일 오류. 반드시 수정해야 합니다.
warning 런타임 문제 가능성이 있습니다.
info 스타일 개선 제안입니다.

VS Code 통합

저장(Cmd+S / Ctrl+S)할 때마다 자동으로 dart analyze가 실행됩니다. 결과는 Problems 패널(Cmd+Shift+M)에 표시됩니다.


analysis_options.yaml 예비 설명

dart analyze의 동작은 프로젝트 루트의 analysis_options.yaml로 제어합니다. 자세한 내용은 다음 챕터에서 다루지만, 기본 파일 형태는 다음과 같습니다.

include: package:lints/recommended.yamllinter:  rules:    - prefer_const_constructors    - avoid_print

Dart DevTools

Dart DevTools는 브라우저 기반 성능 분석 도구입니다. 메모리 사용량, CPU 프로파일, 타임라인, 로그 등을 시각적으로 확인할 수 있습니다.

실행 방법

디버그 모드로 실행한 뒤 VS Code 상태바 하단에 Dart DevTools 버튼이 나타납니다. 클릭하면 브라우저에서 DevTools가 열립니다.

또는 터미널에서 직접 실행합니다.

dart pub global activate devtoolsdart devtools

dart pub global 방식은 별도 설치 없이 SDK에 포함된 devtools를 사용할 수도 있습니다.

dart run devtools

주요 탭

기능
Debugger 브레이크포인트, 콜 스택, 변수 확인
Logging log(), print() 출력 필터링
Memory 힙 스냅샷, 메모리 누수 탐지
CPU Profiler 함수별 CPU 점유율 분석
Network HTTP 요청/응답 기록 (Flutter용)

콘솔 로그 대신 log() 사용

프로덕션 코드에서는 print() 대신 dart:developerlog()를 사용하면 DevTools Logging 탭에서 필터링할 수 있습니다.

import 'dart:developer';

void processData(List<int> data) {
  log('Processing ${data.length} items', name: 'DataProcessor');
  
  try {
    final result = data.reduce((a, b) => a + b);
    log('Result: $result', name: 'DataProcessor');
  } catch (e, stack) {
    log('Error occurred', name: 'DataProcessor', error: e, stackTrace: stack);
  }
}

실전 디버깅 시나리오

다음 코드에서 버그를 찾아보겠습니다.

// bin/main.dart
List<double> averages(List<List<int>> groups) {
  return groups.map((group) {
    final sum = group.reduce((a, b) => a + b);
    return sum / group.length;  // ← 문제 발생 가능 지점
  }).toList();
}

void main() {
  final data = [
    [1, 2, 3],
    [],            // ← 빈 리스트가 들어오면?
    [10, 20],
  ];

  final result = averages(data);
  print(result);
}
  1. sum / group.length 줄에 브레이크포인트를 설정합니다.
  2. F5로 실행합니다.
  3. 첫 번째 반복에서 멈추면 group 변수를 확인합니다.
  4. F5로 계속 진행하다 보면 빈 리스트에서 reduce 예외가 발생합니다.
  5. Debug Console에서 group.isEmpty를 입력해 원인을 확인합니다.

수정 코드입니다.

List<double> averages(List<List<int>> groups) {
  return groups.map((group) {
    if (group.isEmpty) return 0.0;
    final sum = group.reduce((a, b) => a + b);
    return sum / group.length;
  }).toList();
}

정리

이번 챕터에서 다룬 내용입니다.

  • VS Code 디버거로 브레이크포인트를 설정하고 변수를 실시간으로 확인합니다.
  • 조건부 브레이크포인트로 특정 상황에서만 멈추게 할 수 있습니다.
  • dart analyze는 실행 전에 오류와 경고를 미리 잡아냅니다.
  • Dart DevTools로 메모리와 성능을 시각적으로 분석합니다.
  • print() 대신 dart:developerlog()를 사용하면 DevTools와 통합됩니다.

다음 챕터에서는 dart fix, dart format, analysis_options.yaml로 코드 품질을 자동으로 관리하는 방법을 배웁니다.