{"id":86,"date":"2025-07-16T14:46:49","date_gmt":"2025-07-16T05:46:49","guid":{"rendered":"http:\/\/34.64.61.65\/?p=86"},"modified":"2025-07-16T14:52:14","modified_gmt":"2025-07-16T05:52:14","slug":"5-flutter-%eb%9e%9c%eb%8d%94%eb%a7%81-%ec%8b%9c%ec%8a%a4%ed%85%9c-%ec%99%84%ec%a0%84-%ec%a0%95%eb%b3%b5","status":"publish","type":"post","link":"https:\/\/hed-g.me\/?p=86","title":{"rendered":"5. [Flutter] \ub79c\ub354\ub9c1 \uc2dc\uc2a4\ud15c \uc644\uc804 \uc815\ubcf5"},"content":{"rendered":"\n<h1 class=\"wp-block-heading is-style-text-subtitle is-style-text-subtitle--1\">Flutter \ub80c\ub354\ub9c1 \uc2dc\uc2a4\ud15c \uc644\uc804 \uc815\ubcf5: \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc790\ub97c \uc704\ud55c \uc2ec\ud654 \uac00\uc774\ub4dc<\/h1>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\uc548\ub4dc\ub85c\uc774\ub4dc\/iOS \uac1c\ubc1c \uacbd\ud5d8\uc774 \uc788\ub294 \uac1c\ubc1c\uc790\ub77c\uba74 \ubc18\ub4dc\uc2dc \uc54c\uc544\uc57c \ud560 Flutter\uc758 \ub80c\ub354\ub9c1 \uba54\ucee4\ub2c8\uc998\uacfc \uc131\ub2a5 \ucd5c\uc801\ud654 \uc804\ub7b5<\/p>\n<\/blockquote>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ub4e4\uc5b4\uac00\uba70: \uc65c Flutter\uc758 \ub80c\ub354\ub9c1 \uc2dc\uc2a4\ud15c\uc744 \uc54c\uc544\uc57c \ud560\uae4c?<\/h2>\n\n\n\n<p>\uc548\ub4dc\ub85c\uc774\ub4dc\ub098 iOS \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc744 \ud574\ubcf4\uc2e0 \ubd84\uc774\ub77c\uba74, \uac01 \ud50c\ub7ab\ud3fc\uc758 UI \ub80c\ub354\ub9c1 \ubc29\uc2dd\uc5d0 \uc775\uc219\ud558\uc2e4 \uac83\uc785\ub2c8\ub2e4. \uc548\ub4dc\ub85c\uc774\ub4dc\uc758 View \uc2dc\uc2a4\ud15c, iOS\uc758 UIKit&#8230; \ud558\uc9c0\ub9cc Flutter\ub294 \uc644\uc804\ud788 \ub2e4\ub978 \uc811\uadfc \ubc29\uc2dd\uc744 \ucde8\ud569\ub2c8\ub2e4. <\/p>\n\n\n\n<p><strong>&#8220;Flutter\ub294 \uc65c \ub124\uc774\ud2f0\ube0c\ubcf4\ub2e4 \ube60\ub974\ub2e4\uace0 \ud558\ub294 \uac78\uae4c?&#8221;<\/strong><\/p>\n\n\n\n<p>\uc774 \uc9c8\ubb38\uc5d0 \ub2f5\ud558\ub824\uba74 Flutter\uc758 \ub80c\ub354\ub9c1 \uc544\ud0a4\ud14d\ucc98\ub97c \uc774\ud574\ud574\uc57c \ud569\ub2c8\ub2e4. \ub2e8\uc21c\ud788 \uc704\uc82f\uc744 \ubc30\uce58\ud558\ub294 \uac83\uc774 \uc544\ub2c8\ub77c, \uc5b4\ub5bb\uac8c \ud654\uba74\uc5d0 \uadf8\ub824\uc9c0\ub294\uc9c0, \uc65c \uc131\ub2a5\uc774 \uc88b\uc740\uc9c0, \uadf8\ub9ac\uace0 \uc6b0\ub9ac\uac00 \uc5b4\ub5bb\uac8c \ucd5c\uc801\ud654\ud560 \uc218 \uc788\ub294\uc9c0 \uc54c\uc544\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\uae30\uc874 \ud06c\ub85c\uc2a4 \ud50c\ub7ab\ud3fc\uacfc Flutter\uc758 \ucc28\uc774\uc810<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uae30\uc874 \ud06c\ub85c\uc2a4 \ud50c\ub7ab\ud3fc \ud504\ub808\uc784\uc6cc\ud06c\uc758 \ud55c\uacc4<\/h3>\n\n\n\n<p>\uae30\uc874\uc758 React Native, Xamarin \uac19\uc740 \ud06c\ub85c\uc2a4 \ud50c\ub7ab\ud3fc \ud504\ub808\uc784\uc6cc\ud06c\ub4e4\uc740 \ub2e4\uc74c\uacfc \uac19\uc740 \uad6c\uc870\ub97c \uac00\uc9d1\ub2c8\ub2e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>JavaScript\/C# \ucf54\ub4dc \u2192 Bridge \u2192 \ub124\uc774\ud2f0\ube0c UI \ucef4\ud3ec\ub10c\ud2b8<\/code><\/pre>\n\n\n\n<p><strong>\ubb38\uc81c\uc810:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\ube0c\ub9bf\uc9c0 \uc624\ubc84\ud5e4\ub4dc<\/strong>: JavaScript\uc640 \ub124\uc774\ud2f0\ube0c \uac04 \ud1b5\uc2e0 \ube44\uc6a9<\/li>\n\n\n\n<li><strong>\ud50c\ub7ab\ud3fc \uc758\uc874\uc131<\/strong>: \uac01 \ud50c\ub7ab\ud3fc\uc758 UI \uc5c5\ub370\uc774\ud2b8 \ubc29\uc2dd\uc5d0 \uc758\uc874<\/li>\n\n\n\n<li><strong>\uc131\ub2a5 \ubcd1\ubaa9<\/strong>: \ubcf5\uc7a1\ud55c \uc560\ub2c8\uba54\uc774\uc158\uc774\ub098 \uc2a4\ud06c\ub864 \uc2dc \ud504\ub808\uc784 \ub4dc\ub78d<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Flutter\uc758 \ud601\uc2e0\uc801 \uc811\uadfc<\/h3>\n\n\n\n<p>Flutter\ub294 \uc644\uc804\ud788 \ub2e4\ub978 \ucca0\ud559\uc744 \ud0dd\ud588\uc2b5\ub2c8\ub2e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Dart \ucf54\ub4dc \u2192 Skia \ub80c\ub354\ub9c1 \uc5d4\uc9c4 \u2192 \ud53d\uc140 \uc9c1\uc811 \uc81c\uc5b4<\/code><\/pre>\n\n\n\n<p><strong>Flutter\uc758 \uc7a5\uc810:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\ube0c\ub9bf\uc9c0 \uc81c\uac70<\/strong>: \ub124\uc774\ud2f0\ube0c UI \ucef4\ud3ec\ub10c\ud2b8\ub97c \uac70\uce58\uc9c0 \uc54a\uc74c<\/li>\n\n\n\n<li><strong>\uc77c\uad00\ub41c \ub80c\ub354\ub9c1<\/strong>: \ubaa8\ub4e0 \ud50c\ub7ab\ud3fc\uc5d0\uc11c \ub3d9\uc77c\ud55c \ub80c\ub354\ub9c1 \uc5d4\uc9c4 \uc0ac\uc6a9<\/li>\n\n\n\n<li><strong>\ud53d\uc140 \uc218\uc900 \uc81c\uc5b4<\/strong>: \ud504\ub808\uc784\uc6cc\ud06c\uac00 \uc9c1\uc811 \ud654\uba74\uc744 \uadf8\ub9bc<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Flutter \ub80c\ub354\ub9c1 \ud30c\uc774\ud504\ub77c\uc778 \uc2ec\ud654 \ubd84\uc11d<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. \ub80c\ub354\ub9c1 \ud30c\uc774\ud504\ub77c\uc778 \uac1c\uc694<\/h3>\n\n\n\n<p>Flutter\uc758 \ub80c\ub354\ub9c1\uc740 \ub450 \uac1c\uc758 \uc8fc\uc694 \uc2a4\ub808\ub4dc\uc5d0\uc11c \uc791\ub3d9\ud569\ub2c8\ub2e4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UI Thread (Dart)     GPU Thread (C++)\n      \u2502                    \u2502\n   1. Build            6. Rasterize\n   2. Layout           7. Composite\n   3. Paint            8. Display\n   4. Composite\n   5. Scene \uc0dd\uc131\n      \u2502                    \u2502\n      \u2514\u2500\u2500\u2500\u2500 Layer Tree \u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. UI Thread\uc5d0\uc11c \uc77c\uc5b4\ub098\ub294 \uc77c\ub4e4<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Build Phase (\ube4c\ub4dc \ub2e8\uacc4)<\/h4>\n\n\n\n<p>\uc704\uc82f \ud2b8\ub9ac\uac00 \uc2e4\uc81c \ub80c\ub354\ub9c1 \uac00\ub2a5\ud55c \uac1d\uccb4\ub85c \ubcc0\ud658\ub418\ub294 \ub2e8\uacc4\uc785\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \uc774 \uac04\ub2e8\ud55c \ucf54\ub4dc\uac00...\nContainer(\n  color: Colors.blue,\n  child: Row(\n    children: &#91;\n      Image.network('https:\/\/example.com\/image.png'),\n      const Text('Hello Flutter'),\n    ],\n  ),\n)\n\n\/\/ \uc2e4\uc81c\ub85c\ub294 \uc774\ub807\uac8c \ubcf5\uc7a1\ud55c \uc704\uc82f \ud2b8\ub9ac\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4\nContainer\n\u251c\u2500\u2500 ColoredBox (color \uc18d\uc131 \ub54c\ubb38\uc5d0 \uc790\ub3d9 \uc0dd\uc131)\n\u2502   \u2514\u2500\u2500 Row\n\u2502       \u251c\u2500\u2500 RawImage (Image.network\uac00 \ub0b4\ubd80\uc801\uc73c\ub85c \uc0ac\uc6a9)\n\u2502       \u2514\u2500\u2500 RichText (Text\uac00 \ub0b4\ubd80\uc801\uc73c\ub85c \uc0ac\uc6a9)<\/code><\/pre>\n\n\n\n<p><strong>\uac1c\ubc1c\uc790 \ud301<\/strong>: <code>flutter inspector<\/code>\ub97c \uc0ac\uc6a9\ud558\uba74 \uc2e4\uc81c \uc704\uc82f \ud2b8\ub9ac\ub97c \ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Layout Phase (\ub808\uc774\uc544\uc6c3 \ub2e8\uacc4)<\/h4>\n\n\n\n<p>\ubc15\uc2a4 \uc81c\uc57d\uc870\uac74(Box Constraints) \uc2dc\uc2a4\ud15c\uc744 \uc0ac\uc6a9\ud55c \ub808\uc774\uc544\uc6c3 \uacc4\uc0b0:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Flutter\uc758 \ub808\uc774\uc544\uc6c3 \uc6d0\uce59\n\/\/ \"Constraints go down, sizes go up, parent sets position\"\n\nclass CustomWidget extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      width: 200,  \/\/ \ubd80\ubaa8\uc5d0\uac8c \uc6d0\ud558\ub294 \ud06c\uae30 \uc804\ub2ec\n      height: 100,\n      child: Text('Hello'), \/\/ \uc790\uc2dd\uc740 \ubd80\ubaa8 \uc81c\uc57d\uc870\uac74 \ub0b4\uc5d0\uc11c \ud06c\uae30 \uacb0\uc815\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>\uc81c\uc57d\uc870\uac74\uc758 \uc885\ub958:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Tight Constraints<\/strong>: \uc815\ud655\ud55c \ud06c\uae30 \uc9c0\uc815 (width: 100, height: 50)<\/li>\n\n\n\n<li><strong>Loose Constraints<\/strong>: \ucd5c\ub300 \ud06c\uae30\ub9cc \uc9c0\uc815 (maxWidth: 100)<\/li>\n\n\n\n<li><strong>Unbounded Constraints<\/strong>: \ud06c\uae30 \uc81c\ud55c \uc5c6\uc74c (\ubb34\ud55c \uc2a4\ud06c\ub864 \ub4f1)<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Paint Phase (\ud398\uc778\ud2b8 \ub2e8\uacc4)<\/h4>\n\n\n\n<p>\uc2e4\uc81c\ub85c \ud654\uba74\uc5d0 \uadf8\ub9b4 \uba85\ub839\uc5b4\ub4e4\uc744 \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ CustomPainter\ub97c \uc0ac\uc6a9\ud55c \uc9c1\uc811 \ud398\uc778\ud305\nclass CirclePainter extends CustomPainter {\n  @override\n  void paint(Canvas canvas, Size size) {\n    final paint = Paint()\n      ..color = Colors.blue\n      ..style = PaintingStyle.fill;\n\n    canvas.drawCircle(\n      Offset(size.width \/ 2, size.height \/ 2),\n      50,\n      paint,\n    );\n  }\n\n  @override\n  bool shouldRepaint(CustomPainter oldDelegate) =&gt; false;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. GPU Thread\uc5d0\uc11c \uc77c\uc5b4\ub098\ub294 \uc77c\ub4e4<\/h3>\n\n\n\n<p>UI Thread\uc5d0\uc11c \uc0dd\uc131\ub41c Layer Tree\ub97c \ubc1b\uc544 \uc2e4\uc81c \ud53d\uc140\ub85c \ubcc0\ud658:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Rasterization<\/strong>: \ubca1\ud130 \uadf8\ub798\ud53d\uc744 \ube44\ud2b8\ub9f5\uc73c\ub85c \ubcc0\ud658<\/li>\n\n\n\n<li><strong>Composition<\/strong>: \uc5ec\ub7ec \ub808\uc774\uc5b4\ub97c \ud569\uc131<\/li>\n\n\n\n<li><strong>Display<\/strong>: \ud654\uba74\uc5d0 \ucd5c\uc885 \ucd9c\ub825<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Widget Tree vs Element Tree vs Render Tree<\/h2>\n\n\n\n<p>Flutter\ub97c \uc81c\ub300\ub85c \uc774\ud574\ud558\ub824\uba74 \uc138 \uac00\uc9c0 \ud2b8\ub9ac\uc758 \ucc28\uc774\uc810\uc744 \uc54c\uc544\uc57c \ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Widget Tree (\uc704\uc82f \ud2b8\ub9ac)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \uc704\uc82f\uc740 \ubd88\ubcc0(immutable) \uac1d\uccb4\nclass MyWidget extends StatelessWidget {\n  final String title;\n\n  const MyWidget({required this.title, Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return Text(title); \/\/ \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 Text \uc704\uc82f \ubc18\ud658\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>\ud2b9\uc9d5:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ubd88\ubcc0 \uac1d\uccb4 (\ub9e4\ubc88 \uc0c8\ub85c \uc0dd\uc131)<\/li>\n\n\n\n<li>\uc124\uc815\uac12\ub9cc \ubcf4\uad00 (\ub370\uc774\ud130)<\/li>\n\n\n\n<li>\ube60\ub978 \uc0dd\uc131\uacfc \ud3d0\uae30<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Element Tree (\uc5d8\ub9ac\uba3c\ud2b8 \ud2b8\ub9ac)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Element\ub294 \uc704\uc82f\uc758 \uc778\uc2a4\ud134\uc2a4\ub97c \uad00\ub9ac\nabstract class Element {\n  Widget get widget; \/\/ \ud604\uc7ac \uc704\uc82f\n  RenderObject? get renderObject; \/\/ \ub80c\ub354 \uac1d\uccb4 \ucc38\uc870\n\n  void update(Widget newWidget) {\n    \/\/ \uc704\uc82f\uc774 \ubc14\ub00c\uc5b4\ub3c4 Element\ub294 \uc7ac\uc0ac\uc6a9\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>\ud2b9\uc9d5:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc704\uc82f\uacfc \ub80c\ub354 \uac1d\uccb4 \uc0ac\uc774\uc758 \uc911\uc7ac\uc790<\/li>\n\n\n\n<li>\uc0dd\uba85\uc8fc\uae30 \uad00\ub9ac (mount, unmount)<\/li>\n\n\n\n<li>BuildContext\uc758 \uc2e4\uccb4<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Render Tree (\ub80c\ub354 \ud2b8\ub9ac)<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ RenderObject\ub294 \uc2e4\uc81c \ub808\uc774\uc544\uc6c3\uacfc \ud398\uc778\ud305 \ub2f4\ub2f9\nclass RenderFlex extends RenderBox {\n  @override\n  void performLayout() {\n    \/\/ \uc790\uc2dd\ub4e4\uc758 \ud06c\uae30\uc640 \uc704\uce58 \uacc4\uc0b0\n  }\n\n  @override\n  void paint(PaintingContext context, Offset offset) {\n    \/\/ \uc2e4\uc81c \uadf8\ub9ac\uae30 \uba85\ub839 \uc218\ud589\n  }\n}<\/code><\/pre>\n\n\n\n<p><strong>\ud2b9\uc9d5:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\uc2e4\uc81c \ub808\uc774\uc544\uc6c3\uacfc \ud398\uc778\ud305 \uc218\ud589<\/li>\n\n\n\n<li>\uc131\ub2a5 \ucd5c\uc801\ud654\uc758 \ud575\uc2ec<\/li>\n\n\n\n<li>\uac00\uc7a5 \ubb34\uac70\uc6b4 \uac1d\uccb4<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\uc131\ub2a5 \ucd5c\uc801\ud654 \uc804\ub7b5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. const \uc704\uc82f \ud65c\uc6a9<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u274c \ub9e4\ubc88 \uc0c8\ub85c\uc6b4 \uc704\uc82f \uc0dd\uc131\nclass BadExample extends StatefulWidget {\n  @override\n  _BadExampleState createState() =&gt; _BadExampleState();\n}\n\nclass _BadExampleState extends State&lt;BadExample&gt; {\n  int counter = 0;\n\n  @override\n  Widget build(BuildContext context) {\n    return Column(\n      children: &#91;\n        Text('Counter: $counter'),\n        ExpensiveWidget(), \/\/ \ub9e4\ubc88 \uc7ac\uc0dd\uc131!\n      ],\n    );\n  }\n}\n\n\/\/ \u2705 const \uc704\uc82f\uc73c\ub85c \ucd5c\uc801\ud654\nclass GoodExample extends StatefulWidget {\n  @override\n  _GoodExampleState createState() =&gt; _GoodExampleState();\n}\n\nclass _GoodExampleState extends State&lt;GoodExample&gt; {\n  int counter = 0;\n\n  @override\n  Widget build(BuildContext context) {\n    return Column(\n      children: &#91;\n        Text('Counter: $counter'),\n        const ExpensiveWidget(), \/\/ \ud55c \ubc88\ub9cc \uc0dd\uc131!\n      ],\n    );\n  }\n}\n\nclass ExpensiveWidget extends StatelessWidget {\n  const ExpensiveWidget({Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    \/\/ \ubcf5\uc7a1\ud55c \uc704\uc82f \ud2b8\ub9ac\n    return Container(\/* ... *\/);\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. RepaintBoundary \ud65c\uc6a9<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud2b9\uc815 \uc601\uc5ed\uc758 \ub9ac\ud398\uc778\ud2b8\ub97c \uaca9\ub9ac\nclass OptimizedListItem extends StatelessWidget {\n  final String title;\n  final bool isSelected;\n\n  const OptimizedListItem({\n    required this.title,\n    required this.isSelected,\n    Key? key,\n  }) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return RepaintBoundary( \/\/ \ub9ac\ud398\uc778\ud2b8 \uacbd\uacc4 \uc124\uc815\n      child: Container(\n        color: isSelected ? Colors.blue : Colors.white,\n        child: Row(\n          children: &#91;\n            Text(title),\n            RepaintBoundary( \/\/ \uc560\ub2c8\uba54\uc774\uc158 \uc601\uc5ed \ubd84\ub9ac\n              child: AnimatedContainer(\n                duration: Duration(milliseconds: 300),\n                width: isSelected ? 20 : 0,\n                height: 20,\n                color: Colors.green,\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. ListView.builder\ub97c \uc0ac\uc6a9\ud55c \ud6a8\uc728\uc801\uc778 \uc2a4\ud06c\ub864<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u274c \ubaa8\ub4e0 \uc544\uc774\ud15c\uc744 \ud55c \ubc88\uc5d0 \uc0dd\uc131\nclass BadListView extends StatelessWidget {\n  final List&lt;String&gt; items;\n\n  const BadListView({required this.items, Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return ListView(\n      children: items.map((item) =&gt; ListTile(title: Text(item))).toList(),\n    ); \/\/ \ubaa8\ub4e0 \uc544\uc774\ud15c\uc774 \uba54\ubaa8\ub9ac\uc5d0 \ub85c\ub4dc\ub428\n  }\n}\n\n\/\/ \u2705 \ud544\uc694\ud55c \uc544\uc774\ud15c\ub9cc \ub3d9\uc801 \uc0dd\uc131\nclass GoodListView extends StatelessWidget {\n  final List&lt;String&gt; items;\n\n  const GoodListView({required this.items, Key? key}) : super(key: key);\n\n  @override\n  Widget build(BuildContext context) {\n    return ListView.builder(\n      itemCount: items.length,\n      itemBuilder: (context, index) {\n        return ListTile(title: Text(items&#91;index]));\n      }, \/\/ \ud654\uba74\uc5d0 \ubcf4\uc774\ub294 \uc544\uc774\ud15c\ub9cc \uc0dd\uc131\n    );\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. \ucee4\uc2a4\ud140 RenderObject\ub85c \uadf9\ud55c \ucd5c\uc801\ud654<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \ud2b9\ubcc4\ud55c \uc694\uad6c\uc0ac\ud56d\uc774 \uc788\uc744 \ub54c \uc9c1\uc811 RenderObject \uad6c\ud604\nclass CustomProgressBar extends LeafRenderObjectWidget {\n  final double progress;\n  final Color color;\n\n  const CustomProgressBar({\n    required this.progress,\n    required this.color,\n    Key? key,\n  }) : super(key: key);\n\n  @override\n  RenderObject createRenderObject(BuildContext context) {\n    return RenderCustomProgressBar(\n      progress: progress,\n      color: color,\n    );\n  }\n\n  @override\n  void updateRenderObject(\n    BuildContext context,\n    RenderCustomProgressBar renderObject,\n  ) {\n    renderObject\n      ..progress = progress\n      ..color = color;\n  }\n}\n\nclass RenderCustomProgressBar extends RenderBox {\n  double _progress;\n  Color _color;\n\n  RenderCustomProgressBar({\n    required double progress,\n    required Color color,\n  }) : _progress = progress, _color = color;\n\n  double get progress =&gt; _progress;\n  set progress(double value) {\n    if (_progress != value) {\n      _progress = value;\n      markNeedsPaint(); \/\/ \ub9ac\ud398\uc778\ud2b8\ub9cc \ud544\uc694\n    }\n  }\n\n  Color get color =&gt; _color;\n  set color(Color value) {\n    if (_color != value) {\n      _color = value;\n      markNeedsPaint();\n    }\n  }\n\n  @override\n  void performLayout() {\n    size = constraints.biggest; \/\/ \ucd5c\ub300 \ud06c\uae30 \uc0ac\uc6a9\n  }\n\n  @override\n  void paint(PaintingContext context, Offset offset) {\n    final canvas = context.canvas;\n    final rect = offset &amp; size;\n\n    \/\/ \ubc30\uacbd \uadf8\ub9ac\uae30\n    canvas.drawRect(rect, Paint()..color = Colors.grey&#91;300]!);\n\n    \/\/ \uc9c4\ud589\ub960 \ubc14 \uadf8\ub9ac\uae30\n    final progressRect = Rect.fromLTWH(\n      offset.dx,\n      offset.dy,\n      size.width * _progress,\n      size.height,\n    );\n    canvas.drawRect(progressRect, Paint()..color = _color);\n  }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ub514\ubc84\uae45\uacfc \ud504\ub85c\ud30c\uc77c\ub9c1<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Flutter Inspector \ud65c\uc6a9<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># Flutter Inspector \uc2e4\ud589\nflutter run\n# \uadf8 \ud6c4 IDE\uc5d0\uc11c Flutter Inspector \ud0ed \ud655\uc778<\/code><\/pre>\n\n\n\n<p><strong>\uc8fc\uc694 \uae30\ub2a5:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Widget Tree \uc2dc\uac01\ud654<\/li>\n\n\n\n<li>\uc120\ud0dd\ub41c \uc704\uc82f\uc758 \uc18d\uc131 \ud655\uc778<\/li>\n\n\n\n<li>Layout \ubb38\uc81c \ub514\ubc84\uae45<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Overlay<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>class MyApp extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      \/\/ \uc131\ub2a5 \uc624\ubc84\ub808\uc774 \ud65c\uc131\ud654\n      showPerformanceOverlay: true, \/\/ \uac1c\ubc1c \uc911\uc5d0\ub9cc \uc0ac\uc6a9\n      home: HomePage(),\n    );\n  }\n}\n\n\/\/ \ub610\ub294 \ucf54\ub4dc\ub85c \ud1a0\uae00\nclass PerformanceToggle {\n  static void toggle() {\n    WidgetsApp.debugShowWidgetInspectorOverride = \n        !WidgetsApp.debugShowWidgetInspectorOverride;\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Timeline \ubd84\uc11d<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code># \ud0c0\uc784\ub77c\uc778 \ucd94\uc801 \uc2dc\uc791\nflutter run --trace-startup\n\n# DevTools\ub85c \ubd84\uc11d\nflutter pub global activate devtools\nflutter pub global run devtools<\/code><\/pre>\n\n\n\n<p><strong>\ubd84\uc11d \ud3ec\uc778\ud2b8:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Frame rendering time (16.67ms \uc774\ud558 \uc720\uc9c0)<\/li>\n\n\n\n<li>GPU utilization<\/li>\n\n\n\n<li>Memory usage patterns<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\uc2e4\uc804 \ucd5c\uc801\ud654 \uccb4\ud06c\ub9ac\uc2a4\ud2b8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\ube4c\ub4dc \ub2e8\uacc4 \ucd5c\uc801\ud654<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] <code>const<\/code> \uc0dd\uc131\uc790\ub97c \ucd5c\ub300\ud55c \ud65c\uc6a9\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] <code>StatelessWidget<\/code>\uc744 \uc6b0\uc120\uc801\uc73c\ub85c \uc0ac\uc6a9\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \ubd88\ud544\uc694\ud55c <code>build()<\/code> \ud638\ucd9c\uc744 \uc904\uc600\ub294\uac00?<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ub808\uc774\uc544\uc6c3 \ucd5c\uc801\ud654<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] <code>ListView.builder<\/code> vs <code>ListView<\/code> \uc801\uc808\ud788 \uc120\ud0dd\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \ubcf5\uc7a1\ud55c \uc911\ucca9 \ub808\uc774\uc544\uc6c3\uc744 \ud53c\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] <code>Flex<\/code>\uc640 <code>Expanded<\/code>\ub97c \uc62c\ubc14\ub974\uac8c \uc0ac\uc6a9\ud588\ub294\uac00?<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud398\uc778\ud305 \ucd5c\uc801\ud654<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] <code>RepaintBoundary<\/code>\ub85c \ub9ac\ud398\uc778\ud2b8 \uc601\uc5ed\uc744 \ubd84\ub9ac\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \ubd88\ud544\uc694\ud55c <code>Opacity<\/code> \uc704\uc82f\uc744 \ud53c\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \ubcf5\uc7a1\ud55c \uadf8\ub77c\ub370\uc774\uc158\uc774\ub098 \uadf8\ub9bc\uc790\ub97c \uacfc\ub3c4\ud558\uac8c \uc0ac\uc6a9\ud558\uc9c0 \uc54a\uc558\ub294\uac00?<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\uba54\ubaa8\ub9ac \ucd5c\uc801\ud654<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[ ] \uc774\ubbf8\uc9c0 \uce90\uc2f1\uc744 \uc801\uc808\ud788 \uad6c\ud604\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \ub9ac\uc18c\uc2a4\ub97c \ud574\uc81c\ud588\ub294\uac00?<\/li>\n\n\n\n<li>[ ] \ub300\uc6a9\ub7c9 \ub9ac\uc2a4\ud2b8\uc5d0 \uc801\uc808\ud55c \uac00\uc0c1\ud654\ub97c \uc801\uc6a9\ud588\ub294\uac00?<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\uace0\uae09 \ub80c\ub354\ub9c1 \ud14c\ud06c\ub2c9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. \ucee4\uc2a4\ud140 RenderObject\ub85c \ud2b9\ubcc4\ud55c \ub808\uc774\uc544\uc6c3 \uad6c\ud604<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \uc6d0\ud615\uc73c\ub85c \uc790\uc2dd\ub4e4\uc744 \ubc30\uce58\ud558\ub294 \ucee4\uc2a4\ud140 \ub808\uc774\uc544\uc6c3\nclass CircularLayout extends MultiChildRenderObjectWidget {\n  CircularLayout({\n    Key? key,\n    required List&lt;Widget&gt; children,\n  }) : super(key: key, children: children);\n\n  @override\n  RenderObject createRenderObject(BuildContext context) {\n    return RenderCircularLayout();\n  }\n}\n\nclass RenderCircularLayout extends RenderBox\n    with ContainerRenderObjectMixin&lt;RenderBox, MultiChildLayoutParentData&gt;,\n         RenderBoxContainerDefaultsMixin&lt;RenderBox, MultiChildLayoutParentData&gt; {\n\n  @override\n  void setupParentData(RenderBox child) {\n    if (child.parentData is! MultiChildLayoutParentData) {\n      child.parentData = MultiChildLayoutParentData();\n    }\n  }\n\n  @override\n  void performLayout() {\n    size = constraints.biggest;\n\n    if (childCount == 0) return;\n\n    final center = Offset(size.width \/ 2, size.height \/ 2);\n    final radius = math.min(size.width, size.height) \/ 3;\n    final angleStep = 2 * math.pi \/ childCount;\n\n    RenderBox? child = firstChild;\n    int index = 0;\n\n    while (child != null) {\n      child.layout(BoxConstraints.loose(size));\n\n      final angle = angleStep * index;\n      final childPosition = Offset(\n        center.dx + radius * math.cos(angle) - child.size.width \/ 2,\n        center.dy + radius * math.sin(angle) - child.size.height \/ 2,\n      );\n\n      (child.parentData as MultiChildLayoutParentData).offset = childPosition;\n\n      child = childAfter(child);\n      index++;\n    }\n  }\n\n  @override\n  void paint(PaintingContext context, Offset offset) {\n    defaultPaint(context, offset);\n  }\n\n  @override\n  bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {\n    return defaultHitTestChildren(result, position: position);\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. \ud6a8\uc728\uc801\uc778 \uc560\ub2c8\uba54\uc774\uc158 \uad6c\ud604<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ GPU\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 Transform \uc560\ub2c8\uba54\uc774\uc158\nclass OptimizedAnimation extends StatefulWidget {\n  @override\n  _OptimizedAnimationState createState() =&gt; _OptimizedAnimationState();\n}\n\nclass _OptimizedAnimationState extends State&lt;OptimizedAnimation&gt;\n    with TickerProviderStateMixin {\n  late AnimationController _controller;\n  late Animation&lt;double&gt; _animation;\n\n  @override\n  void initState() {\n    super.initState();\n    _controller = AnimationController(\n      duration: Duration(seconds: 2),\n      vsync: this,\n    );\n\n    _animation = Tween&lt;double&gt;(\n      begin: 0.0,\n      end: 1.0,\n    ).animate(CurvedAnimation(\n      parent: _controller,\n      curve: Curves.easeInOut,\n    ));\n\n    _controller.repeat(reverse: true);\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return AnimatedBuilder(\n      animation: _animation,\n      builder: (context, child) {\n        return Transform.rotate( \/\/ GPU\uc5d0\uc11c \ucc98\ub9ac\n          angle: _animation.value * 2 * math.pi,\n          child: Transform.scale( \/\/ GPU\uc5d0\uc11c \ucc98\ub9ac\n            scale: 0.5 + _animation.value * 0.5,\n            child: child,\n          ),\n        );\n      },\n      child: Container( \/\/ child\ub294 \ud55c \ubc88\ub9cc \ube4c\ub4dc\ub428\n        width: 100,\n        height: 100,\n        color: Colors.blue,\n        child: Center(child: Text('Animated')),\n      ),\n    );\n  }\n\n  @override\n  void dispose() {\n    _controller.dispose();\n    super.dispose();\n  }\n}<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ub9c8\ubb34\ub9ac: \uc131\ub2a5 \uc88b\uc740 Flutter \uc571\uc744 \uc704\ud55c \ud575\uc2ec \uc6d0\uce59<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. \ub80c\ub354\ub9c1 \ud30c\uc774\ud504\ub77c\uc778\uc744 \uc774\ud574\ud558\ub77c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Build<\/strong>: \uc704\uc82f \ud2b8\ub9ac \uad6c\uc131 \ucd5c\uc801\ud654<\/li>\n\n\n\n<li><strong>Layout<\/strong>: \uc81c\uc57d\uc870\uac74 \uc2dc\uc2a4\ud15c \ud65c\uc6a9<\/li>\n\n\n\n<li><strong>Paint<\/strong>: \ubd88\ud544\uc694\ud55c \ub9ac\ud398\uc778\ud2b8 \ubc29\uc9c0<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. \uba54\ubaa8\ub9ac \ud6a8\uc728\uc744 \uace0\ub824\ud558\ub77c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>const<\/code> \uc704\uc82f \uc801\uadf9 \ud65c\uc6a9<\/li>\n\n\n\n<li><code>ListView.builder<\/code>\ub85c lazy loading<\/li>\n\n\n\n<li>\uc774\ubbf8\uc9c0\uc640 \ub9ac\uc18c\uc2a4 \uad00\ub9ac<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. GPU \uce5c\ud654\uc801\uc778 \ucf54\ub4dc\ub97c \uc791\uc131\ud558\ub77c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Transform<\/code> \uc704\uc82f \ud65c\uc6a9<\/li>\n\n\n\n<li><code>Opacity<\/code> \ub300\uc2e0 \ub2e4\ub978 \ubc29\ubc95 \uace0\ub824<\/li>\n\n\n\n<li>\ubcf5\uc7a1\ud55c <code>ClipPath<\/code> \uc0ac\uc6a9 \uc790\uc81c<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. \uc9c0\uc18d\uc801\uc778 \ubaa8\ub2c8\ud130\ub9c1<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Flutter DevTools \ud65c\uc6a9<\/li>\n\n\n\n<li>Performance Overlay \ud655\uc778<\/li>\n\n\n\n<li>\uc2e4\uc81c \uae30\uae30\uc5d0\uc11c \ud14c\uc2a4\ud2b8<\/li>\n<\/ul>\n\n\n\n<p><strong>\uae30\uc5b5\ud558\uc138\uc694<\/strong>: \uc131\ub2a5 \ucd5c\uc801\ud654\ub294 \uce21\uc815 \uac00\ub2a5\ud55c \ubb38\uc81c\uac00 \uc788\uc744 \ub54c\ub9cc \uc218\ud589\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4. \ubbf8\ub9ac \ucd5c\uc801\ud654\ud558\ub824\uace0 \ud558\uc9c0 \ub9d0\uace0, \uc2e4\uc81c \uc131\ub2a5 \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud588\uc744 \ub54c \uccb4\uacc4\uc801\uc73c\ub85c \uc811\uadfc\ud558\uc138\uc694.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">\ucd94\uac00 \ud559\uc2b5 \uc790\ub8cc<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">\uacf5\uc2dd \ubb38\uc11c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.flutter.dev\/perf\/best-practices\">Flutter Performance Best Practices<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.flutter.dev\/resources\/architectural-overview#flutter-rendering-pipeline\">Flutter Rendering Pipeline<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ub514\ubc84\uae45 \ub3c4\uad6c<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.flutter.dev\/development\/tools\/flutter-inspector\">Flutter Inspector<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.flutter.dev\/development\/tools\/devtools\/performance\">DevTools Performance View<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\uc2ec\ud654 \ud559\uc2b5<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.flutter.dev\/development\/ui\/advanced\/custom-render-objects\">Custom RenderObject<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/flutter\/flutter\/wiki\/The-Engine-architecture\">Flutter Engine Architecture<\/a><\/li>\n<\/ul>\n\n\n\n<p>Flutter\uc758 \ub80c\ub354\ub9c1 \uc2dc\uc2a4\ud15c\uc744 \uae4a\uc774 \uc774\ud574\ud558\uace0 \ub098\uba74, \ub2e8\uc21c\ud788 \uc704\uc82f\uc744 \ubc30\uce58\ud558\ub294 \uac83\uc744 \ub118\uc5b4\uc11c \uc9c4\uc815\ud55c \uc131\ub2a5 \ucd5c\uc801\ud654\uc640 \uc0ac\uc6a9\uc790 \uacbd\ud5d8 \uac1c\uc120\uc774 \uac00\ub2a5\ud574\uc9d1\ub2c8\ub2e4. \uc9c0\uae08 \ub2f9\uc7a5 \uc5ec\ub7ec\ubd84\uc758 \ud504\ub85c\uc81d\ud2b8\uc5d0 \uc801\uc6a9\ud574 \ubcf4\uc138\uc694!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Flutter \ub80c\ub354\ub9c1 \uc2dc\uc2a4\ud15c \uc644\uc804 \uc815\ubcf5: \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc790\ub97c \uc704\ud55c \uc2ec\ud654 \uac00\uc774\ub4dc \uc548\ub4dc\ub85c\uc774\ub4dc\/iOS \uac1c\ubc1c \uacbd\ud5d8\uc774 \uc788\ub294 \uac1c\ubc1c\uc790\ub77c\uba74 \ubc18\ub4dc\uc2dc \uc54c\uc544\uc57c \ud560 Flutter\uc758 \ub80c\ub354\ub9c1 \uba54\ucee4\ub2c8\uc998\uacfc \uc131\ub2a5 \ucd5c\uc801\ud654 \uc804\ub7b5 \ub4e4\uc5b4\uac00\uba70: \uc65c Flutter\uc758 \ub80c\ub354\ub9c1 \uc2dc\uc2a4\ud15c\uc744 \uc54c\uc544\uc57c \ud560\uae4c? \uc548\ub4dc\ub85c\uc774\ub4dc\ub098 iOS \ub124\uc774\ud2f0\ube0c \uac1c\ubc1c\uc744 \ud574\ubcf4\uc2e0 \ubd84\uc774\ub77c\uba74, \uac01 \ud50c\ub7ab\ud3fc\uc758 UI \ub80c\ub354\ub9c1 \ubc29\uc2dd\uc5d0 \uc775\uc219\ud558\uc2e4 \uac83\uc785\ub2c8\ub2e4. \uc548\ub4dc\ub85c\uc774\ub4dc\uc758 View \uc2dc\uc2a4\ud15c, iOS\uc758 UIKit&#8230; \ud558\uc9c0\ub9cc Flutter\ub294 \uc644\uc804\ud788 \ub2e4\ub978 \uc811\uadfc \ubc29\uc2dd\uc744 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[43],"tags":[114,110,78,113,111,79,112,106],"class_list":["post-86","post","type-post","status-publish","format-standard","hentry","category-flutter","tag-android","tag-dart","tag-flutter","tag-ios","tag-111","tag-79","tag-112","tag-106"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/86","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=86"}],"version-history":[{"count":2,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/86\/revisions"}],"predecessor-version":[{"id":109,"href":"https:\/\/hed-g.me\/index.php?rest_route=\/wp\/v2\/posts\/86\/revisions\/109"}],"wp:attachment":[{"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=86"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=86"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hed-g.me\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=86"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}