Flutter: ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ์ฑ„๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2018๋…„ 01์›” 05์ผ  ยท  133์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: flutter/flutter

์‚ฌ์šฉ์ž ์ง€์ • ์ƒ์„ฑ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ์ฑ„๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์•ฑ์ด ์‹ฌํ•˜๊ฒŒ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค(iOS ๋ฐ Android ๋ชจ๋‘์—์„œ). ์ด๊ฒƒ์ด ์˜ˆ์ƒ๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ์•„ ๋‚ด๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ์–ด๋”˜๊ฐ€์— ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ๋‚˜๋Š” ์ด๊ฒƒ์ด ์ž ์žฌ์ ์œผ๋กœ ๊ฐ•๋ ฅํ•œ ํ•œ๊ณ„๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ณด์กฐ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

P5 annoyance crowd gold engine framework passed first triage plugin crash new feature

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค์–‘ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ:

  • ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ๊ตฌ๋ฌธ ๋ถ„์„ํ•œ ๋‹ค์Œ(dart:convert ๋ฉ”์„œ๋“œ๋Š” ๋น„๋™๊ธฐ์‹ ์•„๋‹˜) sqflite ํ”Œ๋Ÿฌ๊ทธ์ธ(ํ”Œ๋žซํผ ๋ฐ”์ธ๋”ฉ ์‚ฌ์šฉ)์„ ์‚ฌ์šฉํ•˜์—ฌ sqlite db์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • UI์— ์ œ๊ณตํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๊ณ  ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.
  • ์•”ํ˜ธํ™”/์•”ํ˜ธ ํ•ด๋… ๋ฐ ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ/์“ฐ๊ธฐ(์•”ํ˜ธํ™” ์ž‘์—…์€ ํ”Œ๋žซํผ ๋ณด์•ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ํ†ตํ•ด ์ˆ˜ํ–‰๋จ)

์ผ๋ฐ˜์ ์œผ๋กœ ์–ด๋–ค ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋Š” ์ข…์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ตญ์—๋Š” ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: flutterfire์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๊ฒƒ๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋Œ๋กœ ์“ฐ์—ฌ์ง„ ๊ฒƒ ๋Œ€์‹ ์— ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฌ๋‚˜ ๊ตฌํ˜„ํ•˜๋Š” ๋™์•ˆ ์•ฝ๊ฐ„ ๋ง‰ํ˜”์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์—์„œ ๋ณด์กฐ ๋ฉ”์„œ๋“œ์—์„œ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์˜ ์˜ˆ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”

๋ชจ๋“  133 ๋Œ“๊ธ€

๋ถ„๋ฅ˜๋ฅผ ์œ„ํ•œ cc @mravn-google

์—”์ง„ ์ฝ”๋“œ๋Š” null์„ ์—ญ์ฐธ์กฐํ•˜๊ณ  ๋ณด์กฐ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋ ค๊ณ  ํ•  ๋•Œ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ง ์ •ํ™•ํžˆ ์–ด๋””๋ฅผ ์ง€์ ํ•˜์ง€ ์•Š์•˜๋‹ค; ๋‚˜๋Š” ๋ฌ˜๋น„๋ฅผ ์–ป์—ˆ์ง€๋งŒ ๊ทธ๋Ÿฌํ•œ ๊ฒƒ์„ ํ•ด์„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ์•ผํ•ฉ๋‹ˆ๋‹ค.

(์„œํˆฌ๋ฅธ) ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์œผ๋กœ ๋‘ ๋ฒˆ์งธ ๊ฒฉ๋ฆฌ๋Š” ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@sroddy 2์ฐจ ๊ฒฉ๋ฆฌ๋กœ ๋ฌด์—‡์„ ํ•˜๋ ค๋Š”์ง€ ์—ฌ์ญค๋ด๋„ ๋ ๊นŒ์š”?

๋‹ค์–‘ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ:

  • ์—„์ฒญ๋‚œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ๊ตฌ๋ฌธ ๋ถ„์„ํ•œ ๋‹ค์Œ(dart:convert ๋ฉ”์„œ๋“œ๋Š” ๋น„๋™๊ธฐ์‹ ์•„๋‹˜) sqflite ํ”Œ๋Ÿฌ๊ทธ์ธ(ํ”Œ๋žซํผ ๋ฐ”์ธ๋”ฉ ์‚ฌ์šฉ)์„ ์‚ฌ์šฉํ•˜์—ฌ sqlite db์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  • UI์— ์ œ๊ณตํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๊ณ  ๊ตฌ๋ฌธ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.
  • ์•”ํ˜ธํ™”/์•”ํ˜ธ ํ•ด๋… ๋ฐ ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ/์“ฐ๊ธฐ(์•”ํ˜ธํ™” ์ž‘์—…์€ ํ”Œ๋žซํผ ๋ณด์•ˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ํ†ตํ•ด ์ˆ˜ํ–‰๋จ)

์ผ๋ฐ˜์ ์œผ๋กœ ์–ด๋–ค ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•˜๋Š” ์ข…์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฐ๊ตญ์—๋Š” ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: flutterfire์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค). ๊ทธ๊ฒƒ๋“ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋Œ๋กœ ์“ฐ์—ฌ์ง„ ๊ฒƒ ๋Œ€์‹ ์— ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฌ๋‚˜ ๊ตฌํ˜„ํ•˜๋Š” ๋™์•ˆ ์•ฝ๊ฐ„ ๋ง‰ํ˜”์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์—์„œ ๋ณด์กฐ ๋ฉ”์„œ๋“œ์—์„œ ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์˜ ์˜ˆ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”

@sroddy ๋ฐฐ๊ฒฝ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์—์„œ ์ •์  ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ •๋ณด: ์ง์ ‘ ์ง€์›๋˜์ง€ ์•Š์œผ๋ฉฐ ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŒจํ‚ค์ง€ ๋Š” ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์˜ˆ: here . ๊ทธ๋ž˜๋„ ์ง์ ‘ ์‹œ๋„ํ•˜์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ํ”Œ๋žซํผ ์ฑ„๋„ ํ†ต์‹ ์ด ํ”Œ๋Ÿฌ๊ทธ์ธ ๋˜๋Š” ๊ธฐํƒ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌํ˜„์˜ ์ผ๋ถ€๋กœ ์ˆ˜ํ–‰๋  ๋•Œ๋„ ์ž‘๋™ํ•˜๋Š” ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ ์†”๋ฃจ์…˜์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

์†”๋ฃจ์…˜์€ ์•„๋ž˜์— ์Šค์ผ€์น˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์— ํฌํŠธ M1 ๋ฐ R1์„ ์„ค์ •ํ•˜๊ณ  ๋ณด์กฐ ๊ฒฉ๋ฆฌ์— M2, R2๋ฅผ ์„ค์ •ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. M์€ ๋ฉ”์‹œ์ง€, R์€ ๋‹ต์žฅ์ž…๋‹ˆ๋‹ค.

  • 2์ฐจ ๊ฒฉ๋ฆฌ์—์„œ ๊ฐ ์ฑ„๋„์— ๋Œ€ํ•ด BinaryMessages.setMockMessageHandler ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”Œ๋žซํผ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ M1(ํ•ด๋‹น ์ฑ„๋„๊ณผ ํ•จ๊ป˜ BinaryMessage.send๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์— ํˆฌ๋ช…ํ•˜๊ฒŒ ์ „๋‹ฌ)์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต ์ฝœ๋ฐฑ์„ ์ €์žฅํ•˜๊ณ  ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•œ ์‘๋‹ต ์ˆ˜์‹  ์‹œ ์˜ฌ๋ฐ”๋ฅธ ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋กœ R2๋ฅผ ๊ตฌ์„ฑํ•˜์‹ญ์‹œ์˜ค. BinaryMessages.handlePlatformMessage ๋กœ ์ „๋‹ฌํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋กœ M2๋ฅผ ๊ตฌ์„ฑํ•˜์‹ญ์‹œ์˜ค. ํšŒ์‹  ์ฝœ๋ฐฑ์„ ๊ตฌํ˜„ํ•˜์—ฌ R1์— ํšŒ์‹ ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์š” ๊ฒฉ๋ฆฌ์—์„œ ๋Œ€์นญ์œผ๋กœ. ํ”Œ๋žซํผ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ BinaryMessages.send ๋กœ ์ „๋‹ฌํ•˜๋Š” ์ฒ˜๋ฆฌ๊ธฐ๋กœ M1์„ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ํ”Œ๋žซํผ์—์„œ R2๋กœ ์‘๋‹ต์„ ์ „๋‹ฌํ•˜๋Š” ์‘๋‹ต ์ฝœ๋ฐฑ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ฐ ์ฑ„๋„์— ๋Œ€ํ•ด BinaryMessages.setMessageHandler ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ M2๋กœ ์ „๋‹ฌํ•˜๋Š” ํ”Œ๋žซํผ์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต ์ฝœ๋ฐฑ์„ ์ €์žฅํ•˜๊ณ  ๋ณด์กฐ ๊ฒฉ๋ฆฌ์—์„œ ์‘๋‹ต์„ ์ˆ˜์‹ ํ•˜๋ฉด ์˜ฌ๋ฐ”๋ฅธ ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋กœ R1์„ ๊ตฌ์„ฑํ•˜์‹ญ์‹œ์˜ค.

@Hixie ๋‹ค์Œ ์ด์ •ํ‘œ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ข‹์€ ์†”๋ฃจ์…˜์—๋Š” ์•ฝ๊ฐ„์˜ API ์„ค๊ณ„ ์ž‘์—…๊ณผ ๋ฐ˜๋ณต ์ž‘์—…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@mravn-google ์ด๊ฒƒ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค (์˜ˆ๋ฅผ ๋“ค์–ด ํ”Œ๋žซํผ ์ธก์—์„œ RSA 2048 ํ‚ค ์Œ์„ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋ฉฐ ์ด๋Š” ์ด์ „ ์žฅ์น˜์—์„œ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”/๋ณตํ˜ธํ™”ํ•ฉ๋‹ˆ๋‹ค). Android ๋ฐ iOS ํ”Œ๋žซํผ ๋ชจ๋‘์— ๋Œ€ํ•ด ๊ตฌํ˜„๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ ํ”Œ๋žซํผ ์ธก์—์„œ ์ž‘์—…์„ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฌ๋Š” ์Šค๋ ˆ๋“œ ๋˜๋Š” ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. Dart์—์„œ ํ”Œ๋žซํผ๋ณ„ ์ž‘์—…์„ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์‰ฝ๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ท€ํ•˜์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์ง€๋งŒ Flutter ๋ฐ Dart๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค(Isolate ๋“ฑ์— ๋Œ€ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค). ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด.

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

Android/iOS ์ธก์—์„œ PDF๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ์ข€ ๊ฑธ๋ฆฌ๊ณ  ๊ฑฐ๊ธฐ์—์„œ ํ˜ธ์ถœ์„ ์‹คํ–‰ํ•˜๋ฉด compute(...) ๋ฉ”์„œ๋“œ๊ฐ€ ์•ฑ์„ ์ถฉ๋Œ์‹œํ‚ต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ ์ด์ œ ๋ง‰ํ˜”์Šต๋‹ˆ๋‹ค.

์•ฑ์ด ํฌ๊ทธ๋ผ์šด๋“œ์— ์žˆ์ง€ ์•Š๋”๋ผ๋„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๊ฒฉ๋ฆฌ์—์„œ ๊ณต์œ  ๊ธฐ๋ณธ ์„ค์ •์—์„œ accessToken์„ ์ฝ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค(๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๊ณ  ์žˆ์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค).

๊ทธ๋ž˜์„œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๊ฒฉ๋ฆฌ์—์„œ ์ง€์† ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๋Š” ์†”๋ฃจ์…˜์„ ๋งํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์ง€๊ธˆ ์ •๋ง ๊ณค๋ž€ํ•ด์š”.

/cc @bkonyi ์ด๊ฒƒ์€ ๋‹น์‹ ์ด ์ž‘์—…ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. CPU ๋ฐ”์šด๋“œ์— ๋Œ€ํ•œ ์šฐ๋ฆฌ์˜ ์ œํ’ˆ ๊ธฐ๋ฐ˜. ์šฐ๋ฆฌ๋Š” ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

@Thomson-Tsui ๋‚˜๋„ ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ณ  @bkonyi ์™€ ๊ทธ์˜ FlutterGeofencing ์ƒ˜ํ”Œ์˜ ์ž‘์—… ์ฆ๋ฅ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋‚ด๊ฐ€ flutter_blue ๋ฐ ๊ธฐํƒ€ ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒฉ๋ฆฌ์—์„œ ์ž‘๋™ ํ•  ๋ฌด์–ธ๊ฐ€ ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋˜์ง€ ์•Š์•˜์ง€๋งŒ ์‹œ๋„ํ•ด๋ณด์‹ญ์‹œ์˜ค.

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ ํ–ˆ์Šต๋‹ˆ๊นŒ?

https://pub.dartlang.org/packages/flutter_isolate ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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

Isolate from dart๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ž๋ฐ”์—์„œ ํ”Œ๋Ÿฌํ„ฐ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ์ด ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค:

ย ย  private native void nativeRunBundleAndSnapshotFromLibrary (
ย ย ย ย ย ย  long nativePlatformViewId,
ย ย ย ย ย ย  <strong i="7">@NonNull</strong> String [] prioritizedBundlePaths,
ย ย ย ย ย ย  <strong i="8">@Nullable</strong> String entrypointFunctionName,
ย ย ย ย ย ย  <strong i="9">@Nullable</strong> String pathToEntrypointFunction,
ย ย ย ย ย ย  <strong i="10">@NonNull</strong> AssetManager manager
ย ย  );

๋ชจ๋“  ๋งˆ๋ฒ•์ด ์ผ์–ด๋‚˜๋Š” ๊ณณ)

์ด๊ฒƒ์€ FlutterNativeView๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ ์‹คํ–‰์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‚ฌ์‹ค์— ์˜ํ•ด ํ™•์ธ๋ฉ๋‹ˆ๋‹ค.

ย  public void runFromBundle (FlutterRunArguments args)

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ช‡ ๊ฐ€์ง€ "dart isolates"๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ์ด ๋ฌธ์ œ์— ์ง๋ฉดํ•ด ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ชจ๋‘ ํ”Œ๋žซํผ ์ฑ„๋„์— ์˜์กดํ•˜๋Š” ๋ฐฐ๊ฒฝ ๊ฒฉ๋ฆฌ(์˜ˆ: ์œ„์น˜, ์†Œ์Œ ๋“ฑ)์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. @mravn-google -- ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” API ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•œ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๋„๊ตฌ๋‚˜ ๋ฏธ๋””์–ด ์•ฑ์—์„œ๋Š” ์ •๋ง ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.
ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋˜ํ•œ ๋น„์Šทํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜์—ฌ ์ง€๊ธˆ ๋ง‰ํ˜”์Šต๋‹ˆ๋‹ค.

+1(๋‚ด ํ”„๋กœ์ ํŠธ๋„ ๊ฒฉ๋ฆฌ๋œ ํ”Œ๋žซํผ ์ฑ„๋„์ด ์‹ฌํ•˜๊ฒŒ ํ•„์š”ํ•จ)

๋ฐฐ๊ฒฝ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ด๋ฏธ์ง€๋Š” ๋ช‡ ์ดˆ๊ฐ€ ๊ฑธ๋ฆฌ๊ณ  ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ˆ˜ํ–‰๋˜๋Š” ๊ฒฝ์šฐ UI๋ฅผ ์ฐจ๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฉ๋ฆฌ์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” dart:ui.PictureRecorder ์˜ ์ฒซ ๋ฒˆ์งธ ๊ธฐ๋ณธ ํ˜ธ์ถœ์— ๊ฐ‡ํ˜€ ์žˆ๊ณ  ๊ฐ๊ฐ์˜ ๋ชจ๋“  ๊ทธ๋ž˜ํ”ฝ ํ˜ธ์ถœ(๊ธฐ๋ณธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋Š”)๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์บ”๋ฒ„์Šค์—์„œ ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝœ๋ฐฑ ํฌํŠธ๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์€ ๊ณ ํ†ต์Šค๋Ÿฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์†”๋ฃจ์…˜์„ ๋†’์ด ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

+1 ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค

@mravn-google์ด ์˜ค๋ฅดํ›„์Šค์—์„œ Google ์ž‘์—…์„ ์ค‘๋‹จํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•ด ์กฐ์‚ฌํ•˜๊ณ  ์žˆ๋Š” Google Flutter ํŒ€์˜ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. IMO, ์ด๊ฒƒ์€ ํƒ„๋ ฅ์ ์ด๊ณ  ๊ฐ•๋ ฅํ•œ Flutter ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•ด Flutter๋ฅผ ์ง„์ง€ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ฃผ์š” ์‡ผ ์Šคํ† ํผ์ž…๋‹ˆ๋‹ค....

@sethladd ๊ฐ€ ์ƒํƒœ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

+1

์ด์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

+1

์Šค์Šค๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•Œ์ง€๋งŒ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋Š” ๋ฒ„๊ทธ๋ฅผ ๋งŒ๋‚œ ๋‚ ์ด ํ”Œ๋Ÿฌํ„ฐ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋  ๋•Œ๊นŒ์ง€์˜ ๋งˆ์ง€๋ง‰ ํฌ๋ง์ž…๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด flutter/dart ์‚ฌ์šฉ์ž๋ฅผ ์œ„ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ดํ‹€ ์ „์— isolates๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๊ณ  ์ง€๋‚œ ์ฃผ์— flutter/dart๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ช‡ ๊ฐ€์ง€ ์‹ฌ๊ฐํ•˜๊ฒŒ ๋…ธ๋™ ์ง‘์•ฝ์ ์ธ ์ž‘์—…์— ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•™์Šต ํ”Œ๋Ÿฌํ„ฐ๊ฐ€ ๋‚˜์œ ์†”๋ฃจ์…˜์ด ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์ด ์—†์œผ๋ฉด Kotlin์„ ๋ฐฐ์šฐ๊ณ  ์•ฑ์„ ๋‘ ๋ฒˆ ๋นŒ๋“œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„ ๋ชจ๋‘๊ฐ€ ์ดˆ๋ณด์ž๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ํ•จ๊ป˜ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์ง์žฅ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ”Œ๋Ÿฌํ„ฐ ํ•™์Šต์„ ๊ณ ์šฉ์ฃผ์—๊ฒŒ ์ •๋‹นํ™”ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ์ •๋ง ๋ฐ”๋ž๋‹ˆ๋‹ค.
์—ฌ๊ธฐ์— ์—†๋‹ค๋ฉด ์•„๋งˆ๋„ StackOverflow์— ์งˆ๋ฌธ์„ ๊ฒŒ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค: https://stackoverflow.com/q/57466952/6047611

+1 ๊ณง ์ˆ˜์ •๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

+1 ๋‚ด ํ”„๋กœ์ ํŠธ๋Š” ๊ฒฉ๋ฆฌ๋œ ํ”Œ๋žซํผ ์ฑ„๋„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ @mravn-google์ด ๊ฒŒ์‹œํ•œ ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ํŒจํ‚ค์ง€( Isolate Handler )๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฒฉ๋ฆฌ ์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์™€ ํ•จ๊ป˜ ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์˜ ์ฑ„๋„์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฉ๋ฆฌ ๋‚ด์—์„œ ์ง์ ‘ MethodChannel ํ˜ธ์ถœ์„ ์ง€์›ํ•˜์ง€๋งŒ ํ˜„์žฌ EventChannel ์ŠคํŠธ๋ฆผ์€ ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํŒ๋ช…๋˜๋ฉด ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์˜ ํ•œ ๊ฐ€์ง€ ๋‹จ์ ์€ ๊ฒฉ๋ฆฌ ์ฒ˜๋ฆฌ๊ธฐ์— ์ฑ„๋„ ์ด๋ฆ„์„ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ฐพ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ ์ค‘์ธ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์œ„์— ์ด๋ฏธ ๊ฒŒ์‹œ๋œ ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์€ FlutterIsolate ์ž…๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉฐ ์‚ดํŽด๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Flutter ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ณง ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์™„์ „ํ•˜๊ณ  ์ ์ ˆํ•œ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

ํŽธ์ง‘ํ•˜๋‹ค:

๊ฒฐ๊ตญ Flutter ์ž์‚ฌ Android ์•Œ๋žŒ ๊ด€๋ฆฌ์ž ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ์œ ์‚ฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ๊ธฐ๋ณธ ์ธก์—์„œ ๊ฒฉ๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ๋” ๊น”๋”ํ•˜๊ฒŒ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ํ•ด์•ผ ํ•˜๋Š” ์œ ์ผํ•œ ์ผ์€ ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋„ค์ดํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ๋ฟ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋น„๊ต์  ์‰ฌ์šด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. pub.dev์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์›ํ™œํ•˜๊ฒŒ ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

+1 ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

+1

์—ฌ๊ธฐ์„œ ๋‚ด๊ฐ€ ์ฃผ๋ชฉํ•˜๋Š” ํฅ๋ฏธ๋กœ์šด ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์—ฌ๋Ÿฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋ฉ”์†Œ๋“œ ์ฑ„๋„ ํ˜ธ์ถœ์ด Dart์—์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋Š” ๊ฐ€์ • ํ•˜์— ์ž‘์„ฑ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด์™€ ๊ด€๋ จํ•˜์—ฌ, ๊ทธ bg ์ง€์˜คํŽœ์‹ฑ ์˜ˆ์ œ๋ฅผ ๋”ฐ๋ž๊ณ  ์ด์ œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๋Œ์•„๊ฐ€๋Š” ๋ฐฉ๋ฒ•์„ ๊ถ๊ธˆํ•ดํ•˜๋Š” ๋งค์šฐ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ์‚ฌ๋žŒ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค...
ํ•ด๋‹น ํ”Œ๋Ÿฌ๊ทธ์ธ ์ฝ”๋“œ๋Š” ์งง์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ "๋ฒ„๋ฒ…๊ฑฐ๋ฆผ"์„ ์ผ์œผํ‚ค์ง€ ์•Š์ง€๋งŒ ๊ธฐ๋ณธ์ ์œผ๋กœ Android์—์„œ๋Š” "UI ์Šค๋ ˆ๋“œ"๋ผ๊ณ  ํ•˜๋˜ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ž‘์—…๋Ÿ‰์ด ๋งŽ์„ ๋•Œ ์ œ์Šค์ฒ˜๊ฐ€ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฉ”์‹œ์ง€ ์ฑ„๋„๋„ ์ฐจ๋‹จํ•  ์ˆ˜ ์žˆ์Œ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ž‘์„ฑ์ž์˜ ์—”์ง€๋‹ˆ์–ด๋ง์— ์ข…์†๋ฉ๋‹ˆ๋‹ค. ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ์˜ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ๋ฌด๊ฑฐ์šด ์ž‘์—…์„ ์ด๋™ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์‹œ์ง€ ์ฑ„๋„ ์€ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋‚˜๋Š” ์ข‹์€ ์นœ๋ฉ”์ด๊ฐ€๋ฅด๋“œ๊ฐ€ ์—ฌ๊ธฐ์— ๊ด€๋ จ๋œ ๊ทผ๊ฑฐ๋ฅผ ์ดํ•ดํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๋Œ€๋ถ€๋ถ„์˜ ํ”Œ๋žซํผ API ํ˜ธ์ถœ์€ ๋น ๋ฅด๋ฉฐ ์ข…์ข… ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ด ๋” ํ•ฉ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค.
  • ํ”„๋ ˆ์ž„์›Œํฌ ๋ฉ”์„œ๋“œ ์žฌ์ •์˜์—์„œ "๋ฉ”์ธ ์Šค๋ ˆ๋“œ"๋กœ ๋Œ์•„๊ฐ€๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๋Š” ๊ฒƒ์€ Android Java์— ์ต์ˆ™ํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋ถ„๋ช…ํžˆ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

    • ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ ์ „์šฉ API๋ฅผ ์ฒ˜์Œ์œผ๋กœ ํ˜ธ์ถœํ•  ๋•Œ ๊ทธ ์ˆ˜๊ฐ€ ์–ผ๋งˆ๋‚˜ ๋Š˜์–ด๋‚ ์ง€ ์ƒ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ํ”Œ๋Ÿฌ๊ทธ์ธ ์ž‘์„ฑ์ž๋ฅผ ์œ„ํ•œ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ค‘์š”ํ•œ ์•ˆํ‹ฐ ํŒจํ„ด์„ ์—ด์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์–ธ๋œป๋ณด๊ธฐ์—๋Š” Firebase ml ํ”Œ๋Ÿฌ๊ทธ์ธ์กฐ์ฐจ๋„ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋ฌด๊ฑฐ์šด ๋ฌผ๊ฑด์„ ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๊ฐ•๋ ฅํ•œ ๊ฒฝ๊ณ ๊ฐ€ ์ฃผ์–ด์กŒ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€ ์ฑ„๋„ ํ˜ธ์ถœ์ด ๋ฐ˜ํ™˜๋˜๋Š” ๋ฐ ~20ms๋ณด๋‹ค ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฒฝ์šฐ ํ™”๋ฉด ์˜ค๋ฅ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ์˜ˆ์ œ ์•ฑ์˜ ๋ฌธ์ œ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†”์งํžˆ ๋งํ•ด์„œ, db ํ˜ธ์ถœ &c๋ฅผ ๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์„ ์„ค๋“ํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ด๋“ ๊ฐ„์—. ์Šค๋ ˆ๋“œ๋ฅผ ์ด๋ฏธ ๋ฐ›์œผ๋Ÿฌ ๊ฐ‘๋‹ˆ๋‹ค.

์•„, ๊ณต์งœ ์ ์‹ฌ์€ ์—†๋‹ค, ๊ทธ๊ฑด ํ™•์‹คํžˆ...

Java์™€ Swift๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„ค์ดํ‹ฐ๋ธŒ ํ”Œ๋žซํผ ์Šค๋ ˆ๋“œ๋กœ ๋ฌด๊ฑฐ์šด ์›Œํฌ๋กœ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

@AndruByrne ์ด๊ฒƒ์€ ์ฐธ์œผ๋กœ ๋งค์šฐ ํฅ๋ฏธ๋กœ์šด ์ •๋ณด์ด๋ฉฐ ์ง€๊ธˆ ๋Œ์ด์ผœ ๋ณด๋ฉด ๋ช…๋ฐฑํ•ด ๋ณด์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์•Œ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฌด๊ฑฐ์šด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•˜์—ฌ UI๊ฐ€ ์ž ๊ธด ๋‚ด ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๊ฐ€ ์ด๋ฏธ ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฒฝ๊ณ ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜๊ณ  ๋‚ด ํ”Œ๋Ÿฌ๊ทธ์ธ์— ๊ฒฝ๊ณ ๋ฅผ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

+1์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

๋ถˆํ–‰ํžˆ๋„ - Flutter๋Š” ๋งค์šฐ ๊ธฐ๋ณธ์ ์ด์ง€๋งŒ ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฒƒ์ด ๋ถ€์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ™ฉ๊ธˆ๊ธฐ๋ฅผ ๋งž์ดํ•  ์ค€๋น„๊ฐ€ ๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  Flutter ์•ฑ์ด ๊ฐ„๋‹จํ•œ async/await๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ฌด๊ฑฐ์šด ์ž‘์—…์„ ์œ„ํ•ด์„œ๋Š” ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์ˆ˜์ ์ด๋ฉฐ ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ์ฑ„๋„ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์—†๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๊ทธ๊ฒƒ๋“ค์„ ๋ฌด์˜๋ฏธํ•˜๊ณ  ์ค‘๋ณต๋˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. Xamarin์€ 1์ผ ์ฐจ๋ถ€ํ„ฐ ์ด๋ฅผ ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ํ™•์‹คํžˆ ์ด๊ฒƒ์ด ์†”๋ฃจ์…˜์— ๋Œ€ํ•ด ํˆฌํ‘œ๋ฅผ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

+1์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

+1

๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ๋„ ํ”Œ๋žซํผ ์ฑ„๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!

+1

+1

+1

+1 ์ด๊ฒƒ์€ ํ•„์ˆ˜ํ’ˆ์ž…๋‹ˆ๋‹ค

+1
ํ˜ธ์ถœํ•ด์•ผ ํ•˜๋Š” ๊ธฐ๋ณธ SDK๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. BackgroundFlutterMethodChannel ์™€ ๊ฐ™์€ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

+1

+1

_์ถฉ๋Œ์ด ์‹ฌํ•˜๊ฒŒ_ ์‹ค์ œ๋กœ ์„ค๋ช…ํ•˜๋Š” ๋‚ด์šฉ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์žˆ๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐœ๋… ์ฆ๋ช…์„ ์ž‘์—… ์ค‘์ด๋ฉฐ ๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ๋•Œ ๊ฐ์‹œ ์‹œ๊ฐ„ ์ดˆ๊ณผ(0x8badf00d) ๋ฐ ๊ธฐํƒ€ ์ด์ƒํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋œ ์ผ๋ถ€ ๋ฉ”์„œ๋“œ[๋ฐ ๊ฒฐ๊ณผ]๋กœ ์ธํ•ด ๋ฐœ์ƒํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์ •ํ™•ํ•œ ๋ฌธ์ œ๋ฅผ ์ •ํ™•ํžˆ ์ฐพ์•„๋‚ด๋Š” ๋ฐ ์ง„์ „์„ ์ด๋ฃจ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

+1

+1

+1

+1

+1์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

+1 ์ด๊ฒƒ๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค!

์ด ๋ฌธ์ œ๋Š” ์ ์–ด๋„ P2๋กœ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์ง€์ •๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
๋‚ด๊ฐ€ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋žซํผ ์ฑ„๋„์˜ ์šฉ๋„๋Š”

  • ํ”Œ๋žซํผ๋ณ„ API๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๋ฉด
  • ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ํ”Œ๋žซํผ๋ณ„ ๊ณผ์ค‘ํ•œ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ณ  ์™„๋ฃŒ๋˜๋ฉด ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์ฃผ์š” ์ฐจ๋‹จ๊ธฐ์ž…๋‹ˆ๋‹ค.

flutter_downloader ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๊ฒฉ๋ฆฌ ์ฝ”๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ณผ ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์ด ๋‹ค์Œ ๋ฒ„์ „์—์„œ ํ•ด๊ฒฐ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž์ง€๋งŒ ๋ฒ„๊ทธ๋Š” ์—ฌ์ „ํžˆ 1.12 ๋ฒ„์ „์— ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค!

์šฐ๋ฆฌ์˜ ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ๋Š” ์ฑ„๋„์˜ ๋ฐ˜๋Œ€ํŽธ์— ๋งŽ์ด ์žˆ์œผ๋ฉฐ kotlin์œผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ ์•ฑ์€ ๊ฐ ๋‹จ์ผ http ์—ฐ๊ฒฐ์— ๋Œ€ํ•ด ๊ฑฐ์˜ ๋ฉˆ์ท„์Šต๋‹ˆ๋‹ค.

ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹!!!!!!!!!!!!!!!!!?!?!?

์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์€ flutter_isolate ์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

+1 ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค ... ์–ด์„œ

+1

๋‚˜์—๊ฒŒ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” Dart์™€ ๊ธฐ๋ณธ ํ”Œ๋žซํผ ๊ฐ„์˜ ํ†ต์‹ ์ด ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋ฐœ์ƒํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์ž…๋‹ˆ๋‹ค. UI๊ฐ€ ์ง€์—ฐ๋˜๊ฑฐ๋‚˜ ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ์— ๋ฒˆ๊ฑฐ๋กœ์šด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ ๋Š” ์ƒ๋‹นํ•œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

+1์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค

ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ์— ์„ฑ๊ฐ€์‹  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

@lukaszciastko ํŽ˜์ด์ง€ ๋ฐ์ดํ„ฐ์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๋ฌด์—‡์„ ์˜๋ฏธํ•ฉ๋‹ˆ๊นŒ? ์ƒ๋‹นํ•œ ์–‘์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ์ง€์—ฐ๋˜๋Š” UI๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@YaredTaddese

ISOLATE๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์˜ ๋ณต์žก์„ฑ๊ณผ UI์™€ ISOLATE ๊ฐ„์˜ ์ƒํ˜ธ ํ†ต์‹ ์— ๋”ฐ๋ผ - ISOLATE๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ISOLATE๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜์—ฌ UI ์ฝ”๋“œ์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ Flutter ์•ฑ์— ํ’๋ถ€ํ•œ PDF ์ƒ์„ฑ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ƒ์„ฑํ•  ์—ฌ๋Ÿฌ PDF๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ์€ 1-10,000ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด UI๋Š” ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ๋ณด๊ณ ์„œ๋ฅผ ํ‘œ์‹œํ•˜๋Š” TAB๊ฐ€ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. - ์‚ฌ์šฉ์ž๋Š” TOAST๋ฅผ ํ†ตํ•ด ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ณ  UI๊ฐ€ ์ค‘๋‹จ๋˜์ง€ ์•Š์„ ๋•Œ ์•Œ๋ฆผ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. - ์‚ฌ์šฉ์ž๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์„œ๋น„์Šค๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ’๋ถ€ํ•œ PDF ์ƒ์„ฑ.

์ฐธ๊ณ ๋กœ ๋‚ด PDF ์ƒ์„ฑ์€ ISOLATE์ž…๋‹ˆ๋‹ค. ISOLATE์—์„œ๋Š” CLOUD FIRESTORE์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  PDF์— ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๊ฒƒ์ด ์›ํ™œํ•˜๊ฒŒ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

@MsXam ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ๋ณ„ ๊ธฐ๋Šฅ์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค... ์ด๋กœ ์ธํ•ด ์ฃผ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ๋ณ„ ๊ธฐ๋Šฅ์„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค... ์ด๋กœ ์ธํ•ด UI๊ฐ€ ์ง€์—ฐ๋ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@YaredTaddese

ISOLATE๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์˜ ๋ณต์žก์„ฑ๊ณผ UI์™€ ISOLATE ๊ฐ„์˜ ์ƒํ˜ธ ํ†ต์‹ ์— ๋”ฐ๋ผ - ISOLATE๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „์— ISOLATE๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•˜์—ฌ UI ์ฝ”๋“œ์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ Flutter ์•ฑ์— ํ’๋ถ€ํ•œ PDF ์ƒ์„ฑ ๊ธฐ๋Šฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ƒ์„ฑํ•  ์—ฌ๋Ÿฌ PDF๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ์€ 1-10,000ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด UI๋Š” ๋ฐ˜์‘ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ๋ณด๊ณ ์„œ๋ฅผ ํ‘œ์‹œํ•˜๋Š” TAB๊ฐ€ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. - ์‚ฌ์šฉ์ž๋Š” TOAST๋ฅผ ํ†ตํ•ด ์ž‘์—…์ด ์™„๋ฃŒ๋˜๊ณ  UI๊ฐ€ ์ค‘๋‹จ๋˜์ง€ ์•Š์„ ๋•Œ ์•Œ๋ฆผ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. - ์‚ฌ์šฉ์ž๋Š” ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์„œ๋น„์Šค๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ํ’๋ถ€ํ•œ PDF ์ƒ์„ฑ.

์ฐธ๊ณ ๋กœ ๋‚ด PDF ์ƒ์„ฑ์€ ISOLATE์ž…๋‹ˆ๋‹ค. ISOLATE์—์„œ๋Š” CLOUD FIRESTORE์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  PDF์— ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๊ฒƒ์ด ์›ํ™œํ•˜๊ฒŒ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.

ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ์ฑ„๋„์„ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? UI ์Šค๋ ˆ๋“œ์—์„œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ ค๋Š” ์•„์ด๋””์–ด๋ฅผ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐ™์€ ๊ฒƒ์— ๋ถ™์–ด์žˆ๋‹ค.

kotlin ์ฝ”๋“œ์™€ getStream.io API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ methodchannel์„ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์ง€๋งŒ ์†๋„๊ฐ€ ๋„ˆ๋ฌด ๋Š๋ฆฌ๊ณ  Flutter UI๊ฐ€ ์ •์ง€๋˜์–ด ์—ฌ๊ธฐ์— ์ปดํ“จํŒ…์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์—ˆ์ง€๋งŒ ๋™์ผํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋‚˜์š”?

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

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์‘๋‹ต์˜ ์–‘์ด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด๊ฒƒ์€ ์ฃผ์š” ๋ฌธ์ œ์ด๋ฉฐ Flutter ์•ฑ์˜ ์ปจํ…์ŠคํŠธ์—์„œ ๊ฒฉ๋ฆฌ์˜ ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๊ฑฐ์˜ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

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

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์‘๋‹ต์˜ ์–‘์ด ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ด๊ฒƒ์€ ์ฃผ์š” ๋ฌธ์ œ์ด๋ฉฐ Flutter ์•ฑ์˜ ์ปจํ…์ŠคํŠธ์—์„œ ๊ฒฉ๋ฆฌ์˜ ์ฃผ์š” ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๊ฑฐ์˜ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ์ด๊ฒƒ์€ ํฐ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ตœ๋Œ€ํ•œ ๋นจ๋ฆฌ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” 10์ผ ๋™์•ˆ ํ”Œ๋Ÿฌํ„ฐ๋ฅผ ๋ฐฐ์› ๊ณ  ์ง€๊ธˆ๊นŒ์ง€ ๊ทธ๊ฒƒ์„ ์‚ฌ๋ž‘ํ•˜์ง€๋งŒ ์ž ์‹œ ์‹คํ—˜ํ•œ ํ›„์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  ๋‹จ์ ์„ ๋ณด๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” 2018๋…„ 1์›” 5์ผ๋ถ€ํ„ฐ ์—ด๋ ธ์Šต๋‹ˆ๋‹ค.

์ด ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค.

๊ณง ์ง€์›ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@jpsarda , @klaszlo8207 ์ˆจ ์ฐธ์ง€ ๋งˆ์„ธ์š”. ๊ทธ๋ฆฌ๊ณ  ์˜ˆ, ์˜ค๋Š˜๊นŒ์ง€ ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค: https://pub.dev/packages/isolate_handler. ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” Flutter์˜ ์ตœ๊ทผ ๋ณ€๊ฒฝ(๋ช‡ ์ผ ์ „)์œผ๋กœ ์ธํ•ด ๋” ์ด์ƒ ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋Š˜ ํ”Œ๋Ÿฌ๊ทธ๋ฅผ ๋ฝ‘์•„์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์˜๋ฏธํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ์•ฑ์—์„œ๋Š” ๊ทธ๋ ‡๊ฒŒ ๋ณด์ผ ์ˆ˜ ์žˆ๊ณ  ๋ชจ์–‘์ด ์ค‘์š”ํ•˜์ง€๋งŒ ํ”Œ๋žซํผ ์ฝ”๋“œ๋Š” ์–ด์จŒ๋“  ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ ๊ฒฉ๋ฆฌ์—์„œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋กœ ๊ธด ์ž‘์—…์„ ๋‹ค์‹œ ์œ„์ž„ํ•ด๋„ ์‹ค์ œ๋กœ ์•„๋ฌด ๊ฒƒ๋„ ๋‹ฌ์„ฑํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์ค‘ ์Šค๋ ˆ๋”ฉ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋‹คํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@spiderion Async๋Š” ๋‹ค๋ฅธ ๋งŽ์€ ํ”Œ๋žซํผ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ์˜๋„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ €๋ฅผ ์˜คํ•ดํ•˜์ง€ ๋งˆ์„ธ์š”. ํ”Œ๋žซํผ ์ฑ„๋„ ์ œํ•œ์ด ํฐ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๋ง์€ ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด (๋‚ด ์•ฑ์€ ์–ด์ œ๊นŒ์ง€ ์–ธ๊ธ‰ํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๊ณ  ์žˆ์—ˆ๊ณ  ์ด์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ•จ) async/ await๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์— ๊ด€ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

@zoechi ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ๊ณ„ํš์ด ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@spiderion ๊ทธ๋“ค์€ ๊ทธ๊ฒƒ์„ ์‹ค์ œ๋กœ ๊ณ ์น  ์ˆ˜ ์—†์œผ๋ฉฐ ๊ฒฉ๋ฆฌ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ๋’ค์— UI ์—”์ง„์ด ์—†์œผ๋ฏ€๋กœ ํ”Œ๋žซํผ ์ฑ„๋„ ํ†ต์‹ ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋„์›€์ด ๋˜๋Š” ๋‘ ๊ฐ€์ง€ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • https://pub.dev/packages/flutter_isolate ๋Š” ์ž์ฒด UI ์ง€์›์„ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์ฒด ๊ฒฉ๋ฆฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(๊ธฐ์ˆ ์ ์œผ๋กœ๋งŒ ๋ณด๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์—†์Œ).

  • https://pub.dev/packages/isolate_handler ๋Š” ์ตœ๊ทผ Flutter ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด ์ด์ „ ๋ฐฉ์‹์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์˜ ํŒจํ‚ค์ง€์— ์˜์กดํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. flutter_isolate ์ž์ฒด๊ฐ€ ์•„๋‹Œ ์ด ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์ด์ ์€ ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๊ณ  ์—ฌ๋Ÿฌ ๊ฒฉ๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ์ถ”์ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฒฉ๋ฆฌ์™€ ๊ธฐ๋ณธ ํ†ต์‹ ์„ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ(์›๋ž˜ ์Šคํ†ก Isolate ๋ฐ FlutterIsolate ๋ชจ๋‘ ์ˆ˜๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…)๋Š” ์ถ”์ƒํ™”๋˜๊ณ  ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‘ ๋ฒˆ์งธ๋ฅผ ์™„๋ฒฝํ•œ ์„ฑ๊ณต์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ๋‚˜๋Š” ๊ฝค ์˜ค๋žซ๋™์•ˆ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•ด ์™”์œผ๋ฉฐ Flutter์˜ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์™”์„ ๋•Œ ๋‚ด ์•ฑ๋„ ๋ง๊ฐ€์กŒ๋‹ค๋Š” ์ด์œ ๋กœ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ƒˆ๋กœ์šด ์†”๋ฃจ์…˜์œผ๋กœ ๋„˜์–ด๊ฐ€๋„๋ก ๋„์™”์Šต๋‹ˆ๋‹ค. :-)

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

์•ˆ๋…•ํ•˜์„ธ์š” @deakjahn ๋น ๋ฅธ ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๊ท€ํ•˜๊ฐ€ ์ œ๊ณตํ•œ ์†”๋ฃจ์…˜์€ ๋งค์šฐ ์œ ์šฉํ•ด ๋ณด์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์ด ๋‚ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ์•ฑ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ Instagram๊ณผ ์œ ์‚ฌํ•œ ์ด์•ผ๊ธฐ๋ฅผ ๋งŒ๋“œ๋Š” ์ƒํ™ฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์•ฑ์€ ์—…๋กœ๋“œํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ๋งค์šฐ ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋™์˜์ƒ ๋ฐ ํŒŒ์ผ ๋ชฉ๋ก(์—ฐ๊ฒฐ์ด ๋Š๋ฆฐ ๊ฒฝ์šฐ ์•ฝ 15๋ถ„)์„ Firebase ์ €์žฅ์†Œ์— ์—…๋กœ๋“œํ•ด์•ผ ํ•˜๋ฉฐ, ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋œ ํ›„ ์•ฑ์—์„œ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Firebase ํด๋ผ์šฐ๋“œ, Firestore์— ์žˆ๋Š” ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋งŒ๋‚œ ๋ฌธ์ œ๋Š” ํŒŒ์ผ์ด ์—…๋กœ๋“œ๋˜๋Š” ๋™์•ˆ ์‚ฌ์šฉ์ž๊ฐ€ ์•ฑ์„ ์ข…๋ฃŒํ•˜๋ฉด ์ „์ฒด ์ž‘์—…์ด ์™„์ „ํžˆ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์‹ค์ œ๋กœ ๊ฒฉ๋ฆฌ์˜ ์ฑ…์ž„์ด ์•„๋‹ˆ๋ผ ์ง€์‹œํ•œ ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ง์ ‘ ์‚ฌ์šฉํ•œ ์ ์€ ์—†์ง€๋งŒ Firebase๋Š” ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜ ์žˆ๋Š” ํ•œ ์ค‘์ง€๋œ ์–ธ๋กœ๋“œ๋ฅผ ์žฌ๊ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

getBatteryLevel ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
https://flutter.dev/docs/development/platform-integration/platform-channels?tab=android-channel-java-tab
Android ๊ธฐ๊ธฐ์—์„œ ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฐ๊ฐ€ ๋„์™€์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๋กœ๊ทธ๊ฐ€ ์—†๊ณ  ๋ฌดํ•œ ๋ฃจํ”„์—์„œ ๊ณ„์† ์‹คํ–‰๋˜๊ณ  ์ •ํ™•ํžˆ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์กฐ์ฐจ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— P5 ๋ ˆ์ด๋ธ” ์ง€์ • ??? ๐Ÿฅต

์ด์ „ ๋Œ“๊ธ€์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”. ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฉ๋ฆฌ์—๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋ณ€๊ฒฝ๋  ๊ฐ€๋Šฅ์„ฑ์€ ๋งค์šฐ ๋‚ฎ ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์–ผ๋งˆ๋‚˜ ํž˜๋“ ์ง€ ์•„๋‹Œ์ง€. ๊ทธ๋“ค์€ ๋‹จ์ง€ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”๋กœ ํ•˜๋ฉด Flutter์—์„œ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค...

๊ตฌํ˜„์— ์ œํ•œ์ด ์žˆ์œผ๋ฉฐ ์ด ๊ธฐ๋Šฅ์„ ๊ธฐ์กด ๊ฒฉ๋ฆฌ์— ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ API๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Œ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด๊ฒƒ์ด P5๋ณด๋‹ค ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์•„์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ๊ท€ํ•˜์˜ ์˜๊ฒฌ์„ ๋ชจ๋‘ ์ฝ๊ณ  ๊ท€ํ•˜๊ฐ€ ๋งŒ๋“  ํŒจํ‚ค์ง€๋ฅผ ํ™๋ณดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๋‚๋‹ˆ๋‹ค.

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

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

@deakjahn ์ด ํŒ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. isolate_handler๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ ์ธก์—์„œ ์•Œ๋ฆผ์„ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๋‹คํŠธ ์ธก์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐ ๋„์›€์ด ๋ ๊นŒ์š”? (์ €๋Š” twilio ๊ธฐ๋ณธ SDK๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๊ธฐ๋ณธ ์ธก์—์„œ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค)

์ด๊ฒƒ์ด ํ”Œ๋žซํผ ์ฑ„๋„์„ ํ†ตํ•ด ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” patform ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค๋ฉด ์˜ˆ, ๋‘ ํŒจํ‚ค์ง€ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ์ฝ”๋“œ์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒฝ์šฐ ์ด๋Ÿฌํ•œ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฉ๋ฆฌ์—์„œ๋„ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

@deakjahn ๋น ๋ฅธ ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๋‚ด ๋ฌธ์ œ๋Š” ์ผ๋ฐ˜ ํ”Œ๋žซํผ ์ฑ„๋„๋กœ ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ twilio sdk๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์•„๋‹Œ ๋ณ„๋„์˜ ๊ฒฉ๋ฆฌ์—์„œ ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹ ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋‚ด ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‘ ํŒจํ‚ค์ง€ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•Œ๋ฆผ์„ ๋ฐ›์„ ๋•Œ๋งˆ๋‹ค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ž‘๋™ํ•˜๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. (๊ฐ€๋Šฅํ•˜์ง€ ์•Š๋‹ค๋ฉด ๊ธฐ๋ณธ ์•ฑ์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค)

๋‚˜๋Š” Twilio๊ฐ€ ๋ฌด์—‡์ธ์ง€์กฐ์ฐจ ์•Œ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— (OK, ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ดค์Œ :-)), ๊ทธ๋ž˜์„œ ๋‚˜๋Š” ์ •๋ง๋กœ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์–ด์จŒ๋“  ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šคํ•˜๋ ค๋ฉด ํ”Œ๋žซํผ ์ฑ„๋„ ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด Twilio๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์ง์ ‘ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค(์ด ๊ฒฝ์šฐ ๊ฑฐ์˜ ๋™์ผํ•œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋งŒ๋“ค๊ณ  ๊ฒŒ์‹œํ•˜์ง€ ์•Š๊ณ  ๋กœ์ปฌ์—์„œ ์ฐธ์กฐ). ๋˜๋Š” ๋‹จ์ˆœํžˆ ๊ด€๋ จ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์ž์‹ ์˜ ์•ฑ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(์™ธ๋ถ€ ์ข…์†์„ฑ์€ ์•„๋‹ˆ์ง€๋งŒ ๊ทธ ์™ธ์—๋Š” ์‹ค์ œ๋กœ ๋™์ผํ•œ ์ฝ”๋“œ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค).

๊ทธ๋ฆฌ๊ณ  ํ”Œ๋žซํผ ์ฑ„๋„์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ด์ „ ๋‹ต๋ณ€์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜ Flutter ์•ฑ์˜ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ํ”Œ๋žซํผ ์ฑ„๋„๊ณผ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ด๋ฏธ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฉ๋ฆฌ์—์„œ ๋™์ผํ•œ ๊ฒƒ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ํŒจํ‚ค์ง€.

๋”ฐ๋ผ์„œ ์ด ๋ฌธ์ œ๋Š” 2018๋…„ 1์›” 5์ผ๋ถ€ํ„ฐ ์กด์žฌํ•˜๋ฉฐ ์ถ”๊ฐ€ ๋…ธ๋ ฅ์œผ๋กœ ์—ฌ์ „ํžˆ ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ œ๊ณต๋œ ์†”๋ฃจ์…˜์€ ํ›Œ๋ฅญํ•˜์ง€๋งŒ ๋ฐ์Šคํฌํƒ‘์—์„œ๋Š” ์•„์ง ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ์Šคํฌํƒ‘์—์„œ Flutter๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ž˜ ์ž‘๋™ํ•˜๋Š”์ง€ ์‹œํ—˜ํ•ด๋ณด๊ณ  ๋ฏธ๋ž˜ ์ œํ’ˆ์— ๋Œ€ํ•œ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์€ ์—ฌ๊ธฐ์—์„œ ์™„์ „ํžˆ ๋ง‰ํžˆ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ฑฐ์˜ ๋ชจ๋“  ์•ฑ์— ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํ•ญ์ƒ ์—„์ฒญ๋‚œ ๊ณ„์‚ฐ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ค‘์š”ํ•œ Api ์„ค๊ณ„ ๊ฒฐํ•จ์— ๋Œ€ํ•ด ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๊ฐ€๋Šฅํ•œ๊ฐ€์š”?

๋‚ด ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ ๊ฒฝ๊ณ  ์ฐฝ ์— ์ด์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ•์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

์†”๋ฃจ์…˜์€ ์—ฌ๊ธฐ์— ์–ธ๊ธ‰ ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
์ œ๊ณต๋œ ์˜ˆ์ œ๋Š” ์‹œ์Šคํ…œ ๊ฒฝ๊ณ  ์ฐฝ ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ๊ด€๋ จ์ด ์žˆ์ง€๋งŒ ๋‹ค๋ฅธ ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ๋„ ์‰ฝ๊ฒŒ ๋ณต์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์„ ์ž‘๋™์‹œํ‚ค๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๋ฉ‹์ง„ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ๋ฌด์—‡์ด๋“  ํ•˜๋ ค๋ฉด ์•ฑ ๋ฒ”์œ„์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฑ๊ทธ๋ผ์šด๋“œ/ํฌ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ง์ ‘ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•ฑ์ด ์‹คํ–‰๋˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋ฉด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ์•„๋ฌด ๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์˜ˆ๋ฅผ ๋“ค์–ด ์•ฑ์ด ๋‹ซํž ๋•Œ FCM ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ backgroundMessageHandler์—์„œ ๊ณต์œ  ๊ธฐ๋ณธ ์„ค์ •์œผ๋กœ ๋ฌด์—‡์ด๋“  ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ MissingPluginException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋˜๋Š” ์‹œ์Šคํ…œ ๊ฒฝ๊ณ  ์ฐฝ์œผ๋กœ ์•ฑ์„ ์—ด์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒฝ์šฐ. ๊ฒฝ๊ณ  ์ฐฝ์ด ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•ฑ ๋ฒ”์œ„ ๋‚ด์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•ฑ์ด ํ˜„์žฌ ๋‹ซํ˜€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์ด ํฐ ๋ฌธ์ œ์ธ ๋‹ค๋ฅธ ๋งŽ์€ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@michael-ottink ์„ค๋ช…ํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” ์ •ํ™•ํžˆ ๋ฌธ์ œ๊ฐ€ ์—†์–ด์•ผ ํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค์ž…๋‹ˆ๋‹ค. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ž์ฒด ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด FlutterEngine์„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๊ณ  ๊ทธ ์•ˆ์—์„œ ์‹คํ–‰๋˜๋Š” ๊ฒฉ๋ฆฌ๋Š” ํ”Œ๋žซํผ ์ฑ„๋„์„ ํ†ตํ•ด ํ•ด๋‹น ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ์ง์ ‘ ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ง๋ถ™์—ฌ์„œ, ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ํ•ด๋‹น ๊ฒฉ๋ฆฌ๋ฅผ FlutterEngine์— ๋ž˜ํ•‘ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ•ด๋‹น ๊ถŒํ•œ์„ ๋งˆ์ˆ ์ฒ˜๋Ÿผ ์ƒ์†๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Android ๋ฐ iOS์—์„œ flutter_isolate ํŒจํ‚ค์ง€๊ฐ€ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค(ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•๋ณด๋‹ค ์ ์ ˆํ•œ ์ˆ˜์ •์„ ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚ซ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์—๋Š” ๋ณ‘๋ชฉ ํ˜„์ƒ, ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ์ œ๋Œ€๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๊ฑฐ๋‚˜ ์ง€์›์ด ๋ถ€์กฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ”Œ๋žซํผ.)

@ryanheise so flutter_isolate ์ €ํ•œํ…Œ ๋งž๋‚˜์š”? ๋ฌธ์„œ์—์„œ ์–ด๋–ป๊ฒŒ ๋งํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. FCM onBackgroundMessage์—์„œ ์ž‘๋™ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ž˜์„œ ๋‚ด onBackgroundMessageHandler์—์„œ ์ƒˆ ๊ฒฉ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ํ•˜์ง€๋งŒ ๊ฑฐ๊ธฐ์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ flutter_isolate๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ?

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

๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋„์›€์ด ์ ˆ์‹คํžˆ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๋‚ด์ผ ๋‚˜์˜ ์ฒซ ๋ฒˆ์งธ ์ง„์ง€ํ•œ ๊ฑฐ๋ž˜๊ฐ€ ์žˆ๊ณ  ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ดํ•ดํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋กœ๋“œ๋˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๋ฉ”์‹œ์ง€๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ README์˜ ์ง€์นจ์„ ๋”ฐ๋ž๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ FlutterNativeView ์ดˆ๊ธฐํ™”์— ์—ฐ๊ฒฐํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • Application ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ์•Š์œผ๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉด ํ”„๋กœ์ ํŠธ๋ฅผ ์ด์ „ v1 ์Šคํƒ€์ผ ํ”Œ๋Ÿฌ๊ทธ์ธ ์•„ํ‚คํ…์ฒ˜๋กœ ๋‹ค์šด๊ทธ๋ ˆ์ด๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(v2๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์ค‘๋‹จ๋  ์œ„ํ—˜์ด ์žˆ์Œ).

๋‚ด Application.k๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

import `in`.jvapps.system_alert_window.SystemAlertWindowPlugin
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService

import android.os.Build
import android.app.NotificationManager
import android.app.NotificationChannel

public class Application: FlutterApplication(), PluginRegistrantCallback {

   override fun onCreate() {
     super.onCreate()
     FlutterFirebaseMessagingService.setPluginRegistrant(this)
     createNotificationChannels()
     SystemAlertWindowPlugin.setPluginRegistrant(this)
   }

   override fun registerWith(registry: PluginRegistry) {
     FirebaseCloudMessagingPluginRegistrant.registerWith(registry)
     SystemAlertWindowPlugin.registerWith(registry.registrarFor("in.jvapps.system_alert_window"))
   }

   fun createNotificationChannels() {
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = "groupChannel"
        val descriptionText = "This is the group channel"
        val importance = NotificationManager.IMPORTANCE_HIGH
        val mChannel = NotificationChannel("59054", name, importance)
        mChannel.description = descriptionText
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(mChannel)
    }
  }
}

์ด ๋ฌธ์ œ์™€ ๊ด€๋ จ์ด ์—†์œผ๋ฏ€๋กœ firebase_messaging ๋ฌธ์ œ ํŽ˜์ด์ง€์— ๊ฒŒ์‹œํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

'SchedulerBinding'์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด 'spawnIsolate' ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” PR์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํ”Œ๋žซํผ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

import 'dart:async';
import 'dart:isolate';

import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:path_provider/path_provider.dart';

Future<void> _test(SendPort sendPort) async {
  final dir = await getTemporaryDirectory();
  sendPort.send(dir);
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final Completer<Object> completer = Completer<Object>();
  final RawReceivePort receivePort = RawReceivePort(completer.complete);

  final Isolate isolate = await ServicesBinding.instance.spawnIsolate(
    _test,
    receivePort.sendPort,
  );

  print(await completer.future);

  receivePort.close();
  isolate.kill();
}

ํ†ต๋‚˜๋ฌด

Performing hot restart...
Syncing files to device Pixel 4...
Restarted application in 722ms.
I/flutter (11705): Directory: '/data/user/0/com.example.bug/cache'

'SchedulerBinding'์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด 'spawnIsolate' ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š” PR์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด ๊ฒฉ๋ฆฌ์—์„œ ํ”Œ๋žซํผ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํ”Œ๋žซํผ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

SchedulerBinding.instance.spawnIsolate

์ด๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•  ๊ธฐํšŒ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด ์š”๊ตฌ ์‚ฌํ•ญ์— ๋งž๋Š” ๊ฒฝ์šฐ ๋“ฑ ..

@๋‚˜์ผ๋ฆญ
์ด ํŒŒ์ผ์„ ๊ต์ฒดํ•˜์‹ญ์‹œ์˜ค(๋ฒ„์ „ 1.17.5์˜ ๊ฒฝ์šฐ ์‹ค์ œ).


๋ฐ”์ธ๋”ฉ.๋‹คํŠธ

```dart// Copyright 2014 The Flutter Authors. ํŒ๊ถŒ ์†Œ์œ .
// ์ด ์†Œ์Šค ์ฝ”๋“œ์˜ ์‚ฌ์šฉ์€ BSD ์Šคํƒ€์ผ ๋ผ์ด์„ ์Šค์˜ ์ ์šฉ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
// LICENSE ํŒŒ์ผ์—์„œ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.

๊ฐ€์ ธ์˜ค๊ธฐ ' ๋‹คํŠธ:๋น„๋™๊ธฐ ';
๊ฐ€์ ธ์˜ค๊ธฐ ' ๋‹คํŠธ:๋ถ„๋ฆฌ ';
๊ฐ€์ ธ์˜ค๊ธฐ ' ๋‹คํŠธ:typed_data ';
' dart:ui '๋ฅผ ui๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

๊ฐ€์ ธ์˜ค๊ธฐ ' ํŒจํ‚ค์ง€:flutter/foundation.dart ';

import 'asset_bundle.dart';
import 'binary_messenger.dart';
'system_channels.dart' ๊ฐ€์ ธ์˜ค๊ธฐ;

/// ํ”Œ๋žซํผ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  [defaultBinaryMessenger]๋กœ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
///
/// [ServicesBinding]์€ ๋˜ํ•œ ๋…ธ์ถœํ•˜๋Š” [LicenseEntryCollector]๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.
/// ์ž์‚ฐ์˜ ๋ฃจํŠธ์— ์ €์žฅ๋œ LICENSE ํŒŒ์ผ์—์„œ ์ฐพ์€ ๋ผ์ด์„ ์Šค
/// ๋ฒˆ๋“ค๋กœ ์ œ๊ณต๋˜๊ณ  ext.flutter.evict ์„œ๋น„์Šค ํ™•์žฅ์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค(์ฐธ์กฐ
/// [ํ‡ด๊ฑฐ]).
BindingBase์˜ ๋ฏน์Šค์ธ ServicesBinding {
@์šฐ์„ธํ•˜๋‹ค
๋ฌดํšจ initInstances() {
super.initInstances();
_instance = ์ด๊ฒƒ;
_defaultBinaryMessenger = createBinaryMessenger();
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
์ดˆ๊ธฐํ™” ๋ผ์ด์„ ์Šค();
SystemChannels.system.setMessageHandler(handleSystemMessage);
}

/// ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ ํ˜„์žฌ [ServicesBinding]์ž…๋‹ˆ๋‹ค.
์ •์  ServicesBinding get ์ธ์Šคํ„ด์Šค => _instance;
์ •์  ์„œ๋น„์Šค ๋ฐ”์ธ๋”ฉ _instance;

/// [BinaryMessenger]์˜ ๊ธฐ๋ณธ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค.
///
/// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ”Œ๋žซํผ์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ,
/// ๊ฐ ์ฑ„๋„์— ๋“ฑ๋ก๋œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”์ ํ•˜๋ฏ€๋กœ
/// ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๋“ฑ๋ก๋œ ํ•ธ๋“ค๋Ÿฌ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger;
BinaryMessenger _defaultBinaryMessenger;

/// ์ „์†ก์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ [BinaryMessenger] ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
/// ํ”Œ๋žซํผ ๋ฉ”์‹œ์ง€.
@๋ณดํ˜ธ
BinaryMessenger createBinaryMessenger() {
๋ฐ˜ํ™˜ const _DefaultBinaryMessenger._();
}

/// [SystemChannels.system]์—์„œ ์ˆ˜์‹ ๋œ ๋ฉ”์‹œ์ง€์— ๋Œ€ํ•ด ํ˜ธ์ถœ๋œ ํ•ธ๋“ค๋Ÿฌ
/// ๋ฉ”์‹œ์ง€ ์ฑ„๋„.
///
/// ๋‹ค๋ฅธ ๋ฐ”์ธ๋”ฉ์€ ๋“ค์–ด์˜ค๋Š” ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์— ์‘๋‹ตํ•˜๊ธฐ ์œ„ํ•ด ์ด๊ฒƒ์„ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
@๋ณดํ˜ธ
@mustCallSuper
๋ฏธ๋ž˜ํ•ธ๋“ค ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€(๊ฐ์ฒด ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€) ๋น„๋™๊ธฐ { }

/// [LicenseRegistry]์— ๊ด€๋ จ ๋ผ์ด์„ ์Šค๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
///
/// ๊ธฐ๋ณธ์ ์œผ๋กœ [ServicesBinding]์˜ [initLicenses] ๊ตฌํ˜„์€ ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
/// ์ปดํŒŒ์ผํ•˜๋Š” ๋™์•ˆ flutter ๋„๊ตฌ์—์„œ ์ˆ˜์ง‘ํ•œ ๋ชจ๋“  ๋ผ์ด์„ ์Šค.
@๋ณดํ˜ธ
@mustCallSuper
๋ฌดํšจ initLicenses() {
LicenseRegistry.addLicense(_addLicenses);
}

๊ฐœ์šธ_addLicenses() ๋น„๋™๊ธฐ* {
// ์—ฌ๊ธฐ์—์„œ ํƒ€์ด๋จธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(์Šค์ผ€์ค„๋Ÿฌ ๋ฐ”์ธ๋”ฉ์˜ scheduleTask ๋Œ€์‹ ).
// ์„œ๋น„์Šค ๊ณ„์ธต์€ ์Šค์ผ€์ค„๋Ÿฌ ๋ฐ”์ธ๋”ฉ(์Šค์ผ€์ค„๋Ÿฌ
// ๋ฐ”์ธ๋”ฉ์€ ์„œ๋น„์Šค ๊ณ„์ธต์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํƒ€์ด๋จธ
// ์ด๋Š” ์–ด์จŒ๋“  scheduleTask๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์ฐจ์ด์ ์€
// ์ด๊ฒƒ๋“ค์€ ์ƒ๋Œ€์ ์œผ๋กœ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ์ง€์ •๋˜๋Š” ๋Œ€์‹  ๋‹ค์Œ์—๋งŒ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
// ์‹คํ–‰ ์ค‘์ผ ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ์ž‘์—…. ์—ฌ๊ธฐ์—์„œ _๋ฌด์–ธ๊ฐ€_๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘๋‹จ
// isolates๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
// ํ˜„์žฌ ๋ฐ์ดํ„ฐ์ด๊ณ  ๋™์ผํ•œ ์ด๋ฒคํŠธ ๋ฃจํ”„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๊ฒฝ์šฐ
// ๋‹ค์Œ ๊ฒฉ๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋•Œ ๋ฐ˜๋ณต, ์šฐ๋ฆฌ๋Š” ํ™•์‹คํžˆ
// ํ”„๋ ˆ์ž„์„ ๋†“์น˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์€ ๋ชจ๋“  ์ž‘์—…์„
// ํ•˜๋‚˜์˜ ๊ฒฉ๋ฆฌ์—์„œ ๋ฐœ์ƒํ•˜๊ณ  ๊ฒฐ๊ตญ ๊ฑฐ๊ธฐ์— ๊ฐˆ ์ˆ˜ ์žˆ์ง€๋งŒ ๋จผ์ €
// ๊ฒฉ๋ฆฌ ํ†ต์‹ ์„ ๋” ์ €๋ ดํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
// ์ฐธ์กฐ: https://github.com/dart-lang/sdk/issues/31959
// https://github.com/dart-lang/sdk/issues/31960
// TODO(ianh): ์ด๋Ÿฌํ•œ ๋ฒ„๊ทธ๊ฐ€ ์ˆ˜์ •๋˜๋ฉด ์ด ๋ณต์žก์„ฑ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
์ตœ์ข… ์™„์„ฑ์žrawLicenses = ์™„์„ฑ์ž();
Timer.run(() ๋น„๋™๊ธฐ {
rawLicenses.complete(rootBundle.loadString('LICENSE', ์บ์‹œ: false));
});
rawLicenses.future๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
์ตœ์ข… ์™„์„ฑ์ž> parsedLicenses = ์™„์„ฑ์ž>();
Timer.run(() ๋น„๋™๊ธฐ {
parsedLicenses.complete(compute(_parseLicenses, rawLicenses.future ๋Œ€๊ธฐ, debugLabel: 'parseLicenses'));
});
parsedLicenses.future๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
yield* ์ŠคํŠธ๋ฆผ.fromIterable(parsedLicenses.future๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค);
}

// ์ด๊ฒƒ์€ ์œ„์˜ _addLicenses์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
์ •์  ๋ชฉ๋ก_parseLicenses(๋ฌธ์ž์—ด rawLicenses) {
์ตœ์ข… ๋ฌธ์ž์—ด _licenseSeparator = '\n' + ('-' * 80) + '\n';
์ตœ์ข… ๋ชฉ๋ก๊ฒฐ๊ณผ =[];
์ตœ์ข… ๋ชฉ๋ก๋ผ์ด์„ ์Šค = rawLicenses.split(_licenseSeparator);
for (๋ผ์ด์„ผ์Šค์˜ ์ตœ์ข… ๋ฌธ์ž์—ด ๋ผ์ด์„ ์Šค) {
์ตœ์ข… ์ •์ˆ˜ ๋ถ„ํ•  = license.indexOf('\n\n');
if (๋ถ„ํ•  >= 0) {
result.add(LicenseEntryWithLineBreaks(
license.substring(0, split).split('\n'),
license.substring(๋ถ„ํ•  + 2),
));
} ๋˜ ๋‹ค๋ฅธ {
result.add(LicenseEntryWithLineBreaks(const[], ๋ผ์ด์„ ์Šค));
}
}
๋ฐ˜ํ™˜ ๊ฒฐ๊ณผ;
}

@์šฐ์„ธํ•˜๋‹ค
๋ฌดํšจ initServiceExtensions() {
super.initServiceExtensions();

assert(() {
  registerStringServiceExtension(
    // ext.flutter.evict value=foo.png will cause foo.png to be evicted from
    // the rootBundle cache and cause the entire image cache to be cleared.
    // This is used by hot reload mode to clear out the cache of resources
    // that have changed.
    name: 'evict',
    getter: () async => '',
    setter: (String value) async {
      evict(value);
    },
  );
  return true;
}());

}

/// ext.flutter.evict ์„œ๋น„์Šค ํ™•์žฅ์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.
///
/// ์ด๊ฒƒ์€ ํ•ซ ๋ฆฌ๋กœ๋“œ ๋™์•ˆ flutter ๋„๊ตฌ์—์„œ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ชจ๋“  ์ด๋ฏธ์ง€๊ฐ€
/// ๋””์Šคํฌ์—์„œ ๋ณ€๊ฒฝ๋œ ์‚ฌํ•ญ์€ ์บ์‹œ์—์„œ ์ง€์›Œ์ง‘๋‹ˆ๋‹ค.
@๋ณดํ˜ธ
@mustCallSuper
๋ฌดํšจ ์ถ•์ถœ(๋ฌธ์ž์—ด ์ž์‚ฐ) {
rootBundle.evict(์ž์‚ฐ);
}

๋ฏธ๋ž˜์Šคํฐ ๊ฒฉ๋ฆฌ(
๋ฏธ๋ž˜๋˜๋Š”entryPoint(T ๋ฉ”์‹œ์ง€),
T ๋ฉ”์‹œ์ง€, {
๋ถ€์šธ ์ผ์‹œ ์ค‘์ง€ = ๊ฑฐ์ง“,
๋ถ€์šธ ์˜ค๋ฅ˜๊ฐ€ ์น˜๋ช…์ ์ด๊ณ ,
์„ผ๋“œํฌํŠธ ์˜จ์—‘์‹œํŠธ,
SendPort ์˜ค๋ฅ˜,
๋ฌธ์ž์—ด ๋””๋ฒ„๊ทธ ์ด๋ฆ„,
}) {
์ฃผ์žฅํ•˜๋‹ค(
_isMainIsolate,
'์—ฌ๋Ÿฌ ์ˆ˜์ค€์˜ ๋ถ„๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†์Œ',
);

final RawReceivePort messageReceiver = RawReceivePort(
  (Object receivedMessage) async {
    if (receivedMessage is SendPort) {
      receivedMessage.send(
        _IsolateStarter<T>(
          ui.PluginUtilities.getCallbackHandle(entryPoint),
          message,
        ),
      );
    } else if (receivedMessage is _Message) {
      final ByteData result = await defaultBinaryMessenger.send(
        receivedMessage.channel,
        receivedMessage.message,
      );
      receivedMessage.sendPort.send(result);
    }
  },
);
RawReceivePort onExitReceiver;
onExitReceiver = RawReceivePort(
  (Object message) {
    onExit?.send(message);

    onExitReceiver.close();
    messageReceiver.close();
  },
);

return Isolate.spawn(
  _startIsolate,
  messageReceiver.sendPort,
  paused: paused,
  errorsAreFatal: true,
  onExit: onExitReceiver.sendPort,
  onError: onError,
  debugName: debugName,
);

}
}

๋ฏธ๋ž˜_start๊ฒฉ๋ฆฌ(SendPort sendPort) ๋น„๋™๊ธฐ {
_sendPortToMainIsolate = sendPort;
_IsolateBinding();

์ตœ์ข… ์™„์„ฑ์ž<_IsolateStarter> ์™„์„ฑ์ž =
์™„์„ฑ์ž<_IsolateStarter>();

์ตœ์ข… RawReceivePort ์ˆ˜์‹  ํฌํŠธ = RawReceivePort(
(๊ฐ์ฒด ๊ฒฉ๋ฆฌ ์‹œ์ž‘) {
assert(isolateStarter๋Š” _IsolateStarter์ž…๋‹ˆ๋‹ค.);
completer.complete(isolateStarter๋ฅผ _IsolateStarter๋กœ);
},
);

sendPort.send(receivePort.sendPort);

์ตœ์ข… _IsolateStarterisolateStarter = completer.future๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

์ˆ˜์‹ ํฌํŠธ.๋‹ซ๊ธฐ();

์ตœ์ข… ๊ธฐ๋Šฅ ํ•จ์ˆ˜ =
UI.PluginUtilities.getCallbackFromHandle(isolateStarter.callbackHandle);

ํ•จ์ˆ˜(isolateStarter.message)๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
}

SendPort _sendPortToMainIsolate;

bool get _isMainIsolate => _sendPortToMainIsolate == null;

ํด๋ž˜์Šค _IsolateStarter{
_IsolateStarter(this.callbackHandle, this.message);

์ตœ์ข… ui.CallbackHandle callbackHandle;
์ตœ์ข… T ๋ฉ”์‹œ์ง€;
}

ํด๋ž˜์Šค _๋ฉ”์‹œ์ง€ {
_๋ฉ”์„ธ์ง€(
this.์ฑ„๋„,
์ด ๋ฉ”์‹œ์ง€,
this.sendPort,
);

์ตœ์ข… ๋ฌธ์ž์—ด ์ฑ„๋„;
์ตœ์ข… ByteData ๋ฉ”์‹œ์ง€;
์ตœ์ข… SendPort sendPort;
}

ํด๋ž˜์Šค _IsolateBinding์€ ServicesBinding {}์œผ๋กœ BindingBase๋ฅผ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

/// [BinaryMessenger]์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„.
///
/// ์ด ๋ฉ”์‹ ์ €๋Š” ์•ฑ ์ธก์—์„œ ํ”Œ๋žซํผ ์ธก์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ 
/// ํ”Œ๋žซํผ ์ธก์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ ์ ˆํ•œ
/// ํ•ธ๋“ค๋Ÿฌ.
ํด๋ž˜์Šค _DefaultBinaryMessenger๋Š” BinaryMessenger๋ฅผ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค. {
const _DefaultBinaryMessenger._();

// ํ”Œ๋žซํผ ํ”Œ๋Ÿฌ๊ทธ์ธ์—์„œ ๋“ค์–ด์˜ค๋Š” ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ธฐ.
// ์ด๊ฒƒ์€ ์ด ํด๋ž˜์Šค๊ฐ€ const ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ์ •์ ์ž…๋‹ˆ๋‹ค.
์ •์  ์ตœ์ข… ์ง€๋„_ํ•ธ๋“ค๋Ÿฌ =
{};

// ๋‚˜๊ฐ€๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ€๋กœ์ฑ„์„œ ์‘๋‹ตํ•˜๋Š” ๋ชจ์˜ ํ•ธ๋“ค๋Ÿฌ.
// ์ด๊ฒƒ์€ ์ด ํด๋ž˜์Šค๊ฐ€ const ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ์ •์ ์ž…๋‹ˆ๋‹ค.
์ •์  ์ตœ์ข… ์ง€๋„_mockHandlers =
{};

๋ฏธ๋ž˜_sendPlatformMessage(๋ฌธ์ž์—ด ์ฑ„๋„, ByteData ๋ฉ”์‹œ์ง€) {
์ตœ์ข… ์™„์„ฑ์ž์™„์„ฑ์ž = ์™„์„ฑ์ž();

if (_isMainIsolate) {
  // ui.window is accessed directly instead of using ServicesBinding.instance.window
  // because this method might be invoked before any binding is initialized.
  // This issue was reported in #27541. It is not ideal to statically access
  // ui.window because the Window may be dependency injected elsewhere with
  // a different instance. However, static access at this location seems to be
  // the least bad option.
  ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
    try {
      completer.complete(reply);
    } catch (exception, stack) {
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'services library',
        context:
            ErrorDescription('during a platform message response callback'),
      ));
    }
  });
} else {
  RawReceivePort receivePort;
  receivePort = RawReceivePort(
    (Object message) async {
      assert(message is ByteData);
      completer.complete(message as ByteData);
      receivePort.close();
    },
  );
  _sendPortToMainIsolate.send(
    _Message(channel, message, receivePort.sendPort),
  );
}

return completer.future;

}

@์šฐ์„ธํ•˜๋‹ค
๋ฏธ๋ž˜ํ•ธ๋“คํ”Œ๋žซํผ๋ฉ”์‹œ์ง€(
์ŠคํŠธ๋ง ์ฑ„๋„,
๋ฐ”์ดํŠธ๋ฐ์ดํ„ฐ ๋ฐ์ดํ„ฐ,
ui.PlatformMessageResponseCallback ์ฝœ๋ฐฑ,
) ๋น„๋™๊ธฐ {
ByteData ์‘๋‹ต;
๋…ธ๋ ฅํ•˜๋‹ค {
์ตœ์ข… MessageHandler ํ•ธ๋“ค๋Ÿฌ = _handlers[์ฑ„๋„];
if (ํ•ธ๋“ค๋Ÿฌ != null) {
์‘๋‹ต = ํ•ธ๋“ค๋Ÿฌ(๋ฐ์ดํ„ฐ)๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
} ๋˜ ๋‹ค๋ฅธ {
ui.channelBuffers.push(์ฑ„๋„, ๋ฐ์ดํ„ฐ, ์ฝœ๋ฐฑ);
์ฝœ๋ฐฑ = null;
}
} catch(์˜ˆ์™ธ, ์Šคํƒ) {
FlutterError.reportError(FlutterErrorDetails(
์˜ˆ์™ธ: ์˜ˆ์™ธ,
์Šคํƒ: ์Šคํƒ,
๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ: '์„œ๋น„์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ',
์ปจํ…์ŠคํŠธ: ErrorDescription('ํ”Œ๋žซํผ ๋ฉ”์‹œ์ง€ ์ฝœ๋ฐฑ ์ค‘'),
));
} ๋งˆ์ง€๋ง‰์œผ๋กœ {
if (์ฝœ๋ฐฑ != null) {
์ฝœ๋ฐฑ(์‘๋‹ต);
}
}
}

@์šฐ์„ธํ•˜๋‹ค
๋ฏธ๋ž˜send(๋ฌธ์ž์—ด ์ฑ„๋„, ByteData ๋ฉ”์‹œ์ง€) {
์ตœ์ข… MessageHandler ํ•ธ๋“ค๋Ÿฌ = _mockHandlers[์ฑ„๋„];
if (ํ•ธ๋“ค๋Ÿฌ != null)
๋ฆฌํ„ด ํ•ธ๋“ค๋Ÿฌ(๋ฉ”์‹œ์ง€);
return _sendPlatformMessage(์ฑ„๋„, ๋ฉ”์‹œ์ง€);
}

@์šฐ์„ธํ•˜๋‹ค
๋ฌดํšจ setMessageHandler(๋ฌธ์ž์—ด ์ฑ„๋„, MessageHandler ํ•ธ๋“ค๋Ÿฌ) {
if (ํ•ธ๋“ค๋Ÿฌ == null)
_handlers.remove(์ฑ„๋„);
๋˜ ๋‹ค๋ฅธ
_handlers[์ฑ„๋„] = ํ•ธ๋“ค๋Ÿฌ;
ui.channelBuffers.drain(์ฑ„๋„, (ByteData ๋ฐ์ดํ„ฐ, ui.PlatformMessageResponseCallback ์ฝœ๋ฐฑ) ๋น„๋™๊ธฐ {
handlePlatformMessage(์ฑ„๋„, ๋ฐ์ดํ„ฐ, ์ฝœ๋ฐฑ)๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.
});
}

@์šฐ์„ธํ•˜๋‹ค
๋ฌดํšจ setMockMessageHandler(๋ฌธ์ž์—ด ์ฑ„๋„, MessageHandler ํ•ธ๋“ค๋Ÿฌ) {
if (ํ•ธ๋“ค๋Ÿฌ == null)
_mockHandlers.remove(์ฑ„๋„);
๋˜ ๋‹ค๋ฅธ
_mockHandlers[์ฑ„๋„] = ํ•ธ๋“ค๋Ÿฌ;
}
}
```

๋‚˜๋Š” flutter 1.21์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์ปดํŒŒ์ผํ•˜๋ ค๊ณ  ํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด์ œ _IsolateBinding์ด BindingBase ๋ฉ”์„œ๋“œ์˜ ๊ตฌํ˜„์„ ๋งŽ์ด ๋ˆ„๋ฝํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ ๋ฌธ์ œ๊ฐ€ ๋‚จ์•˜์Šต๋‹ˆ๋‹ค...

๋‚˜๋Š” ์ข‹์•„ํ•œ๋‹ค

Error: The non-abstract class '_IsolateBinding' is missing implementations for these members:
 - BindingBase with ServicesBinding.SchedulerBinding.addPersistentFrameCallback

์•ฝ 30ํšŒ.

๋งˆ์ง€๋ง‰์— ์ฝ˜์†”์ด ์ธ์‡„ํ•ฉ๋‹ˆ๋‹ค.

/C:/flutter/packages/flutter/lib/src/services/binding.dart:341:7: Error: 'BindingBase' doesn't implement 'SchedulerBinding' so it can't be used with 'ServicesBinding'.
 - 'BindingBase' is from 'package:flutter/src/foundation/binding.dart' ('/C:/flutter/packages/flutter/lib/src/foundation/binding.dart').
 - 'SchedulerBinding' is from 'package:flutter/src/scheduler/binding.dart' ('/C:/flutter/packages/flutter/lib/src/scheduler/binding.dart').
 - 'ServicesBinding' is from 'package:flutter/src/services/binding.dart' ('/C:/flutter/packages/flutter/lib/src/services/binding.dart').
class _IsolateBinding extends BindingBase with ServicesBinding {}

_startIsolate ์˜ _IsolateBinding() ํ˜ธ์ถœ์ด ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ 100% ํ™•์‹ ํ•  ์ˆ˜ ์—†์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ ์•„์ง ๋ฏน์Šค์ธ์— ๋Œ€ํ•œ ์ง€์‹์ด ๊ทธ๋ฆฌ ์ข‹์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?


์ƒˆ ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์ง€๊ธˆ๊นŒ์ง€).

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// <strong i="24">@dart</strong> = 2.8

import 'dart:async';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';

import 'asset_bundle.dart';
import 'binary_messenger.dart';
import 'restoration.dart';
import 'system_channels.dart';

/// Listens for platform messages and directs them to the [defaultBinaryMessenger].
///
/// The [ServicesBinding] also registers a [LicenseEntryCollector] that exposes
/// the licenses found in the `LICENSE` file stored at the root of the asset
/// bundle, and implements the `ext.flutter.evict` service extension (see
/// [evict]).
mixin ServicesBinding on BindingBase, SchedulerBinding {
  <strong i="25">@override</strong>
  void initInstances() {
    super.initInstances();
    _instance = this;
    _defaultBinaryMessenger = createBinaryMessenger();
    _restorationManager = createRestorationManager();
    window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
    initLicenses();
    SystemChannels.system.setMessageHandler(handleSystemMessage);
    SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
    readInitialLifecycleStateFromNativeWindow();
  }

  /// The current [ServicesBinding], if one has been created.
  static ServicesBinding get instance => _instance;
  static ServicesBinding _instance;

  /// The default instance of [BinaryMessenger].
  ///
  /// This is used to send messages from the application to the platform, and
  /// keeps track of which handlers have been registered on each channel so
  /// it may dispatch incoming messages to the registered handler.
  BinaryMessenger get defaultBinaryMessenger => _defaultBinaryMessenger;
  BinaryMessenger _defaultBinaryMessenger;

  /// Creates a default [BinaryMessenger] instance that can be used for sending
  /// platform messages.
  <strong i="26">@protected</strong>
  BinaryMessenger createBinaryMessenger() {
    return const _DefaultBinaryMessenger._();
  }

  /// Called when the operating system notifies the application of a memory
  /// pressure situation.
  ///
  /// This method exposes the `memoryPressure` notification from
  /// [SystemChannels.system].
  <strong i="27">@protected</strong>
  <strong i="28">@mustCallSuper</strong>
  void handleMemoryPressure() { }

  /// Handler called for messages received on the [SystemChannels.system]
  /// message channel.
  ///
  /// Other bindings may override this to respond to incoming system messages.
  <strong i="29">@protected</strong>
  <strong i="30">@mustCallSuper</strong>
  Future<void> handleSystemMessage(Object systemMessage) async {
    final Map<String, dynamic> message = systemMessage as Map<String, dynamic>;
    final String type = message['type'] as String;
    switch (type) {
      case 'memoryPressure':
        handleMemoryPressure();
        break;
    }
    return;
  }

  /// Adds relevant licenses to the [LicenseRegistry].
  ///
  /// By default, the [ServicesBinding]'s implementation of [initLicenses] adds
  /// all the licenses collected by the `flutter` tool during compilation.
  <strong i="31">@protected</strong>
  <strong i="32">@mustCallSuper</strong>
  void initLicenses() {
    LicenseRegistry.addLicense(_addLicenses);
  }

  Stream<LicenseEntry> _addLicenses() async* {
    // We use timers here (rather than scheduleTask from the scheduler binding)
    // because the services layer can't use the scheduler binding (the scheduler
    // binding uses the services layer to manage its lifecycle events). Timers
    // are what scheduleTask uses under the hood anyway. The only difference is
    // that these will just run next, instead of being prioritized relative to
    // the other tasks that might be running. Using _something_ here to break
    // this into two parts is important because isolates take a while to copy
    // data at the moment, and if we receive the data in the same event loop
    // iteration as we send the data to the next isolate, we are definitely
    // going to miss frames. Another solution would be to have the work all
    // happen in one isolate, and we may go there eventually, but first we are
    // going to see if isolate communication can be made cheaper.
    // See: https://github.com/dart-lang/sdk/issues/31959
    //      https://github.com/dart-lang/sdk/issues/31960
    // TODO(ianh): Remove this complexity once these bugs are fixed.
    final Completer<String> rawLicenses = Completer<String>();
    scheduleTask(() async {
      rawLicenses.complete(await rootBundle.loadString('NOTICES', cache: false));
    }, Priority.animation);
    await rawLicenses.future;
    final Completer<List<LicenseEntry>> parsedLicenses = Completer<List<LicenseEntry>>();
    scheduleTask(() async {
      parsedLicenses.complete(compute(_parseLicenses, await rawLicenses.future, debugLabel: 'parseLicenses'));
    }, Priority.animation);
    await parsedLicenses.future;
    yield* Stream<LicenseEntry>.fromIterable(await parsedLicenses.future);
  }

  // This is run in another isolate created by _addLicenses above.
  static List<LicenseEntry> _parseLicenses(String rawLicenses) {
    final String _licenseSeparator = '\n' + ('-' * 80) + '\n';
    final List<LicenseEntry> result = <LicenseEntry>[];
    final List<String> licenses = rawLicenses.split(_licenseSeparator);
    for (final String license in licenses) {
      final int split = license.indexOf('\n\n');
      if (split >= 0) {
        result.add(LicenseEntryWithLineBreaks(
          license.substring(0, split).split('\n'),
          license.substring(split + 2),
        ));
      } else {
        result.add(LicenseEntryWithLineBreaks(const <String>[], license));
      }
    }
    return result;
  }

  <strong i="33">@override</strong>
  void initServiceExtensions() {
    super.initServiceExtensions();

    assert(() {
      registerStringServiceExtension(
        // ext.flutter.evict value=foo.png will cause foo.png to be evicted from
        // the rootBundle cache and cause the entire image cache to be cleared.
        // This is used by hot reload mode to clear out the cache of resources
        // that have changed.
        name: 'evict',
        getter: () async => '',
        setter: (String value) async {
          evict(value);
        },
      );
      return true;
    }());
  }

  /// Called in response to the `ext.flutter.evict` service extension.
  ///
  /// This is used by the `flutter` tool during hot reload so that any images
  /// that have changed on disk get cleared from caches.
  <strong i="34">@protected</strong>
  <strong i="35">@mustCallSuper</strong>
  void evict(String asset) {
    rootBundle.evict(asset);
  }

  Future<Isolate> spawnIsolate<T>(
      FutureOr<void> entryPoint(T message),
      T message, {
        bool paused = false,
        bool errorsAreFatal,
        SendPort onExit,
        SendPort onError,
        String debugName,
      }) {
    assert(
    _isMainIsolate,
    'Can\'t make multiple levels of isolates',
    );

    final RawReceivePort messageReceiver = RawReceivePort(
          (Object receivedMessage) async {
        if (receivedMessage is SendPort) {
          receivedMessage.send(
            _IsolateStarter<T>(
              ui.PluginUtilities.getCallbackHandle(entryPoint),
              message,
            ),
          );
        } else if (receivedMessage is _Message) {
          final ByteData result = await defaultBinaryMessenger.send(
            receivedMessage.channel,
            receivedMessage.message,
          );
          receivedMessage.sendPort.send(result);
        }
      },
    );
    RawReceivePort onExitReceiver;
    onExitReceiver = RawReceivePort(
          (Object message) {
        onExit?.send(message);

        onExitReceiver.close();
        messageReceiver.close();
      },
    );

    return Isolate.spawn(
      _startIsolate,
      messageReceiver.sendPort,
      paused: paused,
      errorsAreFatal: true,
      onExit: onExitReceiver.sendPort,
      onError: onError,
      debugName: debugName,
    );
  }



  // App life cycle

  /// Initializes the [lifecycleState] with the [Window.initialLifecycleState]
  /// from the window.
  ///
  /// Once the [lifecycleState] is populated through any means (including this
  /// method), this method will do nothing. This is because the
  /// [Window.initialLifecycleState] may already be stale and it no longer makes
  /// sense to use the initial state at dart vm startup as the current state
  /// anymore.
  ///
  /// The latest state should be obtained by subscribing to
  /// [WidgetsBindingObserver.didChangeAppLifecycleState].
  <strong i="36">@protected</strong>
  void readInitialLifecycleStateFromNativeWindow() {
    if (lifecycleState != null) {
      return;
    }
    final AppLifecycleState state = _parseAppLifecycleMessage(window.initialLifecycleState);
    if (state != null) {
      handleAppLifecycleStateChanged(state);
    }
  }

  Future<String> _handleLifecycleMessage(String message) async {
    handleAppLifecycleStateChanged(_parseAppLifecycleMessage(message));
    return null;
  }

  static AppLifecycleState _parseAppLifecycleMessage(String message) {
    switch (message) {
      case 'AppLifecycleState.paused':
        return AppLifecycleState.paused;
      case 'AppLifecycleState.resumed':
        return AppLifecycleState.resumed;
      case 'AppLifecycleState.inactive':
        return AppLifecycleState.inactive;
      case 'AppLifecycleState.detached':
        return AppLifecycleState.detached;
    }
    return null;
  }

  /// The [RestorationManager] synchronizes the restoration data between
  /// engine and framework.
  ///
  /// See the docs for [RestorationManager] for a discussion of restoration
  /// state and how it is organized in Flutter.
  ///
  /// To use a different [RestorationManager] subclasses can override
  /// [createRestorationManager], which is called to create the instance
  /// returned by this getter.
  RestorationManager get restorationManager => _restorationManager;
  RestorationManager _restorationManager;

  /// Creates the [RestorationManager] instance available via
  /// [restorationManager].
  ///
  /// Can be overriden in subclasses to create a different [RestorationManager].
  <strong i="37">@protected</strong>
  RestorationManager createRestorationManager() {
    return RestorationManager();
  }
}

Future<void> _startIsolate<T>(SendPort sendPort) async {
  _sendPortToMainIsolate = sendPort;
  _IsolateBinding();

  final Completer<_IsolateStarter<T>> completer =
  Completer<_IsolateStarter<T>>();

  final RawReceivePort receivePort = RawReceivePort(
        (Object isolateStarter) {
      assert(isolateStarter is _IsolateStarter<T>);
      completer.complete(isolateStarter as _IsolateStarter<T>);
    },
  );

  sendPort.send(receivePort.sendPort);

  final _IsolateStarter<T> isolateStarter = await completer.future;

  receivePort.close();

  final Function function =
  ui.PluginUtilities.getCallbackFromHandle(isolateStarter.callbackHandle);

  await function(isolateStarter.message);
}

SendPort _sendPortToMainIsolate;

bool get _isMainIsolate => _sendPortToMainIsolate == null;

class _IsolateStarter<T> {
  _IsolateStarter(this.callbackHandle, this.message);

  final ui.CallbackHandle callbackHandle;
  final T message;
}

class _Message {
  _Message(
      this.channel,
      this.message,
      this.sendPort,
      );

  final String channel;
  final ByteData message;
  final SendPort sendPort;
}

//TODO not working
class _IsolateBinding extends BindingBase with ServicesBinding {}

/// The default implementation of [BinaryMessenger].
///
/// This messenger sends messages from the app-side to the platform-side and
/// dispatches incoming messages from the platform-side to the appropriate
/// handler.
class _DefaultBinaryMessenger extends BinaryMessenger {
  const _DefaultBinaryMessenger._();

  // Handlers for incoming messages from platform plugins.
  // This is static so that this class can have a const constructor.
  static final Map<String, MessageHandler> _handlers =
  <String, MessageHandler>{};

  // Mock handlers that intercept and respond to outgoing messages.
  // This is static so that this class can have a const constructor.
  static final Map<String, MessageHandler> _mockHandlers =
  <String, MessageHandler>{};

  Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
    final Completer<ByteData> completer = Completer<ByteData>();

    if (_isMainIsolate) {
      // ui.window is accessed directly instead of using ServicesBinding.instance.window
      // because this method might be invoked before any binding is initialized.
      // This issue was reported in #27541. It is not ideal to statically access
      // ui.window because the Window may be dependency injected elsewhere with
      // a different instance. However, static access at this location seems to be
      // the least bad option.
      ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
        try {
          completer.complete(reply);
        } catch (exception, stack) {
          FlutterError.reportError(FlutterErrorDetails(
            exception: exception,
            stack: stack,
            library: 'services library',
            context:
            ErrorDescription('during a platform message response callback'),
          ));
        }
      });
    } else {
      RawReceivePort receivePort;
      receivePort = RawReceivePort(
            (Object message) async {
          assert(message is ByteData);
          completer.complete(message as ByteData);
          receivePort.close();
        },
      );
      _sendPortToMainIsolate.send(
        _Message(channel, message, receivePort.sendPort),
      );
    }

    return completer.future;
  }

  <strong i="38">@override</strong>
  Future<void> handlePlatformMessage(
      String channel,
      ByteData data,
      ui.PlatformMessageResponseCallback callback,
      ) async {
    ByteData response;
    try {
      final MessageHandler handler = _handlers[channel];
      if (handler != null) {
        response = await handler(data);
      } else {
        ui.channelBuffers.push(channel, data, callback);
        callback = null;
      }
    } catch (exception, stack) {
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'services library',
        context: ErrorDescription('during a platform message callback'),
      ));
    } finally {
      if (callback != null) {
        callback(response);
      }
    }
  }

  <strong i="39">@override</strong>
  Future<ByteData> send(String channel, ByteData message) {
    final MessageHandler handler = _mockHandlers[channel];
    if (handler != null)
      return handler(message);
    return _sendPlatformMessage(channel, message);
  }

  <strong i="40">@override</strong>
  void setMessageHandler(String channel, MessageHandler handler) {
    if (handler == null)
      _handlers.remove(channel);
    else
      _handlers[channel] = handler;
    ui.channelBuffers.drain(channel, (ByteData data, ui.PlatformMessageResponseCallback callback) async {
      await handlePlatformMessage(channel, data, callback);
    });
  }

  <strong i="41">@override</strong>
  void setMockMessageHandler(String channel, MessageHandler handler) {
    if (handler == null)
      _mockHandlers.remove(channel);
    else
      _mockHandlers[channel] = handler;
  }

  <strong i="42">@override</strong>
  bool checkMessageHandler(String channel, MessageHandler handler) => _handlers[channel] == handler;

  <strong i="43">@override</strong>
  bool checkMockMessageHandler(String channel, MessageHandler handler) => _mockHandlers[channel] == handler;
}

@๋‚˜์ผ๋ฆญ
ํ˜„์žฌ๋กœ์„œ๋Š” flutter๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์™œ flutter ํŒ€์—์„œ ๊ตฌํ˜„ํ•œ ๋‹ค๋ฅธ flutter ๋„๊ตฌ(์˜ˆ: devtools)๊ฐ€ ์ด ์ฐจ๋‹จ๊ธฐ๋ฅผ ์น˜์ง€ ์•Š์•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋“ค์€ ๊ทธ๋“ค์— ์˜ํ•ด ์ฐจ๋‹จ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์‹ฌ๊ฐํ•œ ์ƒˆ ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ ํ”„๋ ˆ์ž„์›Œํฌ ์ฐจ๋‹จ๊ธฐ์ž…๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ https://github.com/flutter/flutter/issues/18761#issuecomment -639248761์— ๋”ฐ๋ฅด๋ฉด P3์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์™œ flutter ํŒ€์—์„œ ๊ตฌํ˜„ํ•œ ๋‹ค๋ฅธ flutter ๋„๊ตฌ(์˜ˆ: devtools)๊ฐ€ ์ด ์ฐจ๋‹จ๊ธฐ๋ฅผ ์น˜์ง€ ์•Š์•˜๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋“ค์€ ๊ทธ๋“ค์— ์˜ํ•ด ์ฐจ๋‹จ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

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

+1 ์ค‘ ์ผ๋ถ€๊ฐ€ ๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ž˜ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. (์˜ˆ: https://github.com/flutter/flutter/issues/13937#issuecomment-635683123 ). Imo ๋ฐฑ๊ทธ๋ผ์šด๋“œ ๊ฒฉ๋ฆฌ ๋ฐ ํ—ค๋“œ๋ฆฌ์Šค ๋Ÿฐํƒ€์ž„(๋ฐ ๊ด€๋ฆฌ ๋ฐฉ๋ฒ•)์— ๋Œ€ํ•œ ๊ณต์‹ ๋ฌธ์„œ๋Š” ์—ฌ์ „ํžˆ ์•ฝ๊ฐ„ ๋ถ€์กฑํ•˜๊ณ  Firebase ๋ฉ”์‹œ์ง• ํ•ญ๋ชฉ์€ ์•…๋ชฝ์ด์ง€๋งŒ ํ”„๋ ˆ์ž„์›Œํฌ, ์—”์ง„๊ณผ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค ๐Ÿคทโ€โ™‚๏ธ

๊ทธ๋ƒฅ ํ”Œ๋Ÿฌํ„ฐ ํŒ€ ์š•์ข€ ๊ทธ๋งŒํ•˜๊ณ , ๋†€๋ผ์šด ์ง„์ „์ด ์žˆ๊ณ , ์ด๊ฑด ๋Œ์ดํ‚ฌ ์ˆ˜ ์—†๋Š” ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค... ๊ทธ๋ฆฌ๊ณ  PR์ด ์žˆ๋‹ค๋ฉด ํ”Œ๋Ÿฌํ„ฐ ํŒ€์ด ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ์ถœํ•˜๋Š” ๊ฒƒ์ด ์–ด๋–จ๊นŒ์š” ๐Ÿค”

๊ฒฉ๋ฆฌ์— ๋Œ€ํ•ด ์ด ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

๋ฉ”์ธ ์•„์ด์†”๋ ˆ์ดํŠธ์™€ ์—”์ง„์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฒฉ๋ฆฌ์— ํ•„์š”ํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์—”์ง„์— ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
์—”์ง„์— ํ•„์š”ํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ๊ฒฉ๋ฆฌ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ์˜ ์ƒํ™ฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.
2๊ฐœ์˜ ๊ฒฉ๋ฆฌ ์žฅ์น˜์™€ ์—”์ง„์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๊ฒฉ๋ฆฌ์— ํ•„์š”ํ•œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์—”์ง„์— ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
์—”์ง„์— ๋ฌด์–ธ๊ฐ€๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?
๋‘˜ ๋‹ค ๋ฌผ์–ด? ๊ทธ๋Ÿฌ๋ฉด ๋ˆ„๊ตฌ์˜ ๋Œ€๋‹ต์„ ์ทจํ•ด์•ผ ํ• ๊นŒ์š”?
์•„๋‹ˆ๋ฉด ํ•˜๋‚˜์˜ ๋ถ„๋ฆฌ๋ฌผ๋งŒ ์š”์ฒญํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๊ทธ๋Ÿผ ์–ด๋Š ์ชฝ?

@hpoul ์—ฌ๊ธฐ์— ์žˆ๋Š” ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด Android/ios ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ดˆ๋ณด์ž์ด๊ณ  ์•ฑ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์ฒซ ๋ฒˆ์งธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์„ ํƒํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์„ ๊นจ๋‹ซ๊ณ  ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜ํ•ด ์ฐจ๋‹จ๋˜๊ณ  ๊ฐ•์ œ๋กœ ๋ณต์žกํ•œ "ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•"์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ด๋Ÿฌํ•œ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ์— ๋Œ€ํ•œ ์˜ˆ๋ฅผ ํ†ตํ•ด ๊ณต์‹ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๋‚˜ stackoverflow ๋˜๋Š” ๋‹ค๋ฅธ ๋ธ”๋กœ๊ทธ์˜ ์ฃผ์„์— ์ž˜ ์„ค๋ช…๋œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋””์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์•ผ ํ• ๊นŒ์š”? ์ด๊ฒƒ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ตฌํ˜„ํ–ˆ๊ฑฐ๋‚˜ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ๋Š” ์ผ๋ถ€ ํŒจํ‚ค์ง€๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ•ญ๋ชฉ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

Android์™€ ios ๋ชจ๋‘ ์—์„œ ์„œ๋น„์Šค, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ž‘์—… ๋Œ€๊ธฐ์—ด ๋“ฑ์œผ๋กœ ์ž‘์—…ํ•œ ๊ฒฝํ—˜์ด ๋งŽ๊ณ  ์ด ๋ฌธ์ œ๋ฅผ ์‰ฝ๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์€ flutter์˜ ๋Œ€์ƒ ์ธ๊ตฌ ํ†ต๊ณ„๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฌธ์ œ์—๋Š” ์ž˜๋ชป๋œ +1์ด ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฌธ์ œ ์šฐ์„  ์ˆœ์œ„์˜ ์ˆœ์„œ๋ฅผ ํฌ๊ฒŒ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ด ๋ฌธ์ œ๋Š” ์—ฌ์ „ํžˆ ๋งจ ์œ„์— ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” @phanirithvij

flutter_isolate๋Š” ์œ„์— ๋งํฌ๋˜์—ˆ์œผ๋ฉฐ 2019๋…„ 2์›”๋ถ€ํ„ฐ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋ณต์žกํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•ด ๋ณด์ด๋Š” README๋ฅผ ๋ณต์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

FlutterIsolate๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ”Œ๋Ÿฌํ„ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ”Œ๋Ÿฌํ„ฐ์—์„œ ๊ฒฉ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”Œ๋žซํผ ์ฑ„๋„์ด ๊ฒฉ๋ฆฌ ๋‚ด์—์„œ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•„์š”ํ•œ ํ”Œ๋žซํผ๋ณ„ ๋น„ํŠธ(Android์˜ FlutterBackgroundView ๋ฐ iOS์˜ FlutterEngine)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

| | ์•ˆ๋“œ๋กœ์ด๋“œ | iOS | ์„ค๋ช… |
| :-------------------- | :----------------: | :--------------------------------: | :-------------------------------- |
| FlutterIsolate.spawn(entryPoint, ๋ฉ”์‹œ์ง€) | :white_check_mark: | :white_check_mark: | ์ƒˆ๋กœ์šด FlutterIsolate ์ƒ์„ฑ |
| flutterIsolate.pause() | :white_check_mark: | :white_check_mark: | ์‹คํ–‰ ์ค‘์ธ ๊ฒฉ๋ฆฌ๋ฅผ ์ผ์‹œ ์ค‘์ง€ |
| flutterIsolate.resume() | :white_check_mark: | :white_check_mark: | ์ผ์‹œ ์ค‘์ง€ isoalte ์žฌ๊ฐœ |
| flutterIsolate.kill() | :white_check_mark: | :white_check_mark: | ๊ฒฉ๋ฆฌ๋ฅผ ์ฃฝ์ธ๋‹ค |

์ด ๋ฉ”์„œ๋“œ๋Š” "์›๋ž˜" Isolate ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ์™€ ์ด๋ฆ„์ด ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ณต์‹ ๋ฌธ์„œ์—์„œ ๊ฒฉ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๋ฉด ์‚ฌ์šฉ๋ฒ•์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ ์–ด๋„ ์œ„์— ๋‚˜์—ด๋œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋“œ๋กญ ์ธ ๋Œ€์ฒด์ž…๋‹ˆ๋‹ค.

(์ฐธ๊ณ : ์ € ์—ญ์‹œ ์ด์ „ ์˜๊ฒฌ์—์„œ ์ด๋ฏธ ์–ธ๊ธ‰ํ•œ ์ด์œ ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ๊ณต์‹์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ์ผ๋ถ€๋Š” ์—ฌ๋Ÿฌ๋ถ„๊ณผ ๊ณต์œ ํ•˜์ง€๋งŒ ์ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ "๋ณต์žกํ•จ"์ด๋ผ๊ณ  ๋ถ€๋ฅด์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.)

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

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

@ryanheise

flutter_isolate๋Š” ๊ฐ ๊ฒฉ๋ฆฌ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์—”์ง„์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €๋Š” Flutter ํŒ€๋„ ๊ทธ ์ผ์„ ๋” ์ž˜ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

Flutter ํŒ€์ด ์ด๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋งํ•˜์ง€๋งŒ ์–ด๋–ป๊ฒŒ?
์œ„์—์„œ ์งˆ๋ฌธํ•œ ๋‚ด์šฉ์€ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.
์†”๋ฃจ์…˜์ด ์ƒˆ ์—”์ง„์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋ผ๋ฉด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

(์ฐธ๊ณ ๋กœ flutter_isolate๋Š” ๋‚ด ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์•„๋‹ˆ์ง€๋งŒ ์ด ๊ธฐ๋Šฅ๋„ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.)

"๋” ๋‚˜์€ ์ž‘์—…"์ด ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ๊ณผ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด FlutterEngine์˜ ๋ชจ๋“  ๊ธฐ๊ณ„๋ฅผ ๊ฐ€๋™ํ•  ํ•„์š”๋Š” ์—†์ง€๋งŒ ํ˜„์žฌ ํ•„์š”ํ•œ ์ธํ”„๋ผ๊ฐ€ ๋ชจ๋‘ ์—”์ง„์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ํ˜„์žฌ flutter_isolate๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ์ „์ฒด ์—”์ง„์„ ๊ฐ€๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

(์ฐธ๊ณ ๋กœ flutter_isolate๋Š” ๋‚ด ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์•„๋‹ˆ์ง€๋งŒ ์ด ๊ธฐ๋Šฅ๋„ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.)

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ํฌํฌ์ธ ์ค„ ๋ชฐ๋ž์Šต๋‹ˆ๋‹ค.

flutter_isolate๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ์ „์ฒด ์—”์ง„์„ ๊ฐ€๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

'is_background_view = true'๋กœ ์ง€์ •ํ•˜๋ฉด ์—”์ง„์ด ๋ Œ๋”๋ง์„ ์‹œ์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์—”์ง„์ด ์™„์ „ํžˆ ์‹œ์ž‘๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ—ค๋“œ๋ฆฌ์Šค ์‹คํ–‰์„ ์œ„ํ•œ ์ •ํ™•ํ•œ API๋Š” iOS, Android v1 ๋ฐ Android v2์—์„œ ๋‹ค๋ฅด์ง€๋งŒ ๋ณธ์งˆ์ ์œผ๋กœ ์ด๊ฒƒ์ด flutter_isolate๊ฐ€ ์ด๋ฏธ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ๊ฒฉ๋ฆฌ์™€ FlutterEngine ์‚ฌ์ด์—๋Š” ์—ฌ์ „ํžˆ ์˜ค๋ฒ„ํ—ค๋“œ์˜ ์ฐจ์ด๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๋” ๋‚ฎ์ถ”๋Š” ๊ฒƒ์€ Flutter ํŒ€์ด ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹œ์ž‘ ์‹œ๊ฐ„์˜ ์˜ค๋ฒ„ํ—ค๋“œ์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์˜ ์˜ค๋ฒ„ํ—ค๋“œ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ž‘๋™ํ•˜๋„๋ก ์ƒˆ ์—”์ง„ ์ƒ์„ฑ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๊ฒƒ์€ ์•„๋งˆ๋„ ์ด ๋ฌธ์ œ์— ์ ์šฉ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค

๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๋‹จ์ง€ flutter_isolate ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด ํ”ผํ•  ์ˆ˜ ์—†๋Š” ์˜ค๋ฒ„ํ—ค๋“œ ๋•Œ๋ฌธ์— ์ด ์ œํ•œ์ด ์žˆ์Œ์„ ์ง€์ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Flutter ํŒ€์ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ๋” ํšจ์œจ์ ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ๋Š” FlutterEngine์„ ์ธ์Šคํ„ด์Šคํ™”ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ๋กœ๋“œ๋˜๋Š” ๋ฐฉ์‹์— ์•„ํ‚คํ…์ฒ˜ ๋ณ€๊ฒฝ์ด ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์—”์ง„์ด 1์ด๊ณ  ๊ฒฉ๋ฆฌ๊ฐ€ 1๋ณด๋‹ค ํฌ๋ฉด ์ด ์งˆ๋ฌธ์œผ๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

https://github.com/flutter/flutter/issues/13937#issuecomment -667314232

์ด ์ƒˆ๋กœ์šด ๊ฒฝ๋Ÿ‰ ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์„ ์‹ค์ œ๋กœ ์ƒ๊ฐํ•ด๋‚ด๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ €์—๊ฒŒ ๋ฌป๋Š”๋‹ค๋ฉด ๊ฒฝ๋Ÿ‰ ์†”๋ฃจ์…˜์˜ ๋‘ ๊ฐ€์ง€ ๋ณ€ํ˜•์„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ์„ ์ˆ˜๋ฝํ•˜๋„๋ก ํ•˜์—ฌ ๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ์„œ๋ฒ„ ์†Œ์ผ“๊ณผ ์•ฝ๊ฐ„ ์œ ์‚ฌํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ ํ”Œ๋žซํผ ์ธก์˜ ๋ฉ”์†Œ๋“œ ์ฑ„๋„์€ ์—ฌ๋Ÿฌ ๊ฒฉ๋ฆฌ์—์„œ ์—ฐ๊ฒฐ์„ ์ˆ˜๋ฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฐ๊ฒฐ๋˜๋ฉด ์˜ฌ๋ฐ”๋ฅธ ๊ฒฉ๋ฆฌ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋™์ผํ•œ FlutterEngine ๋‚ด์—์„œ ๋ถ„๋ฆฌํ•˜์ง€๋งŒ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ƒˆ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋“ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋‹น์‹ ์ด ๋‚˜์—๊ฒŒ ๋ฌป๋Š”๋‹ค๋ฉด

์˜ˆ, ๋ฌป์Šต๋‹ˆ๋‹ค

์˜ฌ๋ฐ”๋ฅธ ๊ฒฉ๋ฆฌ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

'์˜ฌ๋ฐ”๋ฅธ ๋ถ„๋ฆฌ'๊ฐ€ ์ƒ๋Œ€์ ์ธ ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ๋‚˜์œ ํ•ด๊ฒฐ์ฑ…์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋™์ผํ•œ FlutterEngine ๋‚ด์—์„œ ๋ถ„๋ฆฌํ•˜์ง€๋งŒ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ƒˆ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋“ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ข‹์€ ์˜ต์…˜์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์—”์ง„์ด ํ•ญ์ƒ ์ž์ฒด์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ GeneratedPluginRegistrant์˜ ๋ชจ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
https://github.com/flutter/engine/blob/f7d241fd8a889fadf8ab3f9d57918be3d986b4be/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java#L330 -L344

์ถ”๊ฐ€ ์ฝœ๋ฐฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋ช…๋ฐฑํ•œ ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค.

'์˜ฌ๋ฐ”๋ฅธ ๋ถ„๋ฆฌ'๊ฐ€ ์ƒ๋Œ€์ ์ธ ๊ฐœ๋…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ๋‚˜์œ ํ•ด๊ฒฐ์ฑ…์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

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

์ด๊ฒƒ์€ ์ข‹์€ ์˜ต์…˜์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์—”์ง„์ด ํ•ญ์ƒ ์ž์ฒด์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

ํ•ญ์ƒ ๋ฐœ์ƒํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์•ฝ๊ฐ„ ๋ถˆ์•ˆ์ •ํ•ฉ๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ ํ”Œ๋Ÿฌ๊ทธ์ธ์€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฒฉ๋ฆฌ์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋„ค.

์ด ํ† ๋ก ์— ์ œ 2์„ผํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค... ์•ฝ 2๋…„ ๋™์•ˆ Flutter์™€ ์ƒ์—…์ ์œผ๋กœ ์ผํ•˜๋ฉด์„œ ์ œ๊ฐ€ ๋ฐฐ์šด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ Flutter๊ฐ€ UI ํˆดํ‚ท ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ์ด๊ฒƒ์„ ์žŠ์ง€ ์•Š์•˜๋‹ค๋ฉด ์ด ์„ฑ๋ช…์„œ์—๋Š” ๋†€๋ผ์šด ๊ฒƒ์ด ์—†์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด Flutter์˜ ๋ฉ”์ธ ์›น์‚ฌ์ดํŠธ์—๋„ ๊ทธ๋ ‡๊ฒŒ ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค.

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

๋ฌผ๋ก  Dart๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด UI ์ด์ƒ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด ํˆดํ‚ท์˜ ์ฃผ์š” ๋ชฉ์ ์„ ์žŠ์ง€ ๋ง์ž.

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

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์ธ IMHO๊ฐ€ ์ •๋ง๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์„ธ ๊ฐ€์ง€ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋…ผ๋ฆฌ๋ฅผ ์„œ๋ฒ„๋กœ ์ด๋™ํ•˜์‹ญ์‹œ์˜ค.
  • ๋…ผ๋ฆฌ๋ฅผ ๊ธฐ๋ณธ ํ”Œ๋žซํผ์œผ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด Kotlin Native๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ/๋ฉ”์„œ๋“œ ์ฑ„๋„์„ ์‚ฌ์šฉํ•˜์—ฌ UI์— View Models๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค(OLX๊ฐ€ ํ•œ ์ผ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค: https://tech.olx.com/fast -ํ”Œ๋Ÿฌํ„ฐ๊ฐ€ ์žˆ๋Š” ํ”„๋กœํ† ํƒ€์ž…-kotlin-native-d7ce5cfeb5f1);
  • Flutter๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ฐพ์œผ์„ธ์š”(C#์ด Dart๋ณด๋‹ค ๋” ์ •๊ตํ•œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ Xamarin/Blazor๊ฐ€ ์ด์— ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Œ).

์œ„์˜ ๋ชจ๋“  ๊ฒƒ์—๋Š” ๋‹จ์ ์ด ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ ์„ค๊ณ„๋˜์ง€ ์•Š์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ™•์žฅํ•˜๋Š” ๊ฒƒ๋„ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

isolate_handler ๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ?

@hasonguo ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ flutter_isolate ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ†ต์‹ ์šฉ ์ƒ์šฉ๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ถ„๋ฆฌ(์‹ค์ œ๋กœ ๋ชจ๋“  ๋ถ„๋ฆฌ)๋ฅผ ๋” ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ถ”๊ฐ€ ๋ ˆ์ด์–ด๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฏ€๋กœ ๋งค๋ฒˆ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์‹œ๊ฐ. ์ด์ „์— ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ Flutter ์ž์ฒด์˜ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•ด ๋ถˆ๊ฐ€๋Šฅํ•ด์กŒ์œผ๋ฉฐ ๋Œ€์‹  flutter_isolate ์— ์˜์กดํ•˜๋„๋ก ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

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

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

๋™์ผํ•œ FlutterEngine ๋‚ด์—์„œ ๋ถ„๋ฆฌํ•˜์ง€๋งŒ ๊ฐ๊ฐ์— ๋Œ€ํ•ด ์ƒˆ ํ”Œ๋Ÿฌ๊ทธ์ธ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ ๋“ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ข‹์€ ์˜ต์…˜์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์—”์ง„์ด ํ•ญ์ƒ ์ž์ฒด์ ์œผ๋กœ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋“ฑ๋กํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ GeneratedPluginRegistrant์˜ ๋ชจ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
https://github.com/flutter/engine/blob/f7d241fd8a889fadf8ab3f9d57918be3d986b4be/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java#L330 -L344

์ถ”๊ฐ€ ์ฝœ๋ฐฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ๋ช…๋ฐฑํ•œ ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค.

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

@TahaTesser

๊ท€ํ•˜์˜ ์˜ˆ์—์„œ ์˜ค๋ฅ˜๋Š” ์ด ๋ฌธ์ œ์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

E/flutter ( 7814): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Invalid argument(s): Isolate.spawn expects to be passed a static or top-level function

์•ˆ๋…•ํ•˜์„ธ์š” @nikitadol
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ๋œ ์˜ˆ์—์„œ๋Š” ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งž๋‚˜์š”? (์ด์ „์—๋Š” ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค)
์™„๋ฒฝํ•˜๊ฒŒ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

@TahaTesser


์ฝ”๋“œ ์ƒ˜ํ”Œ

import 'package:battery/battery.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

Future<void> main() async {
  await printBatteryLevel();
  await compute(printBatteryLevel, null);
}

Future<void> printBatteryLevel([dynamic message]) async {
  WidgetsFlutterBinding.ensureInitialized();
  print(await Battery().batteryLevel);
}



๋กœ๊ทธ

Launching lib/main.dart on Pixel 4 in debug mode...
Running Gradle task 'assembleDebug'...
โœ“ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...
Waiting for Pixel 4 to report its views...
Debug service listening on ws://127.0.0.1:50709/-SPs_6AmL2Q=/ws
Syncing files to device Pixel 4...
I/flutter ( 8708): 39
E/flutter ( 8708): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Exception: UI actions are only available on root isolate.
E/flutter ( 8708): #0      Window._nativeSetNeedsReportTimings (dart:ui/window.dart:1003:86)
E/flutter ( 8708): #1      Window.onReportTimings= (dart:ui/window.dart:996:29)
E/flutter ( 8708): #2      SchedulerBinding.addTimingsCallback (package:flutter/src/scheduler/binding.dart:272:14)
E/flutter ( 8708): #3      SchedulerBinding.initInstances (package:flutter/src/scheduler/binding.dart:209:7)
E/flutter ( 8708): #4      ServicesBinding.initInstances (package:flutter/src/services/binding.dart:27:11)
E/flutter ( 8708): #5      PaintingBinding.initInstances (package:flutter/src/painting/binding.dart:23:11)
E/flutter ( 8708): #6      SemanticsBinding.initInstances (package:flutter/src/semantics/binding.dart:24:11)
E/flutter ( 8708): #7      RendererBinding.initInstances (package:flutter/src/rendering/binding.dart:32:11)
E/flutter ( 8708): #8      WidgetsBinding.initInstances (package:flutter/src/widgets/binding.dart:257:11)
E/flutter ( 8708): #9      new BindingBase (package:flutter/src/foundation/binding.dart:59:5)
E/flutter ( 8708): #10     new _WidgetsFlutterBinding&BindingBase&GestureBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #11     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #12     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #13     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #14     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #15     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #16     new _WidgetsFlutterBinding&BindingBase&GestureBinding&SchedulerBinding&ServicesBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #17     new WidgetsFlutterBinding (package:flutter/src/widgets/binding.dart)
E/flutter ( 8708): #18     WidgetsFlutterBinding.ensureInitialized (package:flutter/src/widgets/binding.dart:1229:7)
E/flutter ( 8708): #19     printBatteryLevel (package:bug/main.dart:11:25)
E/flutter ( 8708): #20     _IsolateConfiguration.apply (package:flutter/src/foundation/_isolates_io.dart:83:34)
E/flutter ( 8708): #21     _spawn.<anonymous closure> (package:flutter/src/foundation/_isolates_io.dart:90:65)
E/flutter ( 8708): #22     Timeline.timeSync (dart:developer/timeline.dart:163:22)
E/flutter ( 8708): #23     _spawn (package:flutter/src/foundation/_isolates_io.dart:87:35)
E/flutter ( 8708): #24     _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:304:17)
E/flutter ( 8708): #25     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
E/flutter ( 8708): 



ํ”Œ๋Ÿฌํ„ฐ ๋‹ฅํ„ฐ -v

[โœ“] Flutter (Channel stable, 1.20.4, on Mac OS X 10.15.6 19G2021, locale en-BY)
    โ€ข Flutter version 1.20.4 at /Users/nikitadold/development/flutter
    โ€ข Framework revision fba99f6cf9 (2 weeks ago), 2020-09-14 15:32:52 -0700
    โ€ข Engine revision d1bc06f032
    โ€ข Dart version 2.9.2

[โœ“] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
    โ€ข Android SDK at /Users/nikitadold/Library/Android/sdk
    โ€ข Platform android-30, build-tools 30.0.0
    โ€ข Java binary at: /Users/nikitadold/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/193.6626763/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    โ€ข Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    โ€ข All Android licenses accepted.

[โœ“] Xcode - develop for iOS and macOS (Xcode 12.0.1)
    โ€ข Xcode at /Applications/Xcode.app/Contents/Developer
    โ€ข Xcode 12.0.1, Build version 12A7300
    โ€ข CocoaPods version 1.9.3

[!] Android Studio (version 4.0)
    โ€ข Android Studio at /Users/nikitadold/Library/Application Support/JetBrains/Toolbox/apps/AndroidStudio/ch-0/193.6626763/Android Studio.app/Contents
    โœ— Flutter plugin not installed; this adds Flutter specific functionality.
    โœ— Dart plugin not installed; this adds Dart specific functionality.
    โ€ข Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[โœ“] IntelliJ IDEA Ultimate Edition (version 2020.2.2)
    โ€ข IntelliJ at /Users/nikitadold/Applications/JetBrains Toolbox/IntelliJ IDEA Ultimate.app
    โ€ข Flutter plugin installed
    โ€ข Dart plugin version 202.7319.5

@TahaTesser
์ด ๋Œ“๊ธ€์„ ๋ด์ฃผ์„ธ์š”

ํ”Œ๋žซํผ ๋ฉ”์‹œ์ง€๋Š” ๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ์—์„œ๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค. [...]

์ด ๋™์ž‘์€ _์˜ˆ์ƒ_ ์ด๋ฉฐ ๋ ˆ์ด๋ธ” severe: new feature ์— ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๋ฌธ์ œ๋Š” _ ๋ฒ„๊ทธ _๊ฐ€ ์•„๋‹ˆ๋ผ _๊ธฐ๋Šฅ ์š”์ฒญ_ ๋˜๋Š” _ ์ œ์•ˆ _์œผ๋กœ ๊ฐ„์ฃผ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@iapicca

๊ท€ํ•˜์˜ ์˜ˆ์—์„œ ์˜ค๋ฅ˜๋Š” ์ด ๋ฌธ์ œ์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

E/flutter (23174): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Invalid argument(s): Illegal argument in isolate message : (object is a closure - Function '<anonymous closure>':.)

@iapicca

๊ท€ํ•˜์˜ ์˜ˆ์—์„œ ์˜ค๋ฅ˜๋Š” ์ด ๋ฌธ์ œ์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

E/flutter (23174): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Invalid argument(s): Illegal argument in isolate message : (object is a closure - Function '<anonymous closure>':.)

๋‹น์‹ ์ด ์˜ณ์Šต๋‹ˆ๋‹ค ๋‚ด ๊ฒƒ์€ ์ข‹์€ ์˜ˆ๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ๋ฌด์‹œํ•˜์‹ญ์‹œ์˜ค

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰