2026๋…„ Flutter ์„ฑ๋Šฅ ์ตœ์ ํ™”: Impeller, ๋ฆฌ๋นŒ๋“œ, ๋ชจ๋ฒ” ์‚ฌ๋ก€

2026๋…„์— Flutter ์•ฑ์„ 60 ๋˜๋Š” 120fps๋กœ ์•ˆ์ •์ ์œผ๋กœ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•. Impeller, ์ ˆ์ œ๋œ ์œ„์ ฏ ๋ฆฌ๋นŒ๋“œ, RepaintBoundary, DevTools ํ”„๋กœํŒŒ์ผ๋ง์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

Impeller์™€ ์ค„์–ด๋“  ์œ„์ ฏ ๋ฆฌ๋นŒ๋“œ๋ฅผ ํ™œ์šฉํ•œ Flutter ์„ฑ๋Šฅ ์ตœ์ ํ™”

2026๋…„ Flutter ์„ฑ๋Šฅ ์ตœ์ ํ™”๋Š” ๋ถ€๋“œ๋Ÿฌ์šด ์•ฑ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์„ ๋ฐ”๊พผ ๋‘ ๊ฐ€์ง€ ์ „ํ™˜์— ๊ธฐ๋Œ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ Œ๋”๋ง ์—”์ง„ Impeller๊ฐ€ iOS์™€ Android์—์„œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ œ๊ณต๋˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค๋Š” ์ , ๊ทธ๋ฆฌ๊ณ  ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ฆฌ๋นŒ๋“œ ๋ชจ๋ธ์ด ์œ„์ ฏ ํŠธ๋ฆฌ๋ฅผ ์ž‘๊ณ  ๋ถˆ๋ณ€์œผ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ณด์ƒ์„ ์ค€๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ์ง€๋ ›๋Œ€์— ๊ธฐ๋Œ€๋Š” ํŒ€์€ ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์†์œผ๋กœ ์กฐ์ •ํ•˜์ง€ ์•Š๊ณ ๋„ 60 ๋˜๋Š” 120fps๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์˜ํ–ฅ์ด ํฐ ๋ณ€ํ™”

๋Œ€๋ถ€๋ถ„์˜ Flutter ์•ฑ์—์„œ ๊ฐ€์žฅ ํฐ ์ด๋“์€ const ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํฐ build ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ„ํ• ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด setState ํ˜ธ์ถœ์ด ํ™”๋ฉด ์ „์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋ฒ„ํŠผ ํ•˜๋‚˜๋งŒ ๋‹ค์‹œ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

Impeller๊ฐ€ Flutter ์„ฑ๋Šฅ์˜ ๊ธฐ์ค€์„ ์„ ๋‹ค์‹œ ์„ธ์šฐ๋Š” ์ด์œ 

Impeller๋Š” Flutter์˜ ๋ Œ๋”๋ง ์—”์ง„์ด๋ฉฐ, ๋ชจ๋ฐ”์ผ ํ”Œ๋žซํผ ์ „๋ฐ˜์—์„œ Skia๋ฅผ ๋Œ€์‹ ํ•ด ๊ธฐ๋ณธ๊ฐ’์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ฐจ์ด๊ฐ€ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋“œ๋Ÿฌ๋‚˜๋Š” ๊ณณ์€ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์ฒ˜์Œ ๋ช‡ ์ดˆ์ž…๋‹ˆ๋‹ค. Skia๋Š” ์…ฐ์ด๋”๋ฅผ ์ €์ŠคํŠธ ์ธ ํƒ€์ž„์œผ๋กœ, ํŠน์ • ํšจ๊ณผ๊ฐ€ ํ™”๋ฉด์— ์ฒ˜์Œ ๋‚˜ํƒ€๋‚  ๋•Œ ์ปดํŒŒ์ผํ–ˆ๊ณ , ์ด๊ฒƒ์ด Flutter ์•ฑ์ด ๋น„ํŒ๋ฐ›๋˜ ๊ทธ ์•…๋ช… ๋†’์€ ์ฒซ ์‹คํ–‰ ๋Š๊น€์„ ๋งŒ๋“ค์–ด ๋ƒˆ์Šต๋‹ˆ๋‹ค. Impeller๋Š” ๊ทธ ์…ฐ์ด๋”๋“ค์„ ๋นŒ๋“œ ์‹œ์ ์— ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผํ•˜๋ฏ€๋กœ, ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๋งจ ์ฒซ ํ”„๋ ˆ์ž„์ด 100๋ฒˆ์งธ ํ”„๋ ˆ์ž„๋งŒํผ ๋ถ€๋“œ๋Ÿฝ์Šต๋‹ˆ๋‹ค.

Impeller๋Š” ๋˜ํ•œ ์ตœ์‹  ๊ทธ๋ž˜ํ”ฝ API๋ฅผ ์ง์ ‘ ๊ฒจ๋ƒฅํ•ฉ๋‹ˆ๋‹ค. iOS์—์„œ๋Š” Metal, Android์—์„œ๋Š” Vulkan์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋” ์˜ค๋ž˜๋œ Android ํ•˜๋“œ์›จ์–ด๋ฅผ ์œ„ํ•œ OpenGL ํด๋ฐฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. GitHub์˜ Impeller ์—”์ง„ ๋ฌธ์„œ๋Š” ๋ Œ๋”๋ง ์•„ํ‚คํ…์ฒ˜์™€ ํ”Œ๋žซํผ ์ง€์› ๋งคํŠธ๋ฆญ์Šค๋ฅผ ์ƒ์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

| ์ธก๋ฉด | Skia(๋ ˆ๊ฑฐ์‹œ) | Impeller(2026 ๊ธฐ๋ณธ๊ฐ’) | |--------|---------------|-------------------------| | ์…ฐ์ด๋” ์ปดํŒŒ์ผ | ๋Ÿฐํƒ€์ž„, ์ฒซ ์‹คํ–‰ ๋Š๊น€์„ ์œ ๋ฐœ | ์‚ฌ์ „, ๋นŒ๋“œ ์‹œ์  | | iOS ๋ฐฑ์—”๋“œ | OpenGL / Metal | Metal | | Android ๋ฐฑ์—”๋“œ | OpenGL | Vulkan, OpenGL ํด๋ฐฑ | | ์ฒซ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๋ถ€๋“œ๋Ÿฌ์›€ | ์ด๋”ฐ๊ธˆ ๋Š๊น€ | ์ผ๊ด€๋จ |

๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์€ ๊ณต์งœ์ž…๋‹ˆ๋‹ค. ์ตœ๊ทผ Flutter ๋ฆด๋ฆฌ์Šค๋Š” Impeller๋ฅผ ์ž๋™์œผ๋กœ ํ™œ์„ฑํ™”ํ•˜๊ณ , ์˜› ์…ฐ์ด๋” ์›Œ๋ฐ์—… ์šฐํšŒ์ฑ…(--purge-persistent-cache, ๋ฒˆ๋“ค๋œ .sksl ํŒŒ์ผ)์€ ๋” ์ด์ƒ ํ•„์š” ์—†์–ด ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Flutter๊ฐ€ ์ง€์›ํ•˜๋Š” GLSL ํ•˜์œ„ ์ง‘ํ•ฉ์— ๋งž์ถฐ ์ž‘์„ฑ๋œ ์‚ฌ์šฉ์ž ์ง€์ • FragmentProgram ์…ฐ์ด๋”๋„ ๊ทธ๋Œ€๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค. Impeller๊ฐ€ ์ด๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ ์ž์ฒด ํšจ๊ณผ์™€ ๋™์ผํ•œ ์˜คํ”„๋ผ์ธ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์ปดํŒŒ์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์•ฑ์ด ์–ด๋А ์—”์ง„์—์„œ ์‹คํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ๋Š” ํ•œ ์ค„์ด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋””๋ฒ„๊ทธ ๋นŒ๋“œ๋Š” ์‹œ์ž‘ ์‹œ ํ™œ์„ฑ ๋ฐฑ์—”๋“œ๋ฅผ ์ถœ๋ ฅํ•˜๊ณ , DevTools ์ธ์ŠคํŽ™ํ„ฐ๋Š” ์•ฑ์˜ ๋ Œ๋”๋ง ์„ธ๋ถ€ ์ •๋ณด์—์„œ ์ด๋ฅผ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค. Impeller๊ฐ€ ํ™•์ธ๋˜๋ฉด, ๋‚จ์€ ์„ฑ๋Šฅ ์ž‘์—…์€ ์œ„์ ฏ ๊ณ„์ธต์œผ๋กœ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค. ๊ทธ๊ณณ์—์„œ ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ํ™”๋ฉด์ด ์‹ค์ œ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ์ž์ฃผ ๋ฆฌ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ€์ด๋“œ์˜ ๋‚˜๋จธ์ง€๊ฐ€ ์ดˆ์ ์„ ๋งž์ถ”๋Š” ๊ณณ์ด ๋ฐ”๋กœ ๊ทธ๊ณณ์ž…๋‹ˆ๋‹ค. ๋น ๋ฅธ ์—”์ง„๋„ ์ดˆ๋‹น ์ˆ˜๋ฐฑ ๋ฒˆ ์Šค์Šค๋กœ๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋Š” ์œ„์ ฏ ํŠธ๋ฆฌ๋Š” ๊ตฌํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

const์™€ ์œ„์ ฏ ๋ถ„ํ• ๋กœ Flutter ๋ฆฌ๋นŒ๋“œ ์ค„์ด๊ธฐ

๋ชจ๋“  setState๋Š” ์ž์‹ ์˜ ์œ„์ ฏ์„ ์˜ค๋ž˜๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œํ•˜๊ณ  ๊ทธ ์š”์†Œ์™€ ํ•˜์œ„ ํŠธ๋ฆฌ์— ๋Œ€ํ•ด build๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์š”๋ น์€ ๊ทธ ํ•˜์œ„ ํŠธ๋ฆฌ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ์ข๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์Šต๊ด€์ด ์ž‘์—…์˜ ๋Œ€๋ถ€๋ถ„์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ •์  ์œ„์ ฏ์„ const๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  ์ƒํƒœ๋ฅผ ์•„๋ž˜๋กœ ๋ฐ€์–ด ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ๋ถ€๋ถ„์„ ์ž‘๊ฒŒ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

const ์œ„์ ฏ์€ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค๋กœ ์ •๊ทœํ™”๋˜๋ฏ€๋กœ, ๋ถ€๋ชจ๊ฐ€ ๋ฆฌ๋นŒ๋“œ๋  ๋•Œ Flutter๋Š” ๋™์ผํ•œ ์ฐธ์กฐ๋ฅผ ๋น„๊ตํ•˜๊ณ , ๋ณ€ํ™”๊ฐ€ ์—†๋‹ค๊ณ  ํŒ๋‹จํ•˜์—ฌ, ๊ทธ ๊ฐ€์ง€์˜ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ๋ฅผ ์™„์ „ํžˆ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.

product_screen.dartdart
// A cart update repaints the badge, not the header.

class ProductScreen extends StatefulWidget {
  const ProductScreen({super.key});

  
  State<ProductScreen> createState() => _ProductScreenState();
}

class _ProductScreenState extends State<ProductScreen> {
  int _cartCount = 0;

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        const ProductHeader(),         // const: never rebuilds on setState
        CartBadge(count: _cartCount),   // only this subtree rebuilds
        FilledButton(
          onPressed: () => setState(() => _cartCount++),
          child: const Text('Add to cart'),
        ),
      ],
    );
  }
}

analysis_options.yaml์—์„œ prefer_const_constructors ๋ฆฐํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋ฉด ์ด ๊ทœ์œจ์ด ์ปดํŒŒ์ผ๋Ÿฌ ๊ฒ€์‚ฌ๋กœ ๋ฐ”๋€Œ๋ฏ€๋กœ, const ๊ธฐํšŒ๊ฐ€ ์กฐ์šฉํžˆ ์‚ฌ๋ผ์ง€๋Š” ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ด€๋ จ ๊ทœ์น™ prefer_const_literals_to_create_immutables๋Š” ์œ„์ ฏ์— ์ „๋‹ฌ๋˜๋Š” ๋ฆฌ์ŠคํŠธ์™€ ๋งต์—๋„ ๊ฐ™์€ ๋ณด์žฅ์„ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

์œ„์ ฏ ํ‚ค๋„ ์—ฌ๊ธฐ์„œ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์ŠคํŠธ์˜ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ์œ„์ ฏ์˜ ํƒ€์ž…์€ ๊ฐ™์ง€๋งŒ ์ •์ฒด์„ฑ์ด ๋ฐ”๋€” ๋•Œ, ValueKey๋‚˜ ObjectKey๋Š” Flutter๊ฐ€ ์ƒํƒœ๋ฅผ ํ—๊ณ  ๋‹ค์‹œ ๋งŒ๋“œ๋Š” ๋Œ€์‹  ์ด์ „ ์š”์†Œ๋ฅผ ์˜ฌ๋ฐ”๋ฅธ ์ƒˆ ์œ„์ ฏ ์ธ์Šคํ„ด์Šค์— ๋งค์นญํ•˜๋„๋ก ํ•ด ์ค๋‹ˆ๋‹ค. ํ‚ค์˜ ๋ถ€์žฌ๋Š” ๋™์  ๋ฆฌ์ŠคํŠธ์—์„œ ์Šคํฌ๋กค ์œ„์น˜๊ฐ€ ์‚ฌ๋ผ์ง€๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ฆฌ์…‹๋˜๋Š” ํ”ํ•œ ์›์ธ์ด๋ฉฐ, ๊ทธ๋กœ ์ธํ•œ ์ถ”๊ฐ€ ๋ฆฌ๋นŒ๋“œ ์ž‘์—…์€ ๋†“์น˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋ฐ”๋€ ๋ฐ์ดํ„ฐ๋กœ ๋ฆฌ๋นŒ๋“œ ๋ฒ”์œ„ ์ขํžˆ๊ธฐ

์ƒํƒœ๊ฐ€ ํŠธ๋ฆฌ์˜ ๋†’์€ ๊ณณ์— ์žˆ์œผ๋ฉด, ์ž˜ ๋ถ„ํ• ๋œ ๋ ˆ์ด์•„์›ƒ์ด๋ผ๋„ ์—ฌ์ „ํžˆ ๋งŽ์ด ๋ฆฌ๋นŒ๋“œ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋ฒ•์€ ๊ฐ’์„ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธํ•˜๊ณ  ์œ„์ ฏ ํ•˜๋‚˜๋งŒ ๊ทธ๊ฒƒ์„ ๋“ฃ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Flutter๋Š” ๋ฐ”๋กœ ์ด๋ฅผ ์œ„ํ•ด ValueNotifier์™€ ValueListenableBuilder๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, ์™ธ๋ถ€ ํŒจํ‚ค์ง€๋Š” ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

article_list.dartdart
// A scroll-to-top button that rebuilds alone, not the whole page.

class ArticleList extends StatefulWidget {
  const ArticleList({super.key});

  
  State<ArticleList> createState() => _ArticleListState();
}

class _ArticleListState extends State<ArticleList> {
  final _showFab = ValueNotifier<bool>(false);
  final _controller = ScrollController();

  
  void initState() {
    super.initState();
    // Update the notifier, not setState: the list never rebuilds
    _controller.addListener(() => _showFab.value = _controller.offset > 400);
  }

  
  void dispose() {
    _showFab.dispose();
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        controller: _controller,
        itemCount: 200,
        itemBuilder: (_, i) => ListTile(title: Text('Item $i')),
      ),
      floatingActionButton: ValueListenableBuilder<bool>(
        valueListenable: _showFab,
        builder: (_, visible, __) => visible
            ? FloatingActionButton(
                onPressed: () => _controller.jumpTo(0),
                child: const Icon(Icons.arrow_upward),
              )
            : const SizedBox.shrink(),
      ),
    );
  }
}

์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๊ฐ™์€ ์•„์ด๋””์–ด๋ฅผ ์ผ๋ฐ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค. Riverpod์˜ ref.watch(provider.select(...))์™€ Provider์˜ Selector ์œ„์ ฏ์€ ๋ชจ๋‘ ์ƒํƒœ์˜ ์„ ํƒ๋œ ์กฐ๊ฐ์ด ๋ฐ”๋€” ๋•Œ๋งŒ ๋ฆฌ๋นŒ๋“œํ•˜๋ฉฐ, ์ด๊ฒƒ์ด ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์€ ํ™”๋ฉด์—์„œ ๋ถ€๋“œ๋Ÿฌ์›€๊ณผ ๋ฒ„๋ฒ…์ž„์„ ๊ฐ€๋ฅด๋Š” ๊ฒฐ์ •์  ์š”์ธ์ž…๋‹ˆ๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค ์‚ฌ์ด์˜ ์ ˆ์ถฉ์€ 2026๋…„ Flutter ์ƒํƒœ ๊ด€๋ฆฌ ๊ฐ€์ด๋“œ์—์„œ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

๋ฆฌ๋นŒ๋“œ ๋ฒ”์œ„์— ์ฃผ์˜

ํ™”๋ฉด์˜ ๋ฃจํŠธ ๊ทผ์ฒ˜์—์„œ setState๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ ์ตœ์ƒ์œ„ Consumer๋กœ ๊ฐ์‹ธ๋ฉด, ๋ณ€๊ฒฝ๋งˆ๋‹ค ์กฐ์šฉํžˆ ์ˆ˜๋ฐฑ ๊ฐœ์˜ ์œ„์ ฏ์ด ๋‹ค์‹œ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ์–ด๋–ค ํ™”๋ฉด์ด ์ €๋ ดํ•˜๋‹ค๊ณ  ๋‹จ์ •ํ•˜๊ธฐ ์ „์— DevTools์˜ ๋ฆฌ๋นŒ๋“œ ์นด์šดํ„ฐ๋กœ ํ”„๋กœํŒŒ์ผํ•˜์‹ญ์‹œ์˜ค.

Flutter ๋ฉด์ ‘ ์ค€๋น„๊ฐ€ ๋˜์…จ๋‚˜์š”?

์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ, flashcards, ๊ธฐ์ˆ  ํ…Œ์ŠคํŠธ๋กœ ์—ฐ์Šตํ•˜์„ธ์š”.

RepaintBoundary๋กœ ๋น„์‹ผ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ ๊ฒฉ๋ฆฌํ•˜๊ธฐ

๋ฆฌ๋นŒ๋“œ์™€ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ๋Š” ๋ณ„๊ฐœ์˜ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. ์œ„์ ฏ์€ ๋ฆฌ๋นŒ๋“œ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ ๋„, ์†Œ๋ž€์Šค๋Ÿฌ์šด ์ด์›ƒ์ด ๋ ˆ์ด์–ด๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์‹œ ๊ทธ๋ ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. RepaintBoundary๋Š” ํ•˜์œ„ ํŠธ๋ฆฌ์— ์ž์ฒด ๋ ˆ์ด์–ด๋ฅผ ๋ถ€์—ฌํ•˜๋ฏ€๋กœ, ์• ๋‹ˆ๋ฉ”์ด์…˜๋˜๋Š” ์ฐจํŠธ๊ฐ€ ์ •์  ์นด๋“œ์— ๋งค ํ”„๋ ˆ์ž„ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋„๋ก ๊ฐ•์š”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

dashboard.dartdart
// The live chart repaints on its own layer, cards stay untouched.

class Dashboard extends StatelessWidget {
  const Dashboard({required this.ticker, super.key});
  final Stream<double> ticker;

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        // SummaryCards is static, so isolate it from the animation below
        const RepaintBoundary(child: SummaryCards()),
        RepaintBoundary(
          child: StreamBuilder<double>(
            stream: ticker,
            builder: (_, snap) => LivePriceChart(value: snap.data ?? 0),
          ),
        ),
      ],
    );
  }
}

RepaintBoundary๋Š” ๊ณต์งœ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ฐ๊ฐ์ด ๋ ˆ์ด์–ด ํ•˜๋‚˜๋ฅผ ํ• ๋‹นํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์ €๊ธฐ ๋ฟŒ๋ฆฌ๋ฉด ๋„์›€๋ณด๋‹ค ํ•ด๊ฐ€ ํฝ๋‹ˆ๋‹ค. ์ •๋ง๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜๋˜๋Š” ์˜์—ญ๊ณผ ๊ธด ์Šคํฌ๋กค ๋ฆฌ์ŠคํŠธ ์ฃผ์œ„์— ์‚ฌ์šฉํ•˜๊ณ , ํƒ€์ž„๋ผ์ธ์—์„œ ์ด๋“์„ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. RepaintBoundary API ๋ ˆํผ๋Ÿฐ์Šค๋Š” ๋””๋ฒ„๊ทธ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ ์˜ค๋ฒ„๋ ˆ์ด๊ฐ€ ์‹ค์ œ๋กœ ๋‹ค์‹œ ๊ทธ๋ ค์ง€๋Š” ๋ ˆ์ด์–ด๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐ•์กฐํ•˜๋Š”์ง€ ๋ฌธ์„œํ™”ํ•ฉ๋‹ˆ๋‹ค.

build ๋ฉ”์„œ๋“œ๋ฅผ ์ €๋ ดํ•˜๊ณ  ๋ถ€์ž‘์šฉ ์—†์ด ์œ ์ง€ํ•˜๊ธฐ

build ๋ฉ”์„œ๋“œ๋Š” ๋ฆฌ๋นŒ๋“œ๋งˆ๋‹ค ์‹คํ–‰๋˜๋ฏ€๋กœ, ๊ทธ ์•ˆ์˜ ๋น„์‹ผ ๊ฒƒ์€ ๋ฌด์—‡์ด๋“  ๋ฐฐ๊ฐ€๋ฉ๋‹ˆ๋‹ค. ๊ทœ์น™์€ build๊ฐ€ ์ƒํƒœ๋ฅผ ์ฝ๊ณ  ์œ„์ ฏ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ, ๊ทธ ์ด์ƒ์€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. build ์•ˆ์—์„œ ScrollController, AnimationController, Future๋ฅผ ํ• ๋‹นํ•˜๋ฉด ๋งค ํ”„๋ ˆ์ž„ ๋‹ค์‹œ ์ƒ์„ฑ๋˜๊ณ  ์ด์ „ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ˆ„์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ์ฒด๋“ค์€ initState๋‚˜ dispose์—์„œ ํ•ด์ œ๋˜๋Š” late final ํ•„๋“œ์— ์†ํ•ฉ๋‹ˆ๋‹ค.

๋ฌด๊ฑฐ์šด ๋™๊ธฐ ์ž‘์—…์ด ๋‘ ๋ฒˆ์งธ ํ•จ์ •์ž…๋‹ˆ๋‹ค. build ์•ˆ์—์„œ JSON์„ ํŒŒ์‹ฑํ•˜๊ฑฐ๋‚˜, ํฐ ๋ฆฌ์ŠคํŠธ๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜, ๋‚ ์งœ๋ฅผ ํฌ๋งทํ•˜๋ฉด, ๊ธฐ์ € ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ”๋€Œ์ง€ ์•Š์•˜์–ด๋„ ๊ทธ ์ž‘์—…์ด ๋งค ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ธฐ๋งˆ๋‹ค ์žฌ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ž…๋ ฅ์ด ๋ฐ”๋€” ๋•Œ ๊ฒฐ๊ณผ๋ฅผ ํ•œ ๋ฒˆ๋งŒ ๊ณ„์‚ฐํ•ด ์บ์‹œํ•˜๊ฑฐ๋‚˜, ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ•œ ํ”„๋ ˆ์ž„์„ ๋ง‰๊ณ  ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋„๋ก FutureBuilder๋กœ ์˜ฎ๊ธฐ์‹ญ์‹œ์˜ค. ๋‹ค๋ฅธ ๊ฐ’์—์„œ ํŒŒ์ƒ๋˜๋Š” ๊ฐ’์€ ์˜์กด์„ฑ์ด ๋ฐ”๋€” ๋•Œ๋งŒ ์žฌ๊ณ„์‚ฐํ•˜๋Š” ๊ฒŒํ„ฐ ๋’ค์— ๋ฉ”๋ชจ์ด์ œ์ด์…˜ํ•˜์‹ญ์‹œ์˜ค.

Opacity ์œ„์ ฏ์€ ์ด๋ฆ„์„ ๋ฐํž ๋งŒํ•œ ๊ตฌ์ฒด์ ์ธ ์›ํ‰์ž…๋‹ˆ๋‹ค. ํ•˜์œ„ ํŠธ๋ฆฌ๋ฅผ Opacity๋กœ ๊ฐ์‹ธ๋ฉด ํ™”๋ฉด ๋ฐ– saveLayer๊ฐ€ ๊ฐ•์ œ๋˜๋Š”๋ฐ, ์ด๋Š” ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๊ฐ€์žฅ ๋น„์‹ผ ์—ฐ์‚ฐ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํŽ˜์ด๋“œ ์• ๋‹ˆ๋ฉ”์ด์…˜์—๋Š” AnimatedOpacity๋‚˜ FadeTransition์ด ๋” ์ €๋ ดํ•˜๊ณ , ๊ณ ์ •๋œ ์ƒ‰์กฐ์—๋Š” foregroundDecoration์ด๋‚˜ ์…ฐ์ด๋”๋ฅผ ํ†ตํ•ด ํŽ˜์ธํŠธ ์ˆ˜์ค€์—์„œ ์ƒ‰์„ ์ ์šฉํ•˜๋ฉด ๋ ˆ์ด์–ด๋ฅผ ์™„์ „ํžˆ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ™์€ ์ฃผ์˜๊ฐ€ ํฐ ํ‘œ๋ฉด์—์„œ ์•ˆํ‹ฐ์—์ผ๋ฆฌ์–ด์‹ฑ์„ ์ผ  ClipPath์™€ ClipRRect์—๋„ ์ ์šฉ๋˜๋ฉฐ, ์ด๋“ค ์—ญ์‹œ ๋’ค์—์„œ saveLayer๋ฅผ ์œ ๋ฐœํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ, const ์ปฌ๋ ‰์…˜๊ณผ ๋งค ๋นŒ๋“œ๋งˆ๋‹ค ์ƒˆ ํด๋กœ์ €๋ฅผ ํฌํšํ•˜์ง€ ์•Š๋Š” ์ฝœ๋ฐฑ์„ ์„ ํ˜ธํ•˜์‹ญ์‹œ์˜ค. ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ „๋‹ฌํ•œ const []์™€ ์ธ๋ผ์ธ ๋žŒ๋‹ค ๋Œ€์‹ ์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ๋ชจ๋‘ ์œ„์ ฏ ๋™๋“ฑ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ €๋ ดํ•˜๊ฒŒ ์œ ์ง€ํ•˜๋ฉฐ, ์ด๋Š” ์•ž์„œ ์„ค๋ช…ํ•œ const ๋‹จ๋ฝ(็Ÿญ็ตก)์ด ์‹ค์ œ๋กœ ๋ฐœ๋™ํ•˜๋„๋ก ํ•ด ์ค๋‹ˆ๋‹ค.

๊ธด ๋ฆฌ์ŠคํŠธ์™€ ์ด๋ฏธ์ง€๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ตฌ์„ฑํ•˜๊ธฐ

๊ธด ํ”ผ๋“œ์™€ ์ด๋ฏธ์ง€ ๊ทธ๋ฆฌ๋“œ๋Š” ์ˆœ์ง„ํ•œ Flutter ์ฝ”๋“œ๊ฐ€ ํ”„๋ ˆ์ž„์„ ๋–จ์–ด๋œจ๋ฆฌ๋Š” ์ง€์ ์ž…๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ๊ทœ์น™์ด ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ํ–‰์„ ์ง€์—ฐ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฏธ์ง€๋ฅผ ์†Œ์Šค ํ•ด์ƒ๋„๊ฐ€ ์•„๋‹ˆ๋ผ ํ‘œ์‹œ๋˜๋Š” ํฌ๊ธฐ๋กœ ๋””์ฝ”๋”ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

feed.dartdart
// Lazy rows plus right-sized image decoding keep scrolling at 60fps.

class Feed extends StatelessWidget {
  const Feed({required this.posts, super.key});
  final List<Post> posts;

  
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: posts.length,     // build on demand, not all at once
      cacheExtent: 600,            // pre-build past the viewport edge
      itemBuilder: (context, index) {
        final post = posts[index];
        return ListTile(
          leading: Image.network(
            post.thumbnailUrl,
            width: 48,
            height: 48,
            cacheWidth: 96,        // decode at display size, save memory
          ),
          title: Text(post.title),
        );
      },
    );
  }
}

3000ํ”ฝ์…€ ์ „์ฒด ํ•ด์ƒ๋„ ์ด๋ฏธ์ง€๋ฅผ 48ํ”ฝ์…€ ์•„๋ฐ”ํƒ€์— ์šฑ์—ฌ๋„ฃ์œผ๋ฉด, ๊ทธ ํ•˜๋‚˜ํ•˜๋‚˜๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ์™€ ๋””์ฝ”๋”ฉ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•ฉ๋‹ˆ๋‹ค. cacheWidth๋ฅผ ์„ค์ •ํ•˜๋ฉด ์—”์ง„์— ๋ชฉํ‘œ ํฌ๊ธฐ๋กœ ๋””์ฝ”๋”ฉํ•˜๋ผ๊ณ  ์ง€์‹œํ•˜๊ฒŒ ๋˜๋ฉฐ, ์ด๊ฒƒ๋งŒ์œผ๋กœ๋„ ๋ฆฌ์ŠคํŠธ์˜ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ํ•œ ์ž๋ฆฟ์ˆ˜ ๊ทœ๋ชจ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Flutter์˜ ์„ฑ๋Šฅ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋Š” ๊ฐ™์€ ์›์น™์„ ๋”ฐ๋ฅด๋Š” Opacity, saveLayer, ํด๋ฆฝ ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ง€์นจ์„ ๋ชจ์•„ ๋‘ก๋‹ˆ๋‹ค.

2026๋…„ Flutter ์ตœ์ ํ™”๋ฅผ DevTools๋กœ ์ธก์ •ํ•˜๊ธฐ

์œ„์˜ ๋ชจ๋“  ๊ทœ์น™์€ ๊ฐ€์ •์ด ์•„๋‹ˆ๋ผ ๊ฒ€์ฆ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Flutter DevTools๊ฐ€ ์ง„์‹ค์˜ ์›์ฒœ์ž…๋‹ˆ๋‹ค. ์„ฑ๋Šฅ ์˜ค๋ฒ„๋ ˆ์ด(๋””๋ฒ„๊ทธ ์ฝ˜์†”์˜ P ๋˜๋Š” flutter run --profile)๋Š” UI์™€ ๋ž˜์Šคํ„ฐ๋ผ๋Š” ๋‘ ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๋ฉฐ, ์ดˆ๋ก ์„ ์„ ๋„˜๋Š” ๋ง‰๋Œ€๋Š” ๋ชจ๋‘ ๋–จ์–ด์ง„ ํ”„๋ ˆ์ž„์ž…๋‹ˆ๋‹ค. ์ด์–ด์„œ ํƒ€์ž„๋ผ์ธ ๋ทฐ๊ฐ€ ๊ฐ ๋А๋ฆฐ ํ”„๋ ˆ์ž„์„ ํŠน์ • build, ๋ ˆ์ด์•„์›ƒ, ํŽ˜์ธํŠธ ํ˜ธ์ถœ์— ๊ท€์†์‹œํ‚ต๋‹ˆ๋‹ค.

ํ•ญ์ƒ ์‹ค์ œ ๊ธฐ๊ธฐ์—์„œ --profile ๋ชจ๋“œ๋กœ ํ”„๋กœํŒŒ์ผํ•˜์‹ญ์‹œ์˜ค. ๋””๋ฒ„๊ทธ ๋นŒ๋“œ๋Š” ์ตœ์ ํ™”๋˜์ง€ ์•Š์€ Dart๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋ชจ๋“  ์ธก์ •์น˜๋ฅผ ๋ถ€ํ’€๋ฆฌ๋ฏ€๋กœ, ๋””๋ฒ„๊ทธ์—์„œ ๋ฒ„๋ฒ…์ด๋Š” ํ™”๋ฉด์ด ์ปดํŒŒ์ผ ํ›„์—๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ๋„๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. DevTools ์„ฑ๋Šฅ ๊ฐ€์ด๋“œ๋Š” ํ”„๋ ˆ์ž„ ์ฐจํŠธ๋ฅผ ์ฝ๊ณ  ๋ฒ„๋ฒ…์ž„์˜ ์›์ธ์„ ์ฐพ์•„๋‚ด๋Š” ๊ณผ์ •์„ ์งš์–ด ์ฃผ๋ฉฐ, ๊ฐ™์€ ํ”„๋กœํŒŒ์ผ๋ง ๊ทผ์œก์€ Flutter ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ๋ Œ๋”๋ง์— ๊ด€ํ•œ ๋ฉด์ ‘์—์„œ๋„ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋น ๋ฅธ ํ”„๋กœํŒŒ์ผ๋ง ๋ฃจํ”„

ํ”„๋กœํŒŒ์ผ ๋ชจ๋“œ๋กœ ์‹คํ–‰ํ•˜๊ณ , ๋ฒ„๋ฒ…์ด๋Š” ์ƒํ˜ธ์ž‘์šฉ์„ ์žฌํ˜„ํ•˜๊ณ , ํƒ€์ž„๋ผ์ธ์„ ์—ด์–ด ํ”„๋ ˆ์ž„์„ ์ง€์† ์‹œ๊ฐ„์œผ๋กœ ์ •๋ ฌํ•˜์‹ญ์‹œ์˜ค. ์ตœ์•…์˜ ํ”„๋ ˆ์ž„์€ ๊ฑฐ์˜ ์–ธ์ œ๋‚˜ ์ง€๋‚˜์น˜๊ฒŒ ํฐ ๋‹จ์ผ ๋ฆฌ๋นŒ๋“œ๋‚˜ ์บ์‹œ๋˜์ง€ ์•Š์€ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋ฉฐ, ์ด๋Š” ์ถ”์ธกํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋น ๋ฆ…๋‹ˆ๋‹ค.

๋” ๋„“์€ Flutter ๊ธฐ์ˆ  ํ—ˆ๋ธŒ๋Š” ํ”„๋กœ๋•์…˜ ์„ฑ๋Šฅ ์ „๋žต์„ ์™„์„ฑํ•˜๋Š” ์ƒํƒœ ๊ด€๋ฆฌ, ํ…Œ์ŠคํŠธ, ๋ Œ๋”๋ง ์ฃผ์ œ๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

2026๋…„ Flutter ์„ฑ๋Šฅ์€ ๋ฏธ์„ธํ•œ ์š”๋ น๋ณด๋‹ค๋Š”, ์ผ๊ด€๋˜๊ฒŒ ์ ์šฉํ•˜๋Š” ์งง์€ ์Šต๊ด€ ๋ชฉ๋ก์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • Impeller ์œ„์—์„œ ๋ฐฐํฌํ•˜๊ณ  ์˜ค๋ž˜๋œ ์…ฐ์ด๋” ์›Œ๋ฐ์—… ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•˜์‹ญ์‹œ์˜ค. ์ฒซ ํ”„๋ ˆ์ž„ ๋ฒ„๋ฒ…์ž„ ๋ฌธ์ œ๋Š” ์—”์ง„ ์ˆ˜์ค€์—์„œ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ •์  ์œ„์ ฏ์„ const๋กœ ํ‘œ์‹œํ•˜๊ณ  prefer_const_constructors ๋ฆฐํŠธ๋กœ ๊ฐ•์ œํ•˜์‹ญ์‹œ์˜ค.
  • ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ์œ„์ ฏ์„ ์ž‘๊ฒŒ ๋ถ„ํ• ํ•ด, ๊ฐ setState๊ฐ€ ๊ฐ€๋Šฅํ•œ ํ•œ ์ข์€ ํ•˜์œ„ ํŠธ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ฒŒ ํ•˜์‹ญ์‹œ์˜ค.
  • ๋ณ€ํ•˜๋Š” ๊ฐ’์„ ํ™”๋ฉด ์ „์ฒด๋ฅผ ๋ฆฌ๋นŒ๋“œํ•˜๋Š” ๋Œ€์‹  ValueListenableBuilder๋‚˜ select ์Šคํƒ€์ผ API๋กœ ๋ธŒ๋กœ๋“œ์บ์ŠคํŠธํ•˜์‹ญ์‹œ์˜ค.
  • ์ •๋ง๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜๋˜๋Š” ์˜์—ญ์„ RepaintBoundary๋กœ ๊ฐ์‹ธ๋˜, ๋” ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ์ธก์ •ํ•˜์‹ญ์‹œ์˜ค.
  • ๋ฆฌ์ŠคํŠธ๋Š” ListView.builder๋กœ ๊ตฌ์„ฑํ•˜๊ณ  ์ด๋ฏธ์ง€๋Š” cacheWidth๋กœ ํ‘œ์‹œ ํฌ๊ธฐ์— ๋งž์ถฐ ๋””์ฝ”๋”ฉํ•˜์‹ญ์‹œ์˜ค.
  • ์‹ค์ œ ํ•˜๋“œ์›จ์–ด์—์„œ --profile ๋ชจ๋“œ๋กœ ํ”„๋กœํŒŒ์ผํ•˜๊ณ , ๋‹ค์Œ์— ๋ฌด์—‡์„ ์ตœ์ ํ™”ํ• ์ง€ ์ง๊ฐ์ด ์•„๋‹ˆ๋ผ DevTools๊ฐ€ ๊ฒฐ์ •ํ•˜๊ฒŒ ํ•˜์‹ญ์‹œ์˜ค.

์—ฐ์Šต์„ ์‹œ์ž‘ํ•˜์„ธ์š”!

๋ฉด์ ‘ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ๊ธฐ์ˆ  ํ…Œ์ŠคํŠธ๋กœ ์ง€์‹์„ ํ…Œ์ŠคํŠธํ•˜์„ธ์š”.

ํƒœ๊ทธ

#flutter
#performance
#impeller
#best-practices
#dart
#mobile

๊ณต์œ 

๊ด€๋ จ ๊ธฐ์‚ฌ

Flutter ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Riverpod์™€ BLoC ๋น„๊ต

Flutter ์ƒํƒœ ๊ด€๋ฆฌ: Riverpod vs BLoC - ์™„์ „ ๋น„๊ต ๊ฐ€์ด๋“œ

Flutter ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Riverpod์™€ BLoC์˜ ์‹ฌ์ธต ๋น„๊ต์ž…๋‹ˆ๋‹ค. ์•„ํ‚คํ…์ฒ˜, ์„ฑ๋Šฅ, ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ, ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ†ตํ•ด ์ตœ์ ์˜ ์†”๋ฃจ์…˜์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋ฐ”์ผ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Flutter ๋ฉด์ ‘ ์งˆ๋ฌธ ๊ฐ€์ด๋“œ

๋ชจ๋ฐ”์ผ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ Flutter ๋ฉด์ ‘ ์งˆ๋ฌธ 20์„ 

Flutter ๋ฉด์ ‘์—์„œ ๊ฐ€์žฅ ์ž์ฃผ ์ถœ์ œ๋˜๋Š” 20๊ฐ€์ง€ ์งˆ๋ฌธ์„ ์ค€๋น„ํ•˜์‹ญ์‹œ์˜ค. Widget, ์ƒํƒœ ๊ด€๋ฆฌ, Dart, ์•„ํ‚คํ…์ฒ˜, ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ์ƒ์„ธํ•œ ์ฝ”๋“œ ์˜ˆ์ œ์™€ ํ•จ๊ป˜ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

Flutter์™€ Dart๋กœ ์ฒซ ๋ฒˆ์งธ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฐ€์ด๋“œ

Flutter: ์ฒซ ๋ฒˆ์งธ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์•ฑ ๊ตฌ์ถ•ํ•˜๊ธฐ

Flutter์™€ Dart๋ฅผ ์‚ฌ์šฉํ•œ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๋ชจ๋ฐ”์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์ถ• ์™„์ „ ๊ฐ€์ด๋“œ. Widget, ์ƒํƒœ ๊ด€๋ฆฌ, ๋‚ด๋น„๊ฒŒ์ด์…˜, ์ดˆ๋ณด์ž๋ฅผ ์œ„ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.