LogoCocode Skills

flutter-inspector-ui

UI 디버깅 전문가. 위젯 트리, 레이아웃 오버플로우 검사 시 사용

항목내용
ToolsRead, Glob, Grep
Modelinherit
Skillsflutter-inspector

Flutter Inspector - UI Agent#

위젯 트리를 런타임에서 검사하고 분석하는 전문 에이전트입니다.

트리거#

@flutter-inspector-ui 또는 다음 키워드 감지 시 자동 활성화:

  • 위젯 트리, 레이아웃
  • 오버플로우, 렌더링
  • UI 검사, 화면 분석

MCP 도구#

ui_get_widget_tree#

현재 화면의 위젯 트리를 반환합니다.

{
  "name": "ui_get_widget_tree",
  "description": "위젯 트리 조회",
  "inputSchema": {
    "type": "object",
    "properties": {
      "depth": {
        "type": "integer",
        "description": "트리 깊이",
        "default": 5
      },
      "includeRenderObjects": {
        "type": "boolean",
        "description": "RenderObject 정보 포함",
        "default": false
      }
    }
  }
}

응답 예시:

{
  "tree": {
    "type": "MaterialApp",
    "children": [
      {
        "type": "Scaffold",
        "children": [
          {
            "type": "AppBar",
            "properties": {"title": "Home"}
          },
          {
            "type": "ListView",
            "children": [
              {"type": "ListTile", "properties": {"title": "Item 1"}},
              {"type": "ListTile", "properties": {"title": "Item 2"}}
            ]
          }
        ]
      }
    ]
  },
  "totalWidgets": 15
}

ui_find_widgets#

특정 타입의 위젯을 검색합니다.

{
  "name": "ui_find_widgets",
  "description": "위젯 검색",
  "inputSchema": {
    "type": "object",
    "properties": {
      "type": {
        "type": "string",
        "description": "위젯 타입명 (예: Text, Container, ListView)"
      },
      "key": {
        "type": "string",
        "description": "위젯 Key 값"
      }
    }
  }
}

응답 예시:

{
  "widgets": [
    {
      "type": "Text",
      "path": "MaterialApp/Scaffold/Column/Text",
      "properties": {
        "data": "Hello World",
        "style": {"fontSize": 16, "fontWeight": "bold"}
      }
    },
    {
      "type": "Text",
      "path": "MaterialApp/Scaffold/Column/Row/Text",
      "properties": {
        "data": "Subtitle",
        "style": {"fontSize": 14}
      }
    }
  ],
  "count": 2
}

ui_get_screen_info#

현재 화면 정보를 반환합니다.

{
  "name": "ui_get_screen_info",
  "description": "화면 정보 조회",
  "inputSchema": {
    "type": "object",
    "properties": {}
  }
}

응답 예시:

{
  "screen": {
    "width": 390,
    "height": 844,
    "pixelRatio": 3.0,
    "orientation": "portrait",
    "padding": {
      "top": 47,
      "bottom": 34,
      "left": 0,
      "right": 0
    }
  },
  "device": {
    "platform": "iOS",
    "isPhysicalDevice": true
  }
}

ui_find_overflow#

오버플로우 문제가 있는 위젯을 찾습니다.

{
  "name": "ui_find_overflow",
  "description": "오버플로우 위젯 검색",
  "inputSchema": {
    "type": "object",
    "properties": {}
  }
}

응답 예시:

{
  "overflows": [
    {
      "type": "Row",
      "path": "Scaffold/Column/Row",
      "issue": "RIGHT OVERFLOW by 24.0 pixels",
      "size": {"width": 414, "height": 50},
      "constraints": {"maxWidth": 390}
    }
  ],
  "count": 1
}

ui_get_text_widgets#

모든 텍스트 위젯과 내용을 반환합니다.

{
  "name": "ui_get_text_widgets",
  "description": "텍스트 위젯 조회",
  "inputSchema": {
    "type": "object",
    "properties": {
      "includeStyle": {
        "type": "boolean",
        "description": "스타일 정보 포함",
        "default": false
      }
    }
  }
}

응답 예시:

{
  "textWidgets": [
    {
      "path": "Scaffold/AppBar/Text",
      "text": "홈",
      "style": {"fontSize": 20, "fontWeight": "w600"}
    },
    {
      "path": "Scaffold/Body/Column/Text",
      "text": "환영합니다",
      "style": {"fontSize": 16}
    }
  ],
  "count": 2
}

앱 통합 코드#

// lib/debug/mcp_ui_tools.dart
import 'package:mcp_toolkit/mcp_toolkit.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/rendering.dart';

void registerUITools() {
  if (!kDebugMode) return;

  addMcpTool(MCPCallEntry.tool(
    handler: (_) {
      final binding = WidgetsBinding.instance;
      final renderView = binding.renderView;

      return MCPCallResult(
        message: 'Screen info',
        parameters: {
          'screen': {
            'width': renderView.size.width,
            'height': renderView.size.height,
            'pixelRatio': binding.window.devicePixelRatio,
          },
        },
      );
    },
    definition: MCPToolDefinition(
      name: 'ui_get_screen_info',
      description: '화면 정보 조회',
      inputSchema: {'type': 'object', 'properties': {}},
    ),
  ));

  addMcpTool(MCPCallEntry.tool(
    handler: (params) {
      final depth = params['depth'] as int? ?? 5;
      final tree = _buildWidgetTree(depth);

      return MCPCallResult(
        message: 'Widget tree',
        parameters: {'tree': tree},
      );
    },
    definition: MCPToolDefinition(
      name: 'ui_get_widget_tree',
      description: '위젯 트리 조회',
      inputSchema: {
        'type': 'object',
        'properties': {
          'depth': {'type': 'integer', 'default': 5},
        },
      },
    ),
  ));

  // ui_find_widgets, ui_find_overflow, ui_get_text_widgets도 유사하게 구현
}

Map<String, dynamic> _buildWidgetTree(int maxDepth) {
  final rootElement = WidgetsBinding.instance.renderViewElement;
  if (rootElement == null) return {};

  return _elementToMap(rootElement, 0, maxDepth);
}

Map<String, dynamic> _elementToMap(Element element, int depth, int maxDepth) {
  final widget = element.widget;
  final result = <String, dynamic>{
    'type': widget.runtimeType.toString(),
  };

  if (depth < maxDepth) {
    final children = <Map<String, dynamic>>[];
    element.visitChildren((child) {
      children.add(_elementToMap(child, depth + 1, maxDepth));
    });
    if (children.isNotEmpty) {
      result['children'] = children;
    }
  }

  return result;
}

사용 예시#

위젯 트리 확인#

Q: 현재 화면의 위젯 구조 보여줘
A: ui_get_widget_tree depth=3 실행
   → Scaffold > AppBar + ListView > ListTile items

특정 위젯 찾기#

Q: 텍스트 위젯들 찾아줘
A: ui_get_text_widgets 실행
   → 15개 Text 위젯 발견, 내용 및 스타일 정보

오버플로우 검사#

Q: 레이아웃 오버플로우 문제 있나요?
A: ui_find_overflow 실행
   → Row 위젯에서 RIGHT OVERFLOW 24px 발견

화면 정보 확인#

Q: 현재 디바이스 화면 크기는?
A: ui_get_screen_info 실행
   → 390x844, portrait, iOS, 3.0x pixel ratio

일반적인 문제 진단#

레이아웃 오버플로우#

1. ui_find_overflow로 문제 위젯 식별
2. 해당 위젯 경로 확인
3. constraints vs size 비교
4. Expanded, Flexible, SingleChildScrollView 적용 제안

위젯 찾기 실패#

1. ui_find_widgets type="TargetWidget"
2. 위젯 존재 여부 확인
3. 위젯 트리 경로 추적
4. 조건부 렌더링 로직 검토

UI 성능 문제#

1. ui_get_widget_tree로 깊이 확인
2. 불필요하게 깊은 중첩 식별
3. const 위젯 사용 여부 확인
4. 리빌드 빈도 분석 (@flutter-inspector-bloc 연계)

반응형 레이아웃#

1. ui_get_screen_info로 화면 크기 확인
2. 다양한 크기에서 ui_find_overflow 실행
3. MediaQuery 기반 조건 검토

관련 에이전트#

  • @flutter-inspector: 마스터 인스펙터
  • @flutter-inspector-bloc: 상태와 UI 연결 확인
  • @flutter-ui: UI 컴포넌트 구현 가이드