Flutter iOS 실기기 디버깅 시 "Dart VM Service was not discovered after 60 seconds." 오류 해결하기

2026. 3. 6. 15:47Programming/Flutter

반응형

문제 상황

flutter run 명령으로 iOS 실기기에 앱을 배포하면, 빌드와 설치까지는 정상적으로 진행됩니다. 하지만 그 이후 아래와 같은 메시지가 출력되며 디버거 연결에 실패합니다.

Launching lib/main.dart on iPhone in debug mode...
Running Xcode build...
Xcode build done.                                           12.3s
Installing and launching...

Waiting for VM Service to become available...

약 60초간 대기한 뒤 아래 오류와 함께 종료됩니다.

Error: Failed to attach to the VM Service.
Dart VM Service was not discovered after 60 seconds.

Possible causes:
- The device is not connected to the same network as the host machine.
- The device is using a VPN.
- The application is not running in debug mode on the device.

앱 자체는 실기기에 정상 설치되어 실행까지 되지만, Hot Reload, breakpoint, DevTools 등 디버깅 기능을 전혀 사용할 수 없는 상태입니다.


원인 분석: Flutter는 어떻게 VM Service를 찾는가

이 문제를 이해하려면, Flutter가 iOS 실기기의 VM Service에 연결하는 메커니즘을 알아야 합니다.

VM Service 연결 흐름

[Flutter CLI] --USB--> [iOS 디바이스: 앱 설치 & 실행]
                              |
                     앱이 VM Service 시작
                     (랜덤 포트에서 리스닝)
                              |
                     mDNS(Bonjour)로 서비스 브로드캐스트
                              |
[Flutter CLI] <--mDNS 발견-- [VM Service 포트 정보]
                              |
                     포트 포워딩으로 디버거 연결

핵심은 mDNS(Bonjour) 입니다.

  1. Flutter CLI가 USB를 통해 앱을 실기기에 설치하고 실행합니다.
  2. 앱은 디버그 모드로 시작되며, Dart VM Service가 임의의 포트에서 리스닝을 시작합니다.
  3. 앱은 mDNS(Bonjour) 프로토콜을 사용하여 로컬 네트워크에 VM Service의 존재와 포트 번호를 브로드캐스트합니다.
  4. Flutter CLI는 이 mDNS 브로드캐스트를 수신하여 VM Service의 주소와 포트를 발견합니다.
  5. 발견된 정보를 기반으로 포트 포워딩을 설정하고 디버거를 연결합니다.

왜 mDNS 발견이 실패하는가

mDNS는 로컬 네트워크 멀티캐스트에 의존하기 때문에, 다양한 환경적 요인으로 실패할 수 있습니다.

  • iOS 로컬 네트워크 권한: iOS 14 이상에서 도입된 로컬 네트워크 접근 권한이 거부된 경우, mDNS 브로드캐스트가 차단됩니다.
  • 네트워크 환경: 기업 네트워크, 게스트 Wi-Fi 등에서 멀티캐스트 패킷이 차단될 수 있습니다.
  • 방화벽: Mac의 방화벽 설정이 mDNS 패킷 수신을 차단하는 경우가 있습니다.
  • VPN: VPN이 활성화되어 있으면 네트워크 라우팅이 변경되어 로컬 멀티캐스트가 정상 동작하지 않을 수 있습니다.
  • USB 연결 불안정: 케이블 또는 포트 문제로 통신이 불안정한 경우에도 발생할 수 있습니다.

일반적인 해결 시도

온라인에서 자주 제안되는 해결 방법들을 정리합니다. 많은 경우 이 방법들로 해결이 되지만, 그렇지 않은 경우도 있습니다.

1. iOS 로컬 네트워크 권한 확인

iOS 설정 > 개인정보 보호 > 로컬 네트워크에서 해당 앱의 권한이 허용되어 있는지 확인합니다. 앱을 삭제 후 재설치하면 권한을 다시 요청받을 수 있습니다.

2. 같은 네트워크 연결 확인

Mac과 iOS 디바이스가 동일한 Wi-Fi 네트워크에 연결되어 있는지 확인합니다. 또는 iPhone의 개인 핫스팟에 Mac을 연결하여 단순한 네트워크 환경을 만들어봅니다.

3. Mac 방화벽 비활성화

시스템 설정 > 네트워크 > 방화벽을 일시적으로 비활성화하여 방화벽이 원인인지 확인합니다.

4. VPN 비활성화

VPN이 활성화되어 있다면 비활성화한 뒤 다시 시도합니다.

5. 캐시 정리 및 재설치

# Flutter 캐시 정리
flutter clean
flutter pub get

# iOS 빌드 캐시 정리
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update
cd ..

# DerivedData 정리
rm -rf ~/Library/Developer/Xcode/DerivedData

# 실기기에서 앱 삭제 후 재실행
flutter run

6. 디바이스 신뢰 재설정

USB 케이블을 분리했다가 다시 연결하고, 디바이스에서 "이 컴퓨터를 신뢰하겠습니까?" 대화상자가 나타나면 신뢰를 선택합니다.

7. --verbose 플래그로 상세 로그 확인

flutter run --verbose

--verbose 옵션을 추가하면 mDNS 발견 과정의 상세 로그를 확인할 수 있어 어느 단계에서 실패하는지 파악하는 데 도움이 됩니다.


최종 해결: Xcode 실행 + VSCode Attach

위의 방법들을 모두 시도해도 문제가 해결되지 않는 경우, mDNS 발견 과정 자체를 우회하는 방법이 있습니다. Xcode에서 앱을 직접 실행하고, VSCode에서 이미 실행 중인 앱에 디버거를 attach하는 방식입니다.

Step 1: Xcode에서 앱 실행

# Runner.xcworkspace를 Xcode에서 열기
open ios/Runner.xcworkspace

Xcode에서:

  1. 상단의 디바이스 선택 메뉴에서 연결된 iOS 실기기를 선택합니다.
  2. Run (▶) 버튼을 눌러 앱을 실행합니다.
  3. Xcode 콘솔에서 아래와 같은 VM Service URL이 출력되는 것을 확인합니다.
flutter: The Dart VM service is listening on http://127.0.0.1:00000/XXXXXXXXXX=/

Xcode는 USB를 통한 직접 통신을 사용하므로 mDNS에 의존하지 않습니다. 따라서 mDNS 관련 문제를 완전히 우회할 수 있습니다.

Step 2: VSCode에서 Attach

Xcode에서 앱이 실행되고 있는 상태에서, VSCode의 디버깅 기능을 활용하려면 attach 방식으로 연결합니다.

launch.json 설정

.vscode/launch.json 파일에 다음 설정을 추가합니다.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Flutter: Attach",
      "type": "dart",
      "request": "attach"
    }
  ]
}

Attach 실행

  1. VSCode에서 Run and Debug (Ctrl+Shift+D / Cmd+Shift+D) 패널을 엽니다.
  2. 상단 드롭다운에서 "Flutter: Attach" 를 선택합니다.
  3. Start Debugging (F5) 를 누릅니다.
  4. Flutter extension이 자동으로 실행 중인 VM Service를 탐지하여 연결합니다.

연결이 성공하면 VSCode 하단 상태바가 주황색으로 변하며, 다음 기능들을 모두 사용할 수 있습니다.

  • Breakpoint 디버깅: 코드에 breakpoint를 설정하고 실행 흐름을 추적
  • Hot Reload: 코드 변경 시 Ctrl+S / Cmd+S로 즉시 반영
  • Hot Restart: 앱 상태를 초기화하며 재시작
  • DevTools: Flutter Inspector, Performance 탭 등 DevTools 연동
  • 변수 검사: Debug 패널에서 변수 값 확인 및 Watch 표현식 사용

Tip: flutter attach CLI 명령도 동일한 역할을 합니다. 터미널에서 flutter attach를 실행하면 VM Service를 탐지하여 연결을 시도하며, Hot Reload(r), Hot Restart(R) 등을 사용할 수 있습니다.


launch vs attach: 무엇이 다른가

Flutter 디버깅에서 launchattach는 앱 실행 주체와 디버거 연결 방식이 다릅니다.

구분 launch attach
앱 실행 주체 Flutter CLI / VSCode가 빌드부터 실행까지 전체 담당 외부(Xcode, 이미 실행 중인 앱 등)에서 실행된 앱에 연결
VM Service 발견 mDNS(Bonjour) 기반 자동 발견 이미 실행 중인 VM Service에 직접 연결
빌드 과정 flutter run이 빌드, 설치, 실행을 모두 수행 빌드/설치는 별도로 처리 (Xcode 등)
mDNS 의존성 있음 (발견 실패 시 타임아웃) 없음 (직접 연결)
사용 시나리오 일반적인 개발 워크플로우 mDNS 문제 우회, Native 코드 동시 디버깅
Hot Reload 지원 지원
Breakpoint 지원 지원

언제 어떤 방식을 사용해야 하는가

launch를 사용하는 경우:

  • mDNS가 정상 동작하는 네트워크 환경
  • Flutter 코드만 수정하는 일반적인 개발
  • 빠른 개발-테스트 사이클이 필요한 경우

attach를 사용하는 경우:

  • mDNS 발견이 실패하는 환경
  • Xcode에서 네이티브 코드와 Flutter 코드를 동시에 디버깅해야 하는 경우
  • 이미 실기기에서 실행 중인 앱에 디버거를 연결하고 싶은 경우
  • CI/CD 환경에서 빌드와 디버깅을 분리해야 하는 경우

정리

Flutter iOS 실기기 디버깅에서 "Dart VM Service was not discovered" 오류는 mDNS 기반 서비스 발견이 실패할 때 발생합니다. 로컬 네트워크 권한, 네트워크 환경, 방화벽, VPN 등 다양한 원인이 있으며, 이를 해결하기 위한 일반적인 방법들을 먼저 시도해볼 수 있습니다.

그래도 해결이 되지 않는다면, Xcode에서 앱을 직접 실행하고 VSCode에서 attach하는 방식으로 mDNS 의존성을 완전히 우회할 수 있습니다. 이 방법은 단순히 우회책이 아니라, 네이티브 코드와 Flutter 코드를 동시에 디버깅할 수 있다는 점에서 실무에서도 유용한 워크플로우입니다.

mDNS 문제 발생 시 해결 체크리스트:

1. iOS 로컬 네트워크 권한 확인
2. 동일 네트워크 연결 확인
3. Mac 방화벽 / VPN 비활성화
4. flutter clean & 캐시 정리
5. 디바이스 신뢰 재설정
6. (그래도 안되는 경우) Xcode 실행 + VSCode Attach
반응형