๐Ÿ“š Today I Learned 9ํšŒ์ฐจ - [ํ”Œ๋ฃจํ„ฐ] ์ „์ž ์•ก์ž ๋งŒ๋“ค๊ธฐ ๐Ÿ–ผ๏ธ

4 ๋ถ„ ์†Œ์š”

๐Ÿ–ผ๏ธ ์ „์ž ์•ก์ž ๋งŒ๋“ค๊ธฐ

๐ŸŽฏ ํ•™์Šต ๋ชฉํ‘œ

์ด๋ฒˆ ํ•™์Šต์—์„œ๋Š” ์ „์ž ์•ก์ž ์•ฑ์„ ๋งŒ๋“ค์–ด๋ณด๋ฉฐ ๋‹ค์Œ ๋‚ด์šฉ์„ ์ตํ˜€๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:

  • ์ด๋ฏธ์ง€ ๋กค๋ง ํ‘œ์‹œ: 5๊ฐœ์˜ ์ด๋ฏธ์ง€๋ฅผ ์ž๋™์œผ๋กœ ์ˆœํ™˜ํ•˜๋ฉฐ ํ‘œ์‹œ
  • ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ: ์ขŒ์šฐ ์Šค์™€์ดํ”„๋กœ ์ˆ˜๋™ ์ด๋ฏธ์ง€ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
  • ํƒ€์ด๋จธ ๊ธฐ๋Šฅ: ํŠน์ • ์ฃผ๊ธฐ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ•จ์ˆ˜ ์‹คํ–‰
  • ์ƒ๋ช…์ฃผ๊ธฐ ๊ด€๋ฆฌ: StatefulWidget์˜ ์ƒ๋ช…์ฃผ๊ธฐ ํ™œ์šฉ

๐Ÿ“‹ ํ•™์Šต ์ˆœ์„œ

graph LR
    A[๐Ÿ” ์‚ฌ์ „ ์ง€์‹] --> B[โš™๏ธ ์‚ฌ์ „ ์ค€๋น„]
    B --> C[๐ŸŽจ ๋ ˆ์ด์•„์›ƒ ๊ตฌ์ƒ]
    C --> D[๐Ÿ’ป ๊ตฌํ˜„ํ•˜๊ธฐ]
    D --> E[๐Ÿงช ํ…Œ์ŠคํŠธํ•˜๊ธฐ]

๐Ÿ› ๏ธ ํ•ต์‹ฌ ๊ธฐ์ˆ  ์Šคํƒ

๊ธฐ์ˆ  ์—ญํ•  ์ค‘์š”๋„
PageView ํŽ˜์ด์ง€ ์Šค์™€์ดํ”„ ๋ฐ ์ด๋ฏธ์ง€ ์ „ํ™˜ โญโญโญ
Timer ์ž๋™ ์ด๋ฏธ์ง€ ๋กค๋ง ๊ธฐ๋Šฅ โญโญโญ
StatefulWidget ์ƒํƒœ ๊ด€๋ฆฌ ๋ฐ ์ƒ๋ช…์ฃผ๊ธฐ โญโญโญ

๐Ÿ“š ์‚ฌ์ „ ์ง€์‹

๐Ÿ”„ ์œ„์ ฏ์˜ ์ƒ๋ช…์ฃผ๊ธฐ

์œ„์ ฏ์˜ ์ƒ๋ช…์ฃผ๊ธฐ(Lifecycle)๋Š” ์œ„์ ฏ์ด ํ™”๋ฉด์— ๊ทธ๋ ค์ง€๋Š” ์ˆœ๊ฐ„๋ถ€ํ„ฐ ์‚ญ์ œ๋˜๋Š” ์ˆœ๊ฐ„๊นŒ์ง€์˜ ์ „์ฒด ๊ณผ์ •์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์ค‘์š”: ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ์ดํ•ดํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐฉ์ง€์™€ ์„ฑ๋Šฅ ์ตœ์ ํ™”์— ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค!

โšก StatelessWidget

StatelessWidget์˜ ์ƒ๋ช…์ฃผ๊ธฐ:

  1. ์ƒ์„ฑ์ž ์‹คํ–‰: StatelessWidget ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
  2. build() ์‹คํ–‰: UI ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ˜ํ™˜
  3. ๋ Œ๋”๋ง: build()๊ฐ€ ๋ฐ˜ํ™˜ํ•œ Widget์ด ํ™”๋ฉด์— ํ‘œ์‹œ
class MyStatelessWidget extends StatelessWidget {
  // 1. ์ƒ์„ฑ์ž ์‹คํ–‰
  const MyStatelessWidget({Key? key}) : super(key: key);

  // 2. build ํ•จ์ˆ˜ ์‹คํ–‰
  @override
  Widget build(BuildContext context) {
    return Text('Hello World!'); // 3. ํ™”๋ฉด์— ๋ Œ๋”๋ง
  }
}

โš ๏ธ ์ฃผ์˜: StatelessWidget์€ ๋ถˆ๋ณ€(Immutable) ํŠน์„ฑ์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”„ StatefulWidget

StatefulWidget์€ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ์œ„์ ฏ์ž…๋‹ˆ๋‹ค. ์™ธ๋ถ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ ์‹œ์˜ ๋™์ž‘์€ StatelessWidget๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ๋‚ด๋ถ€์—์„œ build() ํ•จ์ˆ˜๋ฅผ ์žฌ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

StatefulWidget์—๋Š” 3๊ฐ€์ง€ ํ•ต์‹ฌ ์ƒ๋ช…์ฃผ๊ธฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:

์œ ํ˜• ๋ฐœ์ƒ ์‹œ์  ์ฃผ์š” ๋ฉ”์„œ๋“œ
๐Ÿ”„ ๊ธฐ๋ณธ ์ƒ๋ช…์ฃผ๊ธฐ ์œ„์ ฏ ์ตœ์ดˆ ์ƒ์„ฑ ์‹œ initState() โ†’ build()
๐Ÿ“ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ ๋ถ€๋ชจ์—์„œ ์ƒˆ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ „๋‹ฌ didUpdateWidget() โ†’ build()
โšก ์ƒํƒœ ๋ณ€๊ฒฝ setState() ํ˜ธ์ถœ ์‹œ setState() โ†’ build()

์ƒํƒœ ๋ณ€๊ฒฝ์ด ์—†๋Š” ์ƒ๋ช…์ฃผ๊ธฐ

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ StatefulWidget์˜ ๊ธฐ๋ณธ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค:

  1. ์ƒ์„ฑ์ž ์‹คํ–‰: StatefulWidget์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค
  2. createState(): State ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
  3. initState(): ์œ„์ ฏ์ด ์ฒ˜์Œ ์ƒ์„ฑ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค
  4. didChangeDependencies(): State๊ฐ€ ์˜์กดํ•˜๋Š” ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค
  5. dirty โ†’ build() โ†’ clean: UI ๋ Œ๋”๋ง ์‚ฌ์ดํด์ž…๋‹ˆ๋‹ค
  6. didUpdateWidget() / setState(): ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ build()๋ฅผ ์žฌํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค
  7. deactivate() / dispose(): ์œ„์ ฏ์ด ์ œ๊ฑฐ๋  ๋•Œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค

StatefulWidget ์ƒ์„ฑ์ž์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋์„ ๋•Œ ์ƒ๋ช…์ฃผ๊ธฐ

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋ถ€๋ชจ ์œ„์ ฏ์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์ž…๋‹ˆ๋‹ค:

  1. ์ƒˆ๋กœ์šด ์ƒ์„ฑ์ž: ๋ถ€๋ชจ๊ฐ€ ์ƒˆ๋กœ์šด ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์œ„์ ฏ์„ ์žฌ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค
  2. didUpdateWidget(): ๊ธฐ์กด ์œ„์ ฏ๊ณผ ์ƒˆ ์œ„์ ฏ์„ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค
  3. dirty โ†’ build() โ†’ clean: ๋ณ€๊ฒฝ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ UI๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค

State ์ž์ฒด์ ์œผ๋กœ build()๋ฅผ ์žฌ์‹คํ–‰ํ•  ๋•Œ ์ƒ๋ช…์ฃผ๊ธฐ

setState() ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์„œ build() ํ•จ์ˆ˜๋ฅผ ์ž์ฒด์ ์œผ๋กœ ์žฌ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ setState() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ์˜ ์ƒ๋ช…์ฃผ๊ธฐ์ž…๋‹ˆ๋‹ค:

  1. setState() ํ˜ธ์ถœ: ์ƒํƒœ ๋ณ€๊ฒฝ์„ ํ”„๋ ˆ์ž„์›Œํฌ์— ์•Œ๋ฆฌ๊ณ  build() ์žฌ์‹คํ–‰์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค
  2. dirty โ†’ build() โ†’ clean: ๋ณ€๊ฒฝ๋œ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•˜์—ฌ UI๋ฅผ ๋‹ค์‹œ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค

์ด๋Š” ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ UI ์—…๋ฐ์ดํŠธ ํŒจํ„ด์œผ๋กœ, ์‚ฌ์šฉ์ž ์ƒํ˜ธ์ž‘์šฉ์ด๋‚˜ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์‹œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Timer

Timer๋Š” ํŠน์ • ์‹œ๊ฐ„์ด ์ง€๋‚œ ํ›„์— ์ผํšŒ์„ฑ ๋˜๋Š” ์ง€์†์ ์œผ๋กœ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

Timer( // ํ•œ๋ฒˆ ์‹คํ–‰
  Duration(seconds: 3), // ์ฃผ๊ธฐ
  (Timer timer) {}, // ์ฝœ๋ฐฑ ํ•จ์ˆ˜
) 
Timer.periodic( // ์ฃผ๊ธฐ์ ์œผ๋กœ ์‹คํ–‰
  Duration(seconds: 3), // ์ฃผ๊ธฐ
  (Timer timer) {}, // ์ฝœ๋ฐฑ ํ•จ์ˆ˜
)

๊ตฌํ˜„ํ•˜๊ธฐ

PageView ๊ตฌํ˜„ํ•˜๊ธฐ

PageView๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์œ„์ ฏ์„ ๋‹จ๋… ํŽ˜์ด์ง€๋กœ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ€๋กœ ๋˜๋Š” ์„ธ๋กœ ์Šค์™€์ดํ”„๋กœ ํŽ˜์ด์ง€๋ฅผ ๋„˜๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์œ„์ ฏ์ด๋‹ค.

BoxFit ์†์„ฑ ์„ค๋ช…
BoxFit.contain ๊ฐ€๋กœ์„ธ๋กœ ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ•์Šค ์•ˆ์— ์™„์ „ํžˆ ๋“ค์–ด๊ฐ€๋„๋ก ์กฐ์ ˆ
BoxFit.cover ๊ฐ€๋กœ์„ธ๋กœ ๋น„์œจ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ฐ•์Šค๋ฅผ ์™„์ „ํžˆ ์ฑ„์šฐ๋„๋ก ์กฐ์ ˆ (์ด๋ฏธ์ง€ ์ผ๋ถ€ ์ž˜๋ฆด ์ˆ˜ ์žˆ์Œ)
BoxFit.fill ๊ฐ€๋กœ์„ธ๋กœ ๋น„์œจ์„ ๋ฌด์‹œํ•˜๊ณ  ๋ฐ•์Šค๋ฅผ ์™„์ „ํžˆ ์ฑ„์šฐ๋„๋ก ๋Š˜์ด๊ฑฐ๋‚˜ ์ค„์ž„
BoxFit.fitHeight ๋†’์ด์— ๋งž์ถฐ ์ด๋ฏธ์ง€๋ฅผ ์กฐ์ ˆํ•˜๊ณ , ๋„ˆ๋น„๋Š” ๋น„์œจ์— ๋งž์ถฐ ์กฐ์ ˆ
BoxFit.fitWidth ๋„ˆ๋น„์— ๋งž์ถฐ ์ด๋ฏธ์ง€๋ฅผ ์กฐ์ ˆํ•˜๊ณ , ๋†’์ด๋Š” ๋น„์œจ์— ๋งž์ถฐ ์กฐ์ ˆ
BoxFit.none ์ด๋ฏธ์ง€ ์›๋ณธ ํฌ๊ธฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ๋ฐ•์Šค ์ค‘์•™์— ๋ฐฐ์น˜
BoxFit.scaleDown contain๊ณผ none ์ค‘ ๋” ์ž‘์€ ํฌ๊ธฐ๋กœ ์กฐ์ ˆ

์ƒํƒœ๋ฐ” ์ƒ‰์ƒ ๋ณ€๊ฒฝํ•˜๊ธฐ

์ƒํƒœ๋ฐ”๋Š” ์•ฑ์„ ์‹คํ–‰ ์ค‘ ํ•ธ๋“œํฐ ๋ฐฐํ„ฐ๋ฆฌ, ์‹œ๊ฐ„, ์™€์ดํŒŒ์ด ์—ฐ๊ฒฐ ์ƒํƒœ ๋“ฑ์„ ๋ณด์—ฌ์ฃผ๋Š” ์˜์—ญ์ด๋‹ค.

SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light); 

SystemChrome ํด๋ž˜์Šค๋Š” ์‹œ์Šคํ…œ UI์˜ ๊ทธ๋ž˜ํ”ฝ ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

SystemChrome ํ•จ์ˆ˜

ํ•จ์ˆ˜ ์„ค๋ช…
setEnabledSystemUIMode() ์‹œ์Šคํ…œ UI ๋ชจ๋“œ๋ฅผ ์„ค์ • (์ „์ฒดํ™”๋ฉด, ์ƒํƒœ๋ฐ”/๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ” ํ‘œ์‹œ ๋“ฑ)
setPreferredOrientations() ํ™”๋ฉด ํšŒ์ „ ๋ฐฉํ–ฅ์„ ์ œํ•œ (์„ธ๋กœ๋ชจ๋“œ, ๊ฐ€๋กœ๋ชจ๋“œ ๋“ฑ)
setSystemUIChangeCallback() ์‹œ์Šคํ…œ UI ๋ณ€๊ฒฝ ์‹œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋ก
setSystemUIOverlayStyle() ์ƒํƒœ๋ฐ”์™€ ๋„ค๋น„๊ฒŒ์ด์…˜๋ฐ”์˜ ์Šคํƒ€์ผ์„ ์„ค์ •

โฐ ์ž๋™ ๋กค๋ง ํƒ€์ด๋จธ ์ถ”๊ฐ€

์ž๋™ ๋กค๋ง ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด StatefulWidget์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๊นŒ์š”?

โš ๏ธ ์ฃผ์˜: StatelessWidget์—์„œ build() ํ•จ์ˆ˜ ๋‚ด๋ถ€์— Timer๋ฅผ ๋“ฑ๋กํ•˜๋ฉด, ์œ„์ ฏ์ด ๋ฆฌ๋นŒ๋“œ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด Timer๊ฐ€ ๊ณ„์† ์ƒ์„ฑ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค! ๐Ÿšจ

StatefulWidget์„ ์‚ฌ์šฉํ•˜๋ฉด initState()์—์„œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ Timer๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

class PhotoFrameState extends State<PhotoFrame> {
  PageController _pageController = PageController();
  Timer? _timer;

  @override
  void initState() {
    super.initState();

    // โœจ ์ž๋™ ๋กค๋ง ํƒ€์ด๋จธ ์„ค์ • (3์ดˆ๋งˆ๋‹ค)
    _timer = Timer.periodic(Duration(seconds: 3), (timer) {
      // ํ˜„์žฌ ํŽ˜์ด์ง€ ๊ฐ€์ ธ์˜ค๊ธฐ
      double? currentPage = _pageController.page;
      int nextPage = currentPage == null ? 1 : (currentPage.round() + 1) % 5;

      // ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ์ด๋™
      _pageController.animateToPage(
        nextPage,
        duration: Duration(milliseconds: 500),
        curve: Curves.easeInOut,
      );
    });
  }

  @override
  void dispose() {
    _timer?.cancel(); // ๐Ÿงน ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ
    _pageController.dispose();
    super.dispose();
  }
}

PageController๋ฅผ ์‚ฌ์šฉํ•ด์„œ PageView์˜ ํ˜„์žฌ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

๐Ÿ“Š PageController ์‚ฌ์šฉ๋ฒ•

๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ ๋ฐ˜ํ™˜๊ฐ’
.page ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ double? (์Šค์™€์ดํ”„ ์ค‘์—๋Š” ์†Œ์ˆ˜์ )
.animateToPage() ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ํ•จ๊ป˜ ์ด๋™ Future<void>
.nextPage() ๋‹ค์Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ Future<void>

๐Ÿ’ก ๊ฟ€ํŒ: pageController.page๊ฐ€ null์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํ•ญ์ƒ null ์ฒดํฌ๋ฅผ ํ•ด์ฃผ์„ธ์š”!

๐Ÿ† ๋งˆ๋ฌด๋ฆฌ

โœจ ์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ

์ด๋ฒˆ ์ „์ž ์•ก์ž ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†Œ์ค‘ํ•œ ๊ธฐ์ˆ ๋“ค์„ ๋งˆ์Šคํ„ฐํ–ˆ์Šต๋‹ˆ๋‹ค:

๊ธฐ์ˆ  ํ•™์Šต ๋‚ด์šฉ ์‹ค์ œ ์‘์šฉ
๐Ÿ“‹ PageView ์Šค์™€์ดํ”„ ๊ธฐ๋Šฅ, PageController ์‚ฌ์šฉ๋ฒ• ์‚ฌ์ง„ ์•ฑ, ์˜จ๋ณด๋”ฉ ํ™”๋ฉด
โฐ Timer ์ž๋™ ์‹คํ–‰, ์ฃผ๊ธฐ์  ์ž‘์—…, ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๋ฐฐ๋„ˆ ๋กค๋ง, ์•Œ๋žŒ, ์‹ค์‹œ๊ฐ„ ์—…๋ฐ์ดํŠธ
๐Ÿ”„ StatefulWidget 3๊ฐ€์ง€ ์ƒ๋ช…์ฃผ๊ธฐ ํŒจํ„ด, ์ƒํƒœ ๊ด€๋ฆฌ ๋ชจ๋“  ๋™์  UI, ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ์•ฑ
๐ŸŽจ SystemChrome ์ƒํƒœ๋ฐ” ์Šคํƒ€์ผ๋ง, ํ™”๋ฉด ๋ฐฉํ–ฅ ์ „์ฒดํ™”๋ฉด ์•ฑ, ๊ฒŒ์ž„, ๋ฏธ๋””์–ด ์•ฑ
๐Ÿ–ผ๏ธ BoxFit ์ด๋ฏธ์ง€ ์กฐ์ ˆ ๋ฐฉ์‹ 7๊ฐ€์ง€ ๊ฐค๋Ÿฌ๋ฆฌ, ํ”„๋กœํ•„, ์ƒํ’ˆ ์ด๋ฏธ์ง€

๐Ÿš€ ๋‹ค์Œ ๊ณ„ํš

์˜ค๋Š˜ ํ•™์Šตํ•œ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋” ๋ฉ‹์ง„ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ๋„ํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

  • ๐ŸŽจ ๊ณ ๊ธ‰ ์‚ฌ์ง„ ์—๋””ํ„ฐ: ํ•„ํ„ฐ, ํšŒ์ „, ์ž๋ฅด๊ธฐ ๊ธฐ๋Šฅ
  • ๐ŸŽต ์Œ์•… ํ”Œ๋ ˆ์ด์–ด: ์ž๋™ ์žฌ์ƒ, ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ
  • ๐Ÿ“ฑ ์†Œ์…œ ๋ฏธ๋””์–ด ์•ฑ: ์ธํ”ผ๋‹ˆํŠธ ์Šคํฌ๋กค, ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ
  • ๐ŸŽฎ ๋ฏธ๋‹ˆ ๊ฒŒ์ž„: ์• ๋‹ˆ๋ฉ”์ด์…˜, ๋ฒ„ํŠผ ์ธํ„ฐ๋ž™์…˜

๐Ÿ’ช ์„ฑ์žฅ ํŒ: ์˜ค๋Š˜ ๋ฐฐ์šด StatefulWidget ์ƒ๋ช…์ฃผ๊ธฐ๋Š” Flutter ๊ฐœ๋ฐœ์˜ ํ•ต๋Œ€๊ฐ€ ๋˜๋Š” ์ค‘์š”ํ•œ ๊ฐœ๋…์ž…๋‹ˆ๋‹ค. ๊ณ„์† ์—ฐ์Šตํ•ด์„œ ๋งˆ์Šคํ„ฐํ•˜์„ธ์š”!

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ