Flutter Keys

์›๋ฌธ: Flutter Keysarrow-up-right

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

๋‹ค์Œ ๊ธฐ์‚ฌ๋Š” ๋‹ค์Œ ๋น„๋””์˜ค์—์„œ ์ฑ„ํƒ๋˜์—ˆ๋‹ค.

์ฝ๊ธฐ๋ณด๋‹ค๋Š” ๋“ฃ๊ธฐ /๋ณด๊ธฐ๋ฅผ ์„ ํ˜ธํ•œ๋‹ค๋ฉด, ๊ทธ ๋น„๋””์˜ค๋Š” ๋ชจ๋“  ๋™์ผํ•œ ๋‚ด์šฉ์„ ํฌํ•จํ•ด์•ผํ•œ๋‹ค.


The Inside Scoop on Keys

Most of the timeโ€ฆ you donโ€™t need keys! Generally, thereโ€™s no harm adding them, but itโ€™s also unnecessary and just takes up unnecessary space, just like the new keyword, or declaring types on both the right side and left side of a new variable (Iโ€™m looking at you, Map<Foo, Bar> aMap = Map<Foo, Bar>()). But, if you find yourself adding, removing, or reordering a collection of widgets of the same type that hold some state, using keys is likely in your future!

๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ... ํ‚ค๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋Š”๋‹ค! ์ผ๋ฐ˜์ ์œผ๋กœ ๊ทธ๊ฒƒ๋“ค์„ ์ถ”๊ฐ€ํ•ด๋„ ์•„๋ฌด๋Ÿฐ ํ•ด๊ฐ€ ์—†์ง€๋งŒ ๋ถˆํ•„์š”ํ•˜๋ฉฐ ์ƒˆ๋กœ์šด ํ‚ค์›Œ๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ถˆํ•„์š”ํ•œ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๊ฑฐ๋‚˜ ์ƒˆ๋กœ์šด ๋ณ€์ˆ˜์˜ ์˜ค๋ฅธ์ชฝ๊ณผ ์™ผ์ชฝ ๋ชจ๋‘์— ์œ ํ˜•์„ ์„ ์–ธํ•œ๋‹ค (์ €๋Š” ์—ฌ๋Ÿฌ๋ถ„์„ ๋ณด๊ณ  ์žˆ๋‹ค, Map<Foo, Bar> aMap = Map<Foo, Bar> ()). ํ•˜์ง€๋งŒ, ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๊ฐ™์€ ์œ ํ˜•์˜ ์œ„์ ฏ ๋ชจ์Œ์„ ์ถ”๊ฐ€, ์ œ๊ฑฐ ๋˜๋Š” ์žฌ์ •๋ ฌํ•˜๋Š” ๊ฒฝ์šฐ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฏธ๋ž˜์— ๊ฐ€๋Šฅํ•  ๊ฒƒ์ด๋‹ค!

์ผ๋ถ€ ์ƒํƒœ๋ฅผ ๋ณด์œ ํ•˜๋Š” ๋™์ผํ•œ ์œ ํ˜•์˜ ์œ„์ ฏ ๋ชจ์Œ์„ ์ถ”๊ฐ€, ์ œ๊ฑฐ ๋˜๋Š” ์žฌ์ •๋ ฌํ•˜๋Š” ๊ฒฝ์šฐ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฏธ๋ž˜์— ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.

์™œ ์œ„์ ฏ ๋ชจ์Œ์„ ์ˆ˜์ •ํ•  ๋•Œ ํ‚ค๊ฐ€ ํ•„์š”ํ•œ์ง€ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ๋‹จ์ถ”๋ฅผ ๋ˆ„๋ฅผ ๋•Œ ์žฅ์†Œ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ์ƒ‰์ƒ์ด์žˆ๋Š” ์œ„์ ฏ์ด์žˆ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์˜€๋‹ค.

img

stateless ๋ฒ„์ „์˜ ์•ฑ์—๋Š” ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ ๋œ ์ƒ‰์ƒ์ด ์žˆ๋Š” stateless ํƒ€์ผ ๋‘ ๊ฐœ์™€ 'ํƒ€์ผ'์˜ ์œ„์น˜๋ฅผ ์ €์žฅํ•˜๋Š” PositionedTiles๋ผ๋Š” StatefulWidget์ด ์žˆ๋‹ค. ์•„๋ž˜์ชฝ์— ์žˆ๋Š” FloatingActionButton์„ ํƒญํ•˜๋ฉด ๋ชฉ๋ก์—์„œ์˜ ์œ„์น˜๊ฐ€ ๋ฐ”๋€Œ๊ฒŒ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ƒํƒœ ์ €์žฅ์ด ์•„๋‹Œ ColorfulTiles stateful์„ ๋งŒ๋“ค์–ด ์ƒํƒœ์— ์ €์žฅํ•  ๊ฒฝ์šฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋‹ค.

img

์œ„์˜ ์ฝ”๋“œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ "swap"๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ์ƒ‰์ƒ์ด ์„œ๋กœ ๋ฐ”๋€Œ์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์—์„œ buggy์ด๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Stateful ์œ„์ ฏ์— ํ‚ค ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ ํ•œ ๋‹ค์Œ ์œ„์ ฏ์ด ์›ํ•˜๋Š”๋Œ€๋กœ ์Šค์™‘ํ•œ๋‹ค.

img

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ˆ˜์ •์ค‘์ธ ํ•˜์œ„ ํŠธ๋ฆฌ์— stateful ์œ„์ ฏ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ํ•„์š”ํ•˜๋‹ค. ์ปฌ๋ ‰์…˜์˜ ์ „์ฒด ์œ„์ ฏ ํ•˜์œ„ ํŠธ๋ฆฌ๊ฐ€ stateless ์ด๋ฉด ํ‚ค๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๊ฒŒ ๋‹ค์•ผ! Flutter์—์„œ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ธฐ์ˆ ์ ์œผ๋กœ ๋ชจ๋‘ ์•Œ์•„์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์ด ๊ทธ๊ฒƒ์˜ ๋ชจ๋“  ๊ทผ๋ณธ์ ์ธ ์ด์œ ๋ฅผ ์ดํ•ดํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ....


The Nitty Gritty of Why Keys are Sometimes Needed

๋„ˆ ์•„์ง ์—ฌ๊ธฐ์žˆ์–ด? ๊ทธ๋Ÿฐ ๋‹ค์Œ, ๊ทผ์ฒ˜์— ๋ชจ์—ฌ ์œ„์ ฏ๊ณผ Element Tree์˜ ์ง„์ •ํ•œ ๋ณธ์„ฑ์„ ๋ฐฐ์šฐ๊ณ  Flutter ์†Œ์„œ๋Ÿฌ๊ฐ€ ๋˜์‹ญ์‹œ์˜ค! Mwahahaha! ํ•˜ํ•˜! HA ํ•˜! ์—ํ—ด, ์‹ค๋ก€ํ•œ๋‹ค.

์•„๋Š” ๋ฐ”์™€ ๊ฐ™์ด, ๋ชจ๋“  ์œ„์ ฏ์— ๋Œ€ํ•ด Flutter๋Š” ํ•ด๋‹น ์š”์†Œ๋ฅผ ๋งŒ๋“ ๋‹ค. Flutter๋Š” ์œ„์ ฏ ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœElement ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ ๋‹ค. ElementTree๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•œ๋‹ค. ๊ฐ ์œ„์ ฏ์˜ type์— ๋Œ€ํ•œ ์ •๋ณด์™€ children ์š”์†Œ์— ๋Œ€ํ•œ ์ฐธ์กฐ ๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. Flutter ์•ฑ์˜ ๊ณจ๊ฒฉ์ฒ˜๋Ÿผ ElementTree๋ฅผ ์ƒ๊ฐํ•ด๋ณด์‹ญ์‹œ์˜ค. ์•ฑ์˜ ๊ตฌ์กฐ๋ฅผ ๋ณด์—ฌ ์ฃผ์ง€๋งŒ ๋ชจ๋“  ์ถ”๊ฐ€ ์ •๋ณด๋Š” ์›๋ž˜ ์œ„์ ฏ์„ ์ฐธ์กฐํ•˜์—ฌ ์กฐํšŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„์˜ ์˜ˆ์ œ์—์„œRow ์œ„์ ฏ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ ์ž์‹์— ๋Œ€ํ•ด ์ •๋ ฌ ๋œ ์Šฌ๋กฏ ์„ธํŠธ๋ฅผ ๋ณด์œ ํ•œ๋‹ค. Row์—์„œ Tile ์œ„์ ฏ์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ, Flutter๋Š” ElementTree๋ฅผ ๊ฑฐ์ณ ๊ณจ๊ฒฉ ๊ตฌ์กฐ๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ•œ๋‹ค.

img

RowElement๋กœ ์‹œ์ž‘ํ•˜์—ฌ ์ž์‹์œผ๋กœ ์ด๋™ํ•œ๋‹ค. ElementTree๋Š” ์ƒˆ๋กœ์šด ์œ„์ ฏ์ด ์ด์ „ ์œ„์ ฏ๊ณผ ๋™์ผ ์œ ํ˜• ๋ฐ ํ‚ค์ธ์ง€ ํ™•์ธํ•˜๊ณ , ์ผ์น˜ํ•˜๋ฉด ์ƒˆ๋กœ์šด ์œ„์ ฏ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. Stateless ๋ฒ„์ „์—์„œ๋Š” ์œ„์ ฏ์— ํ‚ค๊ฐ€ ์—†์œผ๋ฏ€๋กœ Flutter๊ฐ€ ์œ ํ˜•์„ ํ™•์ธํ•œ๋‹ค. (ํ•œ ๋ฒˆ์— ๋งŽ์€ ์ •๋ณด๊ฐ€ ์žˆ๋Š”๊ฒƒ ๊ฐ™์œผ๋ฉด ์œ„์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋‹ค์ด์–ด๊ทธ๋žจ์„๋ณด์‹ญ์‹œ์˜ค.)

stateful ์œ„์ ฏ์˜ ๊ธฐ๋ณธ ElementTree ๊ตฌ์กฐ๋Š” ์•ฝ๊ฐ„ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ด๋‹ค. ์ด์ „๊ณผ ๊ฐ™์€ ์œ„์ ฏ๊ณผ ์š”์†Œ๊ฐ€ ์žˆ์ง€๋งŒ ์ƒํƒœ ๊ฐ์ฒด ์Œ์ด ์žˆ์œผ๋ฉฐ ์ƒ‰์ƒ ์ •๋ณด๋Š” ์œ„์ ฏ ์ž์ฒด๊ฐ€ ์•„๋‹Œ ํ•ด๋‹น ์œ„์น˜์— ์ €์žฅ๋œ๋‹ค.

img

์ƒํƒœ๊ฐ€ ์—†๋Š” Tile (ํ‚ค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ)์—์„œ ๋‘ ์œ„์ ฏ์˜ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋ฉด Flutter๋Š” ElementTree๋ฅผ ํƒ์ƒ‰ํ•˜๊ณ  RowWidget์˜ ์œ ํ˜•์„ ํ™•์ธํ•œ ๋‹ค์Œ ์ฐธ์กฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ TileElement๋Š” ํ•ด๋‹น ์œ„์ ฏ์ด ๋™์ผํ•œ type (TileWidget)์ธ์ง€ ํ™•์ธํ•˜์—ฌ ์ฐธ์กฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ๋‘ ๋ฒˆ์งธ child์—๊ฒŒ๋„ ๋˜‘๊ฐ™์€ ์ผ์ด ์ผ์–ด๋‚œ๋‹ค. Flutter๋Š” ElementTree์™€ ํ•ด๋‹น state๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฅ์น˜์— ์‹ค์ œ ํ‘œ์‹œ ํ•  ๋‚ด์šฉ์„ ๊ฒฐ์ •ํ•˜๋ฏ€๋กœ ์šฐ๋ฆฌ์˜ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ ์œ„์ ฏ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์Šค์™‘๋˜์ง€ ์•Š์€ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋‹ค!

img

Stateful Tiles๊ฐ€ ์žˆ๋Š” ๊ณ ์นœ ๋ฒ„์ „์—์„œ๋Š” ์œ„์ ฏ์— ํ‚ค ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ์œ„์ ฏ์„ ๋ฐ”๊พธ๋Š” ๊ฒฝ์šฐ Row ์œ„์ ฏ์€ ์ด์ „์ฒ˜๋Ÿผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ํƒ€์ผ ์š”์†Œ์˜ ํ‚ค๊ฐ€ ํ•ด๋‹น ํƒ€์ผ ์œ„์ ฏ์˜ ํ‚ค์™€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ ‡๊ฒŒํ•˜๋ฉด Flutter๊ฐ€ Elements๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ  ElementTree์—์„œ Tile Elements์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค. ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ์ฒซ ๋ฒˆ์งธ Element๋ถ€ํ„ฐ ์‹œ์ž‘ํ•œ๋‹ค.

img

๊ทธ๋Ÿฐ ๋‹ค์Œ Flutter๋Š” ์ผ์น˜ํ•˜๋Š” ํ‚ค๊ฐ€ ์žˆ๋Š” element์— ๋Œ€ํ•ด Row์˜ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ํ•˜์œ„ ํ•ญ๋ชฉ์„ ์‚ดํŽด ๋ณธ๋‹ค. ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์„ ์ฐพ๊ณ  ํ•ด๋‹น ์œ„์ ฏ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ํ”Œ๋Ÿฌํ„ฐ๋Š” ๋‘ ๋ฒˆ์งธ child์—๊ฒŒ ๋˜‘๊ฐ™์€ ์ผ์„ ํ•œ๋‹ค. ์ด์ œ Flutter๋Š” ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์œ„์ ฏ์ด ์žฅ์†Œ๋ฅผ ๊ต์ฒดํ•˜๊ณ  ์ƒ‰์ƒ์„ ์—…๋ฐ์ดํŠธํ•˜์—ฌ ์˜ˆ์ƒ ํ•œ ๊ฒƒ์„ ํ‘œ์‹œํ•œ๋‹ค.

์š”์•ฝํ•˜๋ฉด ํ‚ค๋Š” ์ปฌ๋ ‰์…˜์—์„œ ์ƒํƒœ ์ €์žฅ ์œ„์ ฏ์˜ order ๋˜๋Š” number๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•˜๋‹ค. ์„ค๋ช…์„ ์œ„ํ•ด ์ด ์˜ˆ์ œ์—์„œ๋Š” ์ƒํƒœ๋กœ ์ƒ‰์ƒ์„ ์ €์žฅํ•˜์˜€๋‹ค. ์ข…์ข… state๋Š” ํ›จ์”ฌ ๋” ๋ฏธ๋ฌ˜ํ•œ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜ ์žฌ์ƒ, ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ ํ•œ ๋ฐ์ดํ„ฐ ํ‘œ์‹œ ๋ฐ ์Šคํฌ๋กค ์œ„์น˜๋Š” ๋ชจ๋‘ ์ƒํƒœ๋ฅผ ํฌํ•จํ•œ๋‹ค.


Where do I put โ€˜em?

์งง์€ ๋Œ€๋‹ต : ์•ฑ์— ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ณด์กดํ•ด์•ผ ํ•˜๋Š” ์ƒํƒœ๋กœ ์œ„์ ฏ ํ•˜์œ„ ํŠธ๋ฆฌ์˜ ์ƒ๋‹จ์— ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

๋‚ด๊ฐ€ ๋ณด์•˜๋˜ ํ”ํ•œ ์‹ค์ˆ˜๋Š” ์‚ฌ๋žŒ๋“ค์ด ์ฒ˜์Œ์œผ๋กœ ์ƒํƒœ ์ €์žฅ ์œ„์ ฏ์— ํ‚ค๋ฅผ ๋„ฃ์„ ํ•„์š”๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ์šฉ(dragon)์ด ์žˆ์„๋ฟ์ด๋‹ค. ๋‚˜๋ฅผ ๋ฏฟ์ง€ ์•Š์Šต๋‹ˆ๊นŒ? ์šฐ๋ฆฌ๊ฐ€ ์–ด๋–ค ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ๋‚˜๋Š” colorfulTile ์œ„์ ฏ์„ padding ์œ„์ ฏ์œผ๋กœ ๊ฐ์ŒŒ์ง€๋งŒ ํƒ€์ผ ์œ„์— ํ‚ค๋ฅผ ๋‘์—ˆ๋‹ค.

์ด์ œ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํƒ€์ผ์ด ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ž„์˜์˜ ์ƒ‰์ƒ์œผ๋กœ ๋ฐ”๋€๋‹ˆ๋‹ค.

img

์ถ”๊ฐ€ ๋œ ํŒจ๋”ฉ ์œ„์ ฏ๊ณผ ํ•จ๊ป˜ WidgetTree์™€ ElementTree๊ฐ€ ์–ด๋–ค ๋ชจ์Šต์ธ์ง€ ๋ณด์—ฌ์ค€๋‹ค.

img

Flutter์˜ element-to-widget-matching ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ children๋“ค์˜ ์œ„์น˜๋ฅผ ๊ตํ™˜ ํ•  ๋•Œ ํ•œ ๋ฒˆ์— ํ•œ ๋ ˆ๋ฒจ์˜ ํŠธ๋ฆฌ๋ฅผ ๋ณธ๋‹ค. ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ children๋“ค์˜ children๋“ค์„ ํšŒ์ƒ‰์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ํ•œ ๋ฒˆ์— ํ•œ ์ˆ˜์ค€์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค. Padding ์š”์†Œ๊ฐ€ ์žˆ๋Š” ์ฒซ ๋ฒˆ์งธ ์ˆ˜์ค€์˜ children์—๊ฒŒ๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ผ์น˜ํ•œ๋‹ค.

img

๋‘ ๋ฒˆ์งธ ๋ ˆ๋ฒจ์—์„œ Flutter๋Š” ํƒ€์ผ ์š”์†Œ์˜ ํ‚ค๊ฐ€ ์œ„์ ฏ์˜ ํ‚ค์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํƒ€์ผ ์š”์†Œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜์—ฌ ํ•ด๋‹น ์—ฐ๊ฒฐ์„ ์‚ญ์ œํ•œ๋‹ค. ์ด ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ํ‚ค๋Š” LocalKeys์ด๋‹ค. ์ฆ‰ ์œ„์ ฏ์„ element์™€ ์ผ์น˜ ์‹œํ‚ค๋ฉด Flutter๋Š” ํŠธ๋ฆฌ์˜ ํŠน์ • ์ˆ˜์ค€์—์„œ ์ฃผ์š” ์ผ์น˜ ํ•ญ๋ชฉ์„ ์ฐพ๋Š”๋‹ค.

ํ•ด๋‹น ํ‚ค ๊ฐ’์œผ๋กœ ํ•ด๋‹น ๋ ˆ๋ฒจ์˜ ํƒ€์ผ element๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ƒˆ๋กœ์šด element๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒˆ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.์ด ๊ฒฝ์šฐ์—๋Š” ์œ„์ ฏ์„ ์ฃผํ™ฉ์ƒ‰์œผ๋กœ ๋งŒ๋“ ๋‹ค!

img

ํŒจ๋”ฉ ์œ„์ ฏ ์ˆ˜์ค€์—์„œ ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒฝ์šฐ :

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

img

What kind of Key should I use?

Flutter API์˜ ํ›Œ๋ฅญํ•œ ๊ณต๊ธ‰ ์—…์ฒด๋Š” ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ Key ํด๋ž˜์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ํ‚ค ์œ ํ˜•์€ ํ‚ค๋ฅผ ํ•„์š”๋กœํ•˜๋Š” ํ•ญ๋ชฉ์˜ ๊ตฌ๋ณ„๋˜๋Š” ํŠน์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค. ์œ„์ ฏ์— ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” ์ •๋ณด๋ฅผ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค. ์—ฌ๊ธฐ์„œ๋Š” ๋„ค ๊ฐ€์ง€ ์œ ํ˜•์˜ ํ‚ค, ValueKey , ObjectKey, UniqueKey ๋ฐ UniqueKey์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ฒ ๋‹ค.

๋‹ค์Œ ํ•  ์ผ ๋ชฉ๋ก appยน์„ ๊ณ ๋ คํ•˜๋ผ. ์šฐ์„  ์ˆœ์œ„์— ๋”ฐ๋ผ TODO ๋ชฉ๋ก์˜ ํ•ญ๋ชฉ์„ ์žฌ์ •๋ ฌ ํ•œ ๋‹ค์Œ ์™„๋ฃŒ๋˜๋ฉด ์ œ๊ฑฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.

img

์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” To-do ํ•ญ๋ชฉ์˜ ํ…์ŠคํŠธ๊ฐ€ ์ผ์ •ํ•˜๊ณ  ๊ณ ์œ  ํ•  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์•„๋งˆ๋„ ValueKey์— ๋Œ€ํ•œ ์ข‹์€ ํ›„๋ณด๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค. ํ…์ŠคํŠธ๋Š” value์ด๋‹ค.

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

img

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

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ๊ฒƒ์€ ํ‚ค์— ์ž„์˜์˜ ์ˆซ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์œ„์ ฏ์ด ๋นŒ๋“œ ๋  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๋‚œ์ˆ˜๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  ํ”„๋ ˆ์ž„ ์‚ฌ์ด์˜ ์ผ๊ด€์„ฑ์„ ์žƒ๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ฒ˜์Œ๋ถ€ํ„ฐ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜๋„ ์žˆ๋‹ค!

PageStorageKey๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์Šคํฌ๋กค ์œ„์น˜๋ฅผ ์ €์žฅํ•˜๋Š” ํŠน์ˆ˜ ํ‚ค๋กœ์„œ, ์•ฑ์ด ๋‚˜์ค‘์— ๊ทธ๊ฒƒ์„ ๋ณด์กด ํ•  ์ˆ˜ ์žˆ๋„๋กํ•œ๋‹ค.

img
img

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

img

ํ”ํžˆ (ํ•ญ์ƒ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ!) GlobalKeys๋Š” ์ „์—ญ ๋ณ€์ˆ˜์™€ ์กฐ๊ธˆ ๋น„์Šทํ•œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ InheritedWidgets ๋˜๋Š” Redux ๋‚˜ BLoC ํŒจํ„ด๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ ์ƒํƒœ๋ฅผ ์ฐพ๋Š” ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.


Quick Recap

์š”์•ฝํ•˜๋ฉด ์œ„์ ฏ ํŠธ๋ฆฌ์—์„œ ์ƒํƒœ๋ฅผ ๋ณด์กดํ•˜๋ ค๋ฉด Keys๋ฅผ ์‚ฌ์šฉํ•˜๋ผ. ์ด๋Š” ๋ชฉ๋ก๊ณผ ๊ฐ™์€ ์œ ํ˜•์˜ ์œ„์ ฏ ๋ชจ์Œ์„ ์ˆ˜์ •ํ•  ๋•Œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐœ์ƒํ•œ๋‹ค. ํ‚ค๋ฅผ ๋ณด๊ด€ํ•  ์œ„์ ฏ ํŠธ๋ฆฌ์˜ top์— ๋†“๊ณ  ์œ„์ ฏ์— ์ €์žฅํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ํ‚ค ์œ ํ˜•์„ ์„ ํƒํ•˜๋ผ.

์ถ•ํ•˜ํ•ด, ์ด์ œ ๋„ˆ๋Š” Flutter Sorcerer๊ฐ€๋˜๋Š” ๊ธธ์— ์ž˜ ๋‹ค๋‹ค๋ฅผ๊ฑฐ์•ผ! ์˜ค, ๋‚ด๊ฐ€ ๋งˆ๋ฒ•์‚ฌ๋ผ๊ณ  ํ–ˆ๋‹ˆ? ๋‚˜๋Š” ์•ฑ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์‚ฌ๋žŒ์ฒ˜๋Ÿผ * sourcerer *๋ฅผ ์˜๋ฏธํ–ˆ๋‹ค. โ€ฆ๊ฑฐ์˜. โšก


[1] Code for the To-do app inspired by https://github.com/brianegan/flutter_architecture_samples/tree/master/example/vanilla

Last updated