728x90
๋ฐ˜์‘ํ˜•
728x90

๐Ÿ”—  ์ถœ์ฒ˜ ๋งํฌ

https://www.technologyreview.kr/ai-reinvents-the-metaverse-world/

 

AI๋Š” ๋ฉ”ํƒ€๋ฒ„์Šค ์„ธ๊ณ„๋ฅผ ์žฌ์ฐฝ์กฐํ•œ๋‹ค - MIT Technology Review

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

www.technologyreview.kr

๐Ÿ“†  ๋ฐœํ–‰์ผ : 2021-11-18

 

 

๐Ÿ’ป  ์š”์•ฝ

์œ„ ๊ธฐ์‚ฌ๋Š” ์ธ๊ณต์ง€๋Šฅ ๊ธฐ์ˆ ์ด ๋ฉ”ํƒ€๋ฒ„์Šค(Metaverse) ๊ฐœ๋…์„ ์ƒˆ๋กญ๊ฒŒ ์žฌ๊ตฌ์„ฑํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๋‚ด์šฉ์„ ๋‹ค๋ฃฌ๋‹ค. ๋ฉ”ํƒ€๋ฒ„์Šค๋Š” ๊ฐ€์ƒ ํ˜„์‹ค(Virtual Reality) ๊ธฐ์ˆ ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ์Šค์™€ ์ธํ„ฐ๋„ท ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•ด ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฐ€์ƒ ์„ธ๊ณ„๋ฅผ ๋งํ•˜๋ฉฐ, ์ตœ๊ทผ ์‚ผ์„ฑ์ „์ž, ํŽ˜์ด์Šค๋ถ, ๊ตฌ๊ธ€ ๋“ฑ ๋Œ€ํ˜• ๊ธฐ์—…๋“ค์ด ๊ด€์‹ฌ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ถ„์•ผ์ด๋‹ค.

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

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

 

 

๐Ÿ’ก ์ƒ๊ฐ ์ •๋ฆฌ

ํ‰์†Œ ๋ฉ”ํƒ€๋ฒ„์Šค์— ๊ด€์‹ฌ์ด ๋งŽ์ด ์žˆ์—ˆ๋Š”๋ฐ, AI๊ฐ€ ๋ฉ”ํƒ€๋ฒ„์Šค๋ฅผ ํ˜„์‹คํ™” ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Œ์„ ํ™•์ธํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

AI์™€ ๋ฉ”ํƒ€๋ฒ„์Šค๊ฐ€ ๊ณผ์—ฐ ์–ด๋–ป๊ฒŒ ๊ด€๋ จ์ด ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ถ๊ธˆ์ฆ์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ๋‘ ๋ถ„์•ผ๋Š” ๊ฝค๋‚˜ ๋ฐ€์ ‘ํ•œ ๊ด€๋ จ์ด ์žˆ์Œ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. 

์•ž์œผ๋กœ ๋‘ ๋ถ„์•ผ๊ฐ€ ์œตํ•ฉํ•˜์—ฌ ๋ฉ”ํƒ€๋ฒ„์Šค๋ฅผ ์‹คํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ณผ์ •๊ณผ ํ•„์š”ํ•œ ๊ฒƒ๋“ค์€ ๋ฌด์—‡์ด ์žˆ๋Š”์ง€๋ฅผ ๊ฒฝํ—˜์„ ํ†ตํ•ด ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•

๐Ÿšจ ์ด์Šˆ

์ฑ…์„ ๋”ฐ๋ผํ•˜๋‹ค ๋ณด๋‹ˆ, ๋ฒ„์ „์ด ๋งž์ง€ ์•Š์•„์„œ ๊ทธ๋ ‡๊ตฌ๋‚˜ ํ•˜๊ณ  ๋„˜์–ด๊ฐ”๋˜ ๋ถ€๋ถ„ ์ค‘, ๊ทธ๋ž˜์„œ๋Š” ์•ˆ๋˜๋Š” ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค.

์ฑ…์—์„œ storyboard๋ฅผ ์–ธ๊ธ‰ํ•˜๊ณ , ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ƒ๊ฐ๋ณด๋‹ค ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ ์ฒ˜์Œ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, User interface ์„ค์ •์„ 'SwiftUI''๊ฐ€ ์•„๋‹Œ, 'Storyboard'๋กœ ์„ค์ •ํ•ด์•ผ ํ–ˆ๋‹ค.

 

๊ทธ๋ ‡๊ฒŒ ํ•˜๋‹ˆ, ์ด๋ฆ„์€ ์กฐ๊ธˆ ๋‹ค๋ฅด์ง€๋งŒ, storyboard๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค !

 

 

๐Ÿ’ป ๋ฌธ๋ฒ• ์ •๋ฆฌ

์•„์›ƒ๋ › ๋ณ€์ˆ˜ (Outlet Variable)

๊ฐ์ฒด์— ๋Œ€ํ•œ ์†์„ฑ์„ ์ง€์ •ํ•  ๋•Œ ์—ฐ๊ฒฐ
@IBOutlet weak var lblHello: UILabel!

@IBOutlet : @IBOutlet์œผ๋กœ ์ •์˜๋œ ๋ณ€์ˆ˜๋ฅผ ์•„์šธ๋ › ๋ณ€์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

  • IB๋Š” Interface Builder์˜ ์•ฝ์ž์ด๋ฉฐ, @IB๋กœ ์‹œ์ž‘๋˜๋Š” ๋ณ€์ˆ˜๋‚˜ ํ•จ์ˆ˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์™€ ๊ด€๋ จ๋œ ๋ณ€์ˆ˜๋‚˜ ํ•จ์ˆ˜๋ผ๋Š” ๊ฒƒ์„ ์˜๋ฏธ.
  • @IBOutlet์€ ๊ฐ์ฒด๋ฅผ ์†Œ์Šค ์ฝ”๋“œ์—์„œ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ํ‚ค์›Œ๋“œ.
  • ์ฃผ๋กœ ์ƒ‰์ƒ, ํฌ๊ธฐ, ๋ชจ์–‘, ์„ ์˜ ๋‘๊ป˜, ํ…์ŠคํŠธ ๋‚ด์šฉ ๋“ฑ ๊ฐ์ฒด์˜ ์†์„ฑ ์ œ์–ด์— ์‚ฌ์šฉ๋จ.

var lblHello : ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ var ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ. ๊ทธ ๋’ค์— ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์—ฌ ์„ ์–ธํ•œ๋‹ค.

UILabel! : ์„ ์–ธํ•˜๊ณ ์ž ํ•˜๋Š” ๋ณ€์ˆ˜ ํƒ€์ž…์„ ๋‚˜ํƒ€๋ƒ„.

  • ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๋ ˆ์ด๋ธ” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฏ€๋กœ UILabel ํด๋ž˜์Šค ํƒ€์ž… ์„ ํƒ. (UI=User Interface)

strong / weak : ์•„์›ƒ๋ › ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ํŒ์—… ์ฐฝ์˜ 'Storage' ์—์„œ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Œ.

  • ๋ฉ”๋ชจ๋ฆฌ ํšŒ์ˆ˜ ์ •์ฑ…์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ‚ค์›Œ๋“œ
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•œ ์•„์›ƒ๋ › ๋ณ€์ˆ˜๋Š” strong ์‚ฌ์šฉ. (default)
  • weak๋Š” ๋ณ€์ˆ˜ ์ •์˜ ์•ž์— ์ถ”๊ฐ€๋œ๋‹ค.
  • strong์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ, ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐ๋˜์ง€ ์•Š์ง€๋งŒ, weak๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋”๋ผ๋„ ์‹œ์Šคํ…œ์ด ์ž„์˜์ ์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Œ.
  • ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ด์Šˆ ๋•Œ๋ฌธ์— ๋‘ ๊ฐ€์ง€ ์ •์ฑ…์„ ์‚ฌ์šฉ.
    • strong์œผ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋ผ๋ฆฌ ์ƒํ˜ธ ์ฐธ์กฐํ•˜๋Š” ์ผ์ด ์ƒ๊ธธ ๊ฒฝ์šฐ, ์•ฑ์ด ์ข…๋ฃŒ๋˜๊ธฐ ์ „๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ œ๊ฑฐ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ.
    • ์ด๋Ÿฐ ๊ฒฝ์šฐ, ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ weak๋กœ ์ง€์ •ํ•˜๋ฉด, ์‹œ์Šคํ…œ์—์„œ ์ž„์˜ ์ œ๊ฑฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์ƒํ˜ธ ์ฐธ์กฐํ•  ๋•Œ๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ญ์ œ๋  ์ˆ˜ ์žˆ์Œ.

 

 

์•ก์…˜ ํ•จ์ˆ˜ (Action Function)

๊ฐ์ฒด์— ์ด๋ฒคํŠธ๋ฅผ ๋„ฃ๊ณ  ์‹ถ์„ ๋•Œ ์—ฐ๊ฒฐ
@IBAction func btnSend(_ sender: UIButton) {
        lblHello.text = "Hello, " + txtName.text!
    }

@IBAction : @IBAction์œผ๋กœ ์ •์˜๋œ ํ•จ์ˆ˜๋ฅผ ์•ก์…˜ ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

  • ๊ฐ์ฒด์˜ ์ด๋ฒคํŠธ๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ํ‚ค์›Œ๋“œ ์ด๋‹ค.
  • ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜, ํ”ผ์ปค๊ฐ€ ์„ ํƒ๋˜๋Š” ๋“ฑ ํŠน์ • ๊ฐ์ฒด์—์„œ ์›ํ•˜๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ •ํ•ด์ง„ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ.

func btnSend : ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ func ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์„ ์–ธํ•œ๋‹ค.

(_ sender: UIButton) : ์•ก์…˜ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๋„๋ก ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด๋Š” ๊ฐ์ฒด. 

  • ์—ฌ๊ธฐ์—์„œ๋Š” ๋ฒ„ํŠผ ๊ฐ์ฒด์—์„œ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ํ•ด๋‹น ์•ก์…˜ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ๊ฒƒ์ด๋ฏ€๋กœ UIButton ํด๋ž˜์Šค ํƒ€์ž… ์„ ํƒ.

lblHello.text : ๋ ˆ์ด๋ธ” ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์†์„ฑ ์ค‘ ํ…์ŠคํŠธ ๋‚ด์šฉ์„ ์˜๋ฏธํ•˜๋Š” ์†์„ฑ.

txtName.text! : ํ…์ŠคํŠธํ•„๋“œ ๊ฐ์ฒด๊ฐ€ ๊ฐ–๊ณ  ์žˆ๋Š” ์†์„ฑ ์ค‘ ํ…์ŠคํŠธ ๋‚ด์šฉ์„ ์˜๋ฏธํ•˜๋Š” ์†์„ฑ.

  • ๋์— ๋ถ™๋Š” !๋Š” ์˜ต์…”๋„ ๋ณ€์ˆ˜์˜ ๊ฐ•์ œ ์–ธ๋ž˜ํ•‘์„ ์˜๋ฏธ
  • ์Šคํ„ฐ๋””์—์„œ๋Š” !๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ๊ณ  ํ–ˆ๋‹ค...

 


 

๐Ÿ“ swift์—์„œ๋Š” ๋ฌธ์žฅ ๋์— ';' ์ƒˆ๋ฏธ์ฝœ๋ก ์„ ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค. ํ•˜์ง€๋งŒ ๋ถ™์ธ๋‹ค๊ณ  ํ•ด์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง„ ์•Š๋Š”๋‹ค ^^

๐Ÿ“ ์ƒ์ˆ˜์™€ ๋ณ€์ˆ˜, ํ•จ์ˆ˜, ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„ ์ง€์ • ๊ทœ์น™์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

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

 

 

์ด๋กœ์จ ์ฒซ์งธ ๋งˆ๋‹น ๋ !!

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var lblHello: UILabel!
    @IBOutlet weak var txtName: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    
    @IBAction func btnSend(_ sender: UIButton) {
        lblHello.text = "Hello, " + txtName.text!
    }
}

 

๐Ÿ“ฑ ๊ฒฐ๊ณผ

 

 

 

 

 

728x90

 

 

๐ŸŽ ์ •๋ฆฌ

swift๋ฅผ ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ๋†€๋ž๋˜ ์  ์ค‘ ํ•˜๋‚˜๋Š”, ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค.

Storyboard์—์„œ ๊ฐ์ฒด๋ฅผ ๋Œ์–ด ์ฝ”๋“œ ํŽธ์ง‘๊ธฐ๋กœ ์—ฐ๊ฒฐํ•˜๋ฉด, ์ž๋™์œผ๋กœ ์ผ๋ถ€ ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

๋˜ํ•œ ์ด๋ฆ„๊ณผ Connection, type์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ...

๊ต‰์žฅํžˆ ์‹ ์„ ํ•˜๋ฉด์„œ๋„ ์ถฉ๊ฒฉ์ ์ด๋ฉด์„œ๋„ ํŽธ๋ฆฌํ–ˆ๋‹ค. ์•ฝ๊ฐ„ ์žฌ๋ฏธ์žˆ๊ธฐ๋„ ํ–ˆ๋‹ค..๐Ÿซ 

 

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•
728x90

Swift์— ๋Œ€ํ•˜์—ฌ

swift๋Š” ios, macOS, watchOS, tvOS์˜ ์•ฑ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๋‹ค.

C์™€ Objective-C ๊ฐœ๋ฐœ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋Š๋‚„ ์ˆ˜ ์žˆ๋‹ค.

 

swift๋Š” C์™€ ๊ต‰์žฅํžˆ ๋น„์Šทํ•˜๋‹ค. ์™œ๋ƒ! C์˜ ๊ธฐ๋ณธ์ ์ธ type๋“ค์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

integers -> int
floating-point -> Double, Float
Boolean -> Bool
textual data -> String
Collection Types -> Array, Set, Dictionary

swift๋Š” C์ฒ˜๋Ÿผ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค. ์—ฌ๊ธฐ์—๋Š” Constants๊ฐ€ ์žˆ๋Š”๋ฐ, swift์—์„œ์˜ constants๋Š” c๋ณด๋‹ค ๋” ๊ฐ•ํ•˜๋‹ค.

constants๋Š” ๋ณธ๋ž˜ ๊ฐ’์ด ๋ณ€ํ•˜์ง€ ์•Š๋Š” ๋ณ€์ˆ˜๋กœ ์ดํ•ดํ•˜๋ฉด ๋˜๋Š”๋ฐ, ์ด constant ๋ณ€์ˆ˜๋Š” swift์—์„œ ์ฝ”๋“œ๋ฅผ ๋” ์•ˆ์ „ํ•˜๊ณ  ๋ช…ํ™•ํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. 

Tuple์€ value๋“ค์„ ๊ทธ๋ฃนํ™” ํ•˜์—ฌ ์ „๋‹ฌ, ์ƒ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฌ๋Ÿฌ value๋“ค์„ ํ•จ์ˆ˜๋กœ๋ถ€ํ„ฐ return ํ•ด์•ผํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ swift์˜ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ powerfulํ•œ ํŠน์ง•์ด๋‹ค. ๋ฐ”๋กœ Optional์ด๋‹ค. ์ด๋Š” ๊ฐ’์ด ์žˆ์œผ๋ฉด ๊ฐ’์„, ์—†๋‹ค๋ฉด nil์„ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ํƒ€์ž…์€ ํด๋ž˜์Šค ๋ฟ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์œ ํ˜•์— ๋Œ€ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. 

swift๋Š” type-safe ์–ธ์–ด์ด๋‹ค. ์ฆ‰, ์šฐ๋ฆฌ๊ฐ€ ์ง  ์ฝ”๋“œ์—์„œ ์ž˜๋ชป๋œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด์— ๋Œ€ํ•œ ๊ฒฝ๊ณ ๋ฅผ ์ฃผ์–ด ์ธ์ง€ํ•˜๊ฒŒ ํ•ด์ค€๋‹ค. 

๊ทธ ์˜ˆ๋กœ, ์ผ๋ฐ˜ String ๋ณ€์ˆ˜์— optional string ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

 

 

Constants and Variables

Constant์™€ variable์˜ ์ด๋ฆ„์„ ์ง€์„ ๋•Œ๋Š” ํ•ด๋‹น ๊ฐ’๊ณผ ๋น„์Šทํ•˜๊ฒŒ ์ •ํ•˜๋Š” ๊ฒƒ์ง€ ์ข‹๋‹ค.

Constant(์ƒ์ˆ˜)๋Š” ์ผ๋‹จ ์„ค์ •๋˜๋ฉด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์ง€๋งŒ, Variable(๋ณ€์ˆ˜)๋Š” ๋‚˜์ค‘์— ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Constants์™€ Variable์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์‚ฌ์šฉ ์ „์— ์„ ์–ธ ํ•ด์•ผ ํ•œ๋‹ค. ์ƒ์ˆ˜์™€ ๋ณ€์ˆ˜๋Š” ๊ฐ๊ฐ ์„ ์–ธ์— ์‚ฌ์šฉํ•˜๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ๋‹ค๋ฅด๋‹ค.

์ •๋ฆฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

const -> let
variable -> var

๋ณ€์ˆ˜ ์„ ์–ธ์˜ ์˜ˆ๋ฅผ ๋ณด๋ฉด ์ด๋Ÿฌํ•˜๋‹ค. (๊ณต์‹ ๋ฌธ์„œ์—์„œ ์ œ์‹œํ•œ ์˜ˆ์‹œ์ด๋‹ค.)

let maximumNumberOfLoginAttempts = 10 // ์ตœ๋Œ€๊ฐ’์ด ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š”๋‹ค.
var currentLoginAttempt = 0 // ์ดˆ๊ธฐ ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค.
var x = 0.0, y = 0.0, z = 0.0 // ์ด๋ ‡๊ฒŒ ํ•œ ์ค„์— ๊ตฌ๋ถ„ํ•ด์„œ ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

type annotations

์ƒ์ˆ˜๋‚˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ type annotiation์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋–ค ์œ ํ˜•์˜ ๊ฐ’์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด welcomMessage์— String ๋ณ€์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์—์„œ ':' ์ฆ‰ ์ฝœ๋ก ์€ ~์˜ ์œ ํ˜•์ด๋‹ค ๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

var welcomeMessage: String // String value๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

welcomeMessage = "Hello" // ๋‹ค์Œ๊ณผ ๊ฐ™์ด String ๊ฐ’์„ ์—๋Ÿฌ ์—†์ด ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

var red, green, blue: Double // ์ด๋ ‡๊ฒŒ ์ฝค๋งˆ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ํ•œ ์ค„์— ์„ ์–ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

Naming Constants and Variables

 

728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•
728x90

์ด์ œ Step 6 !!!

์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์•ฑ์€, next ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ด์ „์— ๋‚˜์™”๋˜ ๋‹จ์–ด๋ฅผ ๋ณผ ์ˆ˜ ์—†์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋ฒˆ ๋‹จ๊ณ„์—์„œ๋Š” 'Like' ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ, ์›ํ•˜๋Š” ๋‹จ์–ด๋ฅผ ๊ธฐ์–ตํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

์ด๋ฒˆ ๋ชฉํ‘œ๋Š” ๋‹ค์Œ ํ™”๋ฉด๊ณผ ๊ฐ™๋‹ค.

์ด๋ฒˆ step์˜ ๋ชฉํ‘œ !!

 

Add the business logic

MyAppState ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณด์ž.

 

lib/main.dart

// ...

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }

  // ↓ Add the code below.
  var favorites = <WordPair>[];

  void toggleFavorite() {
    if (favorites.contains(current)) {
      favorites.remove(current);
    } else {
      favorites.add(current);
    }
    notifyListeners();
  }
}

// ...
  • ์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” favorites ๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” property๋ฅผ MyAppState์— ์ถ”๊ฐ€ํ•œ ๊ฒƒ์ด๋‹ค. ์ด property๋Š” ๋นˆ ๋ฆฌ์ŠคํŠธ [] ๋กœ ์ดˆ๊ธฐํ™”๋œ๋‹ค.
  • ๋˜ํ•œ, generics๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชฉ๋ก์— ๋‹จ์–ด์Œ์ธ <WordPair>[]๋งŒ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์ •ํ•œ ๊ฒƒ์ด๋‹ค. ์ด๋Š” ์šฐ๋ฆฌ ์•ฑ์„ ๋” ๊ฐ•๋ ฅํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐ ๋„์›€์„ ์ฃผ๋Š”๋ฐ, Dart๊ฐ€ WordPair ์ด์™ธ์˜ ๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์šฐ๋ฆฌ ์•ฑ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์กฐ์ฐจ ๊ฑฐ๋ถ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 
    ์ฆ‰, WordPair ์ด์™ธ์˜ ๊ฒƒ์€ ์ถ”๊ฐ€ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, favorites ๋ชฉ๋ก์„ ํ†ตํ•ด ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฐœ์ฒด(ex. null)๊ฐ€ ์ˆจ๊ฒจ์งˆ ์ˆ˜ ์—†์Œ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
    List ๋Œ€์‹  Set์„ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค. Set์€ []๊ฐ€ ์•„๋‹Œ, {}์„ ํ†ตํ•ด ํ‘œํ˜„ํ•œ๋‹ค.
  • ๋˜ํ•œ, toggleFavorite() ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” ๋งŒ์•ฝ favorites ๋ฆฌ์ŠคํŠธ์— ํ˜„์žฌ ๋‹จ์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ด๋ฅผ ์—†์• ๊ฑฐ๋‚˜, ๋งŒ์•ฝ ๋ฆฌ์ŠคํŠธ์— ์—†๋‹ค๋ฉด ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋‘ ๊ฒฝ์šฐ, ์ฝ”๋“œ๋Š” notifyListerners();๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

 

Add the button

์ด์ œ ์ข‹์•„์š” ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด์„œ 'Next' ๋ฒ„ํŠผ ์™ผ์ชฝ์— ๋งŒ๋“ค์–ด์ค„ ๊ฒƒ์ด๋‹ค. ๋ฒ„ํŠผ์„ Next ์˜†์— ๋‘๊ธฐ ์œ„ํ•ด์„œ๋Š” Row ์œ„์ ฏ์ด ํ•„์š”ํ•˜๋‹ค.

๋จผ์ € ํ˜„์žฌ ์กด์žฌํ•˜๋Š” ๋ฒ„ํŠผ์„ Row๋กœ ๊ฐ์‹ผ๋‹ค.

MyHomePage์˜ build()๋ฉ”์†Œ๋“œ๋กœ ๊ฐ€์„œ, ElevatedButton ์œ„์— ์ปค์„œ๋ฅผ ๋‘๊ณ  Refactor ๋ฉ”๋‰ด๋ฅผ ์—ด์–ด Wrap with Row๋ฅผ ์„ ํƒํ•œ๋‹ค.

 

์ด๋ฅผ ์ €์žฅํ•˜๋ฉด, Column์„ ์ ์šฉํ–ˆ์„ ๋•Œ์™€ ๋น„์Šทํ•˜๊ฒŒ children์ด ์™ผ์ชฝ์— ์น˜์šฐ์ ธ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (Column์€ ์œ„๋กœ..!)

์ด๋ฅผ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๋ชจ์–‘์œผ๋กœ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Column์—์„œ ํ•œ ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๊ฒŒ center๋ฅผ ๋งž์ถฐ์ฃผ๋ฉด ๋œ๋‹ค.

Row์—์„œ๋Š” mainAxisAlignment๋ฅผ ํ†ตํ•ด ๋งž์ถœ ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ์ ์šฉํ•œ ์ฝ”๋“œ์ด๋‹ค.

 

lib/main.dart

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BigCard(pair: pair),
            SizedBox(height: 10),
            Row(
              mainAxisSize: MainAxisSize.min,   // ← Add this.
              children: [
                ElevatedButton(
                  onPressed: () {
                    appState.getNext();
                  },
                  child: Text('Next'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// ...

๋‹ค์‹œ Row๋ฅผ ์ ์šฉํ•˜๊ธฐ ์ „์œผ๋กœ ๋Œ์•„๊ฐ„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์„ผํ„ฐ๊ฐ€ ๋งž์ถฐ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ, ์šฐ๋ฆฌ๋Š” Like button์„ ์ถ”๊ฐ€ํ•ด์„œ ์ด๋ฅผ toggleFavorites()์™€ ์—ฐ๊ฒฐํ•  ๊ฒƒ์ด๋‹ค.

์ด๋ฅผ ์œ„ํ•ด, ์ฝ”๋“œ๋žฉ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง์ ‘ ๋„์ „ํ•ด๋ณด๊ธธ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ๋‹ค.

๋ชจ๋‘ ์ง์ ‘ ํ•œ ๋ฒˆ ํ•ด๋ณด๊ธธ..!

  • MyHomePage์— ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • ElevatedButton.icon()์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • build ๋ฉ”์†Œ๋“œ์˜ ๊ฐ€์žฅ ์œ— ๋ถ€๋ถ„์— word pair๊ฐ€ favorite์œผ๋กœ ์„ ํƒ๋๋Š”์ง€์˜ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ ์ ˆํ•œ icon์„ ์„ ํƒํ•œ๋‹ค.
  • SizedBox๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‘ ๋ฒ„ํŠผ ์‚ฌ์ด์˜ ์—ฌ๋ฐฑ์„ ๋‘”๋‹ค.

์ฝ”๋“œ๋žฉ์—์„œ ์ œ๊ณตํ•œ ์ฝ”๋“œ๋Š” ์ด๋Ÿฌํ•˜๋‹ค

 

lib/main.dart

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    // ↓ Add this.
    IconData icon;
    if (appState.favorites.contains(pair)) {
      icon = Icons.favorite;
    } else {
      icon = Icons.favorite_border;
    }

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BigCard(pair: pair),
            SizedBox(height: 10),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [

                // ↓ And this.
                ElevatedButton.icon(
                  onPressed: () {
                    appState.toggleFavorite();
                  },
                  icon: Icon(icon),
                  label: Text('Like'),
                ),
                SizedBox(width: 10),

                ElevatedButton(
                  onPressed: () {
                    appState.getNext();
                  },
                  child: Text('Next'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// ...

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค!!

์ด์ œ step 6์ด ๋๋‚ฌ๋‹ค!!!

 

๋‹ค์Œ ์Šคํ…์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ข‹์•„์š” ํ•œ ๋‹จ์–ด๊ฐ€ ๋ฌด์—‡์ธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋„๋ก ํ•  ์˜ˆ์ • !!

 

์ „์ฒด ์ฝ”๋“œ๋ฅผ ์ฒจ๋ถ€ํ•œ๋‹ค !

 

lib/main.dart

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }

  var favorites = <WordPair>[];

  void toggleFavorite() {
    if (favorites.contains(current)) {
      favorites.remove(current);
    } else {
      favorites.add(current);
    }
    notifyListeners();
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    IconData icon;
    if (appState.favorites.contains(pair)) {
      icon = Icons.favorite;
    } else {
      icon = Icons.favorite_border;
    }

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BigCard(pair: pair),
            SizedBox(height: 10),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton.icon(
                  onPressed: () {
                    appState.toggleFavorite();
                  },
                  icon: Icon(icon),
                  label: Text('Like'),
                ),
                SizedBox(width: 10),
                ElevatedButton(
                  onPressed: () {
                    appState.getNext();
                  },
                  child: Text('Next'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

class BigCard extends StatelessWidget {
  const BigCard({
    Key? key,
    required this.pair,
  }) : super(key: key);

  final WordPair pair;

  @override
  Widget build(BuildContext context) {
    var theme = Theme.of(context);
    var style = theme.textTheme.displayMedium!.copyWith(
      color: theme.colorScheme.onPrimary,
    );

    return Card(
      color: theme.colorScheme.primary,
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Text(
          pair.asLowerCase,
          style: style,
          semanticsLabel: pair.asPascalCase,
        ),
      ),
    );
  }
}
728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•
728x90

์ง€๋‚œ ์Šคํ…๊นŒ์ง€ ์ž˜ ๋”ฐ๋ผ์™”๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์„ ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ ๋ชจ๋‘ ๋Š๋ผ๋“ฏ, ํ˜„์žฌ๋Š” ํŒจ๋”ฉ๋„ ๋งž์ง€ ์•Š๊ณ , ์šฐ๋ฆฌ๊ฐ€ ์ค‘์š”ํ•˜๊ฒŒ ๋ณด์—ฌ์ค˜์•ผ ํ•  ๋ฐ์ดํ„ฐ์ธ word๊ฐ€ ํ•œ ๋ˆˆ์— ๋“ค์–ด์˜ค์ง€ ์•Š๋Š”๋‹ค.

์šฐ๋ฆฌ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋Š๋ผ๊ธฐ์— ์กฐ๊ธˆ ๋” ์‰ฝ๊ฒŒ, ์›ํ•˜๋Š” ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผํ•œ๋‹ค. 

 

๊ทธ๋ž˜์„œ ์ด๋ฒˆ ์Šคํ…์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์‹œ๊ฐ์ ์ธ ์š”์†Œ(๋””์ž์ธ) ์— ์กฐ๊ธˆ ์‹ ๊ฒฝ์„ ์จ๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

์ฝ”๋“œ๋žฉ์—์„œ ์ œ์‹œํ•œ ๋‹ค์Œ ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ์ด ์ด๋ฏธ์ง€์™€ ๊ฐ™๋‹ค.

์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ !!

 

Extract a widget

ํ˜„์žฌ ์šฐ๋ฆฌ ์ฝ”๋“œ์—์„œ๋Š” word pair๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ด๊ณ  ์žˆ๋‹ค.

Text(appState.current.asLowerCase)

์ด ์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜๊ฒŒ ๋ฐ”๊ฟ”๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ๋ณ„๋„์˜ ์œ„์ ฏ์œผ๋กœ ๋นผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค. 

์ด์ฒ˜๋Ÿผ UI์˜ ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์œ„์ ฏ์„ ๊ฐ–๋Š” ๊ฒƒ์€ Flutter์—์„œ ์ฝ”๋“œ์˜ ๋ณต์žก์„ฑ์„ ๊ด€๋ฆฌํ•˜๋Š” ์ค‘์š”ํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค. 

(+ ๋‚ด ๊ฒฝํ—˜์— ๋น„์ถ”์–ด๋ณด๋ฉด, ์ด๋ฅผ ๋”ฐ๋กœ ์œ„์ ฏ์œผ๋กœ ๋นผ์„œ ๋งŒ๋“ค์–ด๋‘๋ฉด ๋‚˜์ค‘์— ๋˜ ์“ฐ์ผ ๋•Œ ๋‹ค์‹œ ์ฝ”๋“œ๋ฅผ ์งœ๊ฑฐ๋‚˜, ์ด์ „ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„ ๋ณต๋ถ™ํ•˜๋Š” ์ผ์„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ๋˜ํ•œ, ์ˆ˜์ •์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ๋„ ์‰ฝ๊ฒŒ ์ฐพ์•„์„œ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ž‘์€ ๋‹จ์œ„๋กœ ์œ„์ ฏ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค !!)

 

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

๊ทธ๋ž˜์„œ ์ด์ œ  MyHomePage  ์œ„์ ฏ์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”๋ณด์ž..!!

 

lib/main.dart

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();  
    var pair = appState.current;                 // ← Add this.

    return Scaffold(
      body: Column(
        children: [
          Text('A random AWESOME idea:'),
          Text(pair.asLowerCase),                // ← Change to this.
          ElevatedButton(
            onPressed: () {
              appState.getNext();
            },
            child: Text('Next'),
          ),
        ],      // ← 7
      ),
    );
  }
}

// ...

์ด์ œ Text ์œ„์ ฏ์€ ๋”์ด์ƒ appState๋ฅผ ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ตฌ, ์ด์ œ Refactor ๋ฉ”๋‰ด๋ฅผ ํ†ตํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์œ„์ ฏ extract๋ฅผ ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

1. refactor ํ•˜๊ณ  ์‹ถ์€ ์œ„์ ฏ์—์„œ ์šฐํด๋ฆญ -> Refactor ๋ฉ”๋‰ด๋ฅผ ์„ ํƒ -> "BigCard" ์ž…๋ ฅ -> ์—”ํ„ฐ

 

2. Move your cursor to the piece code you want to refactor (Text, in this case), and press Ctrl+. (Win/Linux) or Cmd+. (Mac). (๋‚˜๋งŒ ํ—ท๊ฐˆ๋ ธ๋‚˜.. Cmd๋ž‘ .์„ ๊ฐ™์ด ๋ˆ„๋ฅด๋ฉด ๋œ๋‹ค..!!!)

์ดํ›„ ๋ฐฉ๋ฒ•์€ ์œ„ ์˜์ƒ์„ ๋”ฐ๋ผํ•˜๋ฉด ๋œ๋‹ค ! 

 

์ด์ฒ˜๋Ÿผ extract widget ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž˜ ๋”ฐ๋ผํ–ˆ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํด๋ž˜์Šค๊ฐ€ ํ•˜๋‚˜ ์ƒ์„ฑ๋์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค !

// ...
class BigCard extends StatelessWidget {
  const BigCard({
    Key? key,
    required this.pair,
  }) : super(key: key);

  final WordPair pair;

  @override
  Widget build(BuildContext context) {
    return Text(pair.asLowerCase);
  }
}
// ...

์ด์ œ ์ด refactoring์„ ํ†ตํ•ด ์•ฑ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

 

Add a Card

์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ชฉํ‘œ๋ผ๊ณ  ํ–ˆ๋˜ ๊ทธ ํ™”๋ฉด์„ ๊ธฐ์–ต ํ•˜๋Š”๊ฐ€...?

์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ !!

์ด ์ด๋ฏธ์ง€๋ฅผ ๋ณด๋ฉด vastweb์ด ํŒŒ๋ž€์ƒ‰ ์นด๋“œ ์•ˆ์— ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์นด๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ ๊ฒƒ์ด๋‹ค !

์•„๊นŒ ์‚ฌ์šฉํ–ˆ๋˜ refactor ๋ฉ”๋‰ด๋ฅผ ์ด์šฉํ•  ๊ฒƒ์ธ๋ฐ, ์ด๋ฒˆ์—๋Š” extract ํ•˜์ง€ ์•Š๊ณ , Wrap with Padding์„ ํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

 

์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•๋ณด๋‹ค ๋‚ด๊ฐ€ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž ๊น ์–ธ๊ธ‰ํ•ด๋ณด๋ ค ํ•œ๋‹ค.

refactor ๋ฉ”๋‰ด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ vscode ์ขŒ์ธก์— ์žˆ๋Š” ์ „๊ตฌ ์•„์ด์ฝ˜์„ ๋ˆ„๋ฅด๋Š” ๊ฒƒ์ด๋‹ค.

 

์ด๋ ‡๊ฒŒ ์ „๊ตฌ ์•„์ด์ฝ˜ -> Wrap with Padding ์„ ์„ ํƒํ•˜๋ฉด, ์ž๋™์œผ๋กœ Padding์ด ์œ„์ ฏ์„ ๊ฐ์‹ธ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , Padding ํฌ๊ธฐ๋ฅผ 8.0 -> 20 ์œผ๋กœ ๋ฐ”๊ฟ”์ค€๋‹ค.

 

์ด์ œ, ์œ„์—์„œ ๋งŒ๋“  Padding ์œ„์ ฏ์„ Card ์œ„์ ฏ์œผ๋กœ ๊ฐ์‹ธ์ค„ ๊ฒƒ์ด๋‹ค. ์ฆ‰, Padding ์œ„์ ฏ์˜ ์ƒ์œ„ ์œ„์ ฏ์œผ๋กœ Card ์œ„์ ฏ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค.

padding ์˜†์— ์žˆ๋Š” ์ „๊ตฌ ์•„์ด์ฝ˜์„ ๋ˆŒ๋Ÿฌ์„œ (์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.) Wrap with widget...์„ ์„ ํƒํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ๋งŒ๋“ค์–ด์ง„ widget ํ…์ŠคํŠธ๋ฅผ ์ง€์šฐ๊ณ , Card๋ฅผ ์ž…๋ ฅํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๋นจ๊ฐ„ ์ค„๋„ ์‚ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค !

 

์ค‘๊ฐ„์ ๊ฒ€์„ ํ•ด๋ณด์ž..!

์—ฌ๊ธฐ๊นŒ์ง€ ์ž˜ ๋”ฐ๋ผ ์™”๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

Theme and style

์ด์ œ ์นด๋“œ ์ƒ‰์„ ๋ฐ”๊ฟ”์ค„ ๊ฑด๋ฐ, ์ผ๊ด€๋œ ์ƒ‰ ๊ตฌ์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ธฐ ๋•Œ๋ฌธ์—, ์•ฑ์˜ ํ…Œ๋งˆ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒ‰์„ ์„ ํƒํ•  ๊ฒƒ์ด๋‹ค.

main.dart์—์„œ BigCard ํด๋ž˜์Šค๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•œ๋‹ค.

lib/main.dart

// ...

  @override
  Widget build(BuildContext context) {
    var theme = Theme.of(context);         // ← Add this.

    return Card(
      color: theme.colorScheme.primary,    // ← And also this.
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Text(pair.asLowerCase),
      ),
    );
  }

// ...

์ด๋ ‡๊ฒŒ ์œ„์—์„œ ์ถ”๊ฐ€ํ•œ ๋‘ ์ฝ”๋“œ๋Š” ๊ต‰์žฅํžˆ ๋งŽ์€ ์ผ์„ ํ•œ๋‹ค.

  • ๋จผ์ €, ์ฒซ๋ฒˆ์งธ ์ฝ”๋“œ๋Š” ์•ฑ์˜ ํ˜„์žฌ ํ…Œ๋งˆ๋ฅผ Theme.of(context)๋กœ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
  • ๋‘ ๋ฒˆ์งธ ์ฝ”๋“œ๋Š” ํ…Œ๋งˆ์˜ colorScheme ์†์„ฑ๊ณผ ๋™์ผํ•˜๊ฒŒ ์นด๋“œ์˜ ์ƒ‰์ƒ์„ ์ •์˜ํ•œ๋‹ค. 
    • ์ƒ‰ ๊ตฌ์„ฑํ‘œ๋Š” ๋งŽ์€ ์ƒ‰์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ธฐ๋ณธ ์ƒ‰์€ ์•ฑ์˜ primary color(์•ฑ์„ ์ •์˜ํ•˜๋Š”)์ด๋‹ค.

์ฆ‰, ์šฐ๋ฆฌ๋Š” ๋‘ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•จ์œผ๋กœ์จ MyApp ํด๋ž˜์Šค์—์„œ ์ •์˜ํ•œ theme color๋ฅผ ๋ถˆ๋Ÿฌ์˜จ ๊ฒƒ์ด๋‹ค.

๋งŒ์•ฝ, ์œ„์˜ seedColor๋ฅผ ๋ฐ”๊พธ๋ฉด, ํ•ด๋‹น ์นด๋“œ์˜ ์ƒ‰๋„ ๊ฐ™์ด ๋ฐ”๋€Œ๊ฒŒ ๋œ๋‹ค.

์ด๋ ‡๊ฒŒ theme color๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์•ฑ์˜ ์ „์ฒด์ ์ธ ๋ฉ”์ธ ์ƒ‰์„ ๋ฐ”๊ฟ”์•ผ ํ•  ๋•Œ, ๊ทธ ์ƒ‰์ด ์‚ฌ์šฉ๋œ ์ฝ”๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ์ฐพ์ง€ ์•Š๊ณ , MyApp์˜ theme์—์„œ ์ƒ‰๋งŒ ๋ฐ”๊ฟ”์ฃผ๋ฉด, ๋ชจ๋‘ ๋ฐ”๋€Œ๊ฒŒ ๋œ๋‹ค.

 

TextTheme

์ง€๊ธˆ๊นŒ์ง€ ์™„์„ฑํ•œ ํ™”๋ฉด์„ ๋ณด๋ฉด ์ด๋Ÿฌํ•˜๋‹ค.

ํ•˜์ง€๋งŒ, ์นด๋“œ ์•ˆ์— ์žˆ๋Š” ๊ธ€์”จ๊ฐ€ ๊ฒ€์€์ƒ‰์ด๋ฉฐ, ํฌ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์ž‘์•„ ์ฝ๊ธฐ ํž˜๋“ค๋‹ค.

์ด์ œ BigCard์˜ build() ๋ฉ”์†Œ๋“œ๋ฅผ ๊ณ ์ณ์„œ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด๋ณผ ๊ฒƒ์ด๋‹ค.

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด BigCard์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณด์ž

 

lib/main.dart

// ...

  @override
  Widget build(BuildContext context) {
    var theme = Theme.of(context);
    // ↓ Add this.
    var style = theme.textTheme.displayMedium!.copyWith(
      color: theme.colorScheme.onPrimary,
    );

    return Card(
      color: theme.colorScheme.primary,
      child: Padding(
        padding: const EdgeInsets.all(20),
        // ↓ Change this line.
        child: Text(pair.asLowerCase, style: style),
      ),
    );
  }

// ...
  • theme.textTheme์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ app์˜ font theme์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ํด๋ž˜์Šค๋Š” bodyMedium(medium size์˜ ํ…์ŠคํŠธ๋ฅผ ์œ„ํ•œ), caption(์ด๋ฏธ์ง€๋ฅผ ์œ„ํ•œ), headlineLarge(large headlines๋ฅผ ์œ„ํ•œ)๊ณผ ๊ฐ™์€ ์†์„ฑ๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.
  • displayMedium property๋Š” ๊ณต์‹ ๋ฌธ์„œ์—, "์งง๊ณ  ์ค‘์š”ํ•œ ํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ" ๋ผ๊ณ  ๋‚˜์™€์žˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ์™€ ๊ฐ™๋‹ค !
  • displayMedium ๋Š” ์ด๋ก ์ ์œผ๋กœ null์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ Dart๋Š” null-safe์ด๊ธฐ ๋•Œ๋ฌธ์— null์ด ๋˜๋„๋ก ๋‚ด๋ฒ„๋ ค๋‘์ง€ ์•Š๋Š”๋‹ค.. ๊ทธ๋ž˜์„œ, ์ด๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” ! ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ญ˜ ํ•˜๊ณ  ์‹ถ์€์ง€ Dart๊ฐ€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•œ ๊ฒƒ์€ ์ด ๊ฒฝ์šฐ์— ํ•ด๋‹นํ•˜์ง€ ์•Š๋Š”๋‹น..ใ…Žใ…Ž
  • displayMedium ์— copyWith() ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ์ˆ˜์ •์‚ฌํ•ญ๊ณผ ํ•จ๊ป˜ ํ…์ŠคํŠธ ์Šคํƒ€์ผ์˜ ๋ณต์‚ฌ๋ณธ์ด return ๋œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ–ˆ๋˜ ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ์šฐ๋ฆฌ๋Š” ํ…์ŠคํŠธ ์ƒ‰์ƒ๋งŒ ๋ณ€๊ฒฝํ•œ ๊ฒƒ์ด๋‹ค.
  • ๋˜ ๋‹ค๋ฅธ ์ƒˆ๋กœ์šด ์ƒ‰์ƒ์„ ์–ป๊ณ  ์‹ถ๋‹ค๋ฉด, ์•ฑ์˜ ํ…Œ๋งˆ์— ๋‹ค์‹œ ์ ‘๊ทผํ•˜๋ฉด ๋œ๋‹ค. 

์ง€๊ธˆ๊นŒ์ง€ ํ•œ ๊ฒฐ๊ณผ์ด๋‹ค..!!

ํ›„... step 5... ์ƒ๊ฐ๋ณด๋‹ค ๊ธธ๋‹ค.....

ํ•˜์ง€๋งŒ...! ๋ฒŒ์จ 50%๋Š” ํ–ˆ์œผ๋‹ˆ.. ๊ดœ์ฐฎ๋‹ค....!!!!!!

๊ณ„์† ๊ฐ€๋ณด์ž๊ตฌ...

 

Improve accessibility

flutter๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์•ฑ์— ์—‘์„ธ์Šค ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ, flutter ์•ฑ์€ ์•ฑ์˜ ๋ชจ๋“  ํ…์ŠคํŠธ๋“ค์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํ‘œ์‹œํ•ด์„œ TalkBack ๋ฐ VoiceOver์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

pair.asLowerCase๋ณด๋‹ค๋Š” upper camel case๊ฐ€ screen reader๊ฐ€ ์ •ํ™•ํ•˜๊ฒŒ ๋‹จ์–ด๋ฅผ ์ธ์‹ํ•˜๋Š” ๊ฒƒ์— ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

์ž์„ธํ•œ ๋ถ€๋ถ„์€ ์ฝ”๋“œ๋žฉ์„ ๋ณด์‹œ๊ธธ...... (์ ˆ๋Œ€ ๊ท€์ฐฎ์•„์„œ ์ƒ๋žตํ•˜๋Š”๊ฒŒ ๋งž์Šต๋‹ˆ๋‹ค..ใ…Žใ…Ž)

 

๊ทธ๋ž˜์„œ..! ๊ฒฐ๊ตญ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋ณด์ž.

๊ทธ๋Ÿฌ๋ฉด, ์ด์ œ screen readers๊ฐ€ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ฐ ๋‹จ์–ด ์Œ๋“ค์„ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค. (๋ฌผ๋ก , UI์—๋Š” ๋ณ€ํ™”๊ฐ€ ์—†์„ ๊ฒƒ์ด๋‹ค!)

// ...

  @override
  Widget build(BuildContext context) {
    var theme = Theme.of(context);
    var style = theme.textTheme.displayMedium!.copyWith(
      color: theme.colorScheme.onPrimary,
    );

    return Card(
      color: theme.colorScheme.primary,
      child: Padding(
        padding: const EdgeInsets.all(20),

        // ↓ Make the following change.
        child: Text(
          pair.asLowerCase,
          style: style,
          semanticsLabel: pair.asPascalCase,
        ),
      ),
    );
  }

// ...

๋ณ€ํ™”๋ฅผ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, screen reader๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•ด๋ณด์‹œ๊ธธ...!!

 

 

Center the UI

์ด์ œ..!! UI์˜ ์„ผํ„ฐ๋ฅผ ๋งž์ถฐ์„œ ์‹œ๊ฐ์ ์ธ ๋ถˆํŽธํ•จ์„ ํ•ด์†Œํ•ด ๋ณผ ๊ฒƒ์ด๋‹ค.

๋จผ์ €, BigCard ๋Š” Column์˜ ๋ถ€๋ถ„์ž„์„ ๊ธฐ์–ตํ•ด์•ผ ํ•œ๋‹ค. Column์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž์‹๋“ค์„ top์œผ๋กœ ํ•œ๋ฒˆ์— ๋‘์ง€๋ฉด, ์ด๋ฅผ ์‰ฝ๊ฒŒ override ํ•  ์ˆ˜ ์žˆ๋‹ค.

MyHomePage์˜ build() ๋ฉ”์†Œ๋“œ๋กœ ๊ฐ€์„œ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”๋ณด์ž..!

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,  // ← Add this.
        children: [
          Text('A random AWESOME idea:'),
          BigCard(pair: pair),
          ElevatedButton(
            onPressed: () {
              appState.getNext();
            },
            child: Text('Next'),
          ),
        ],
      ),
    );
  }
}

// ...

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด, Column ์•ˆ์— ์žˆ๋Š” children๋“ค์ด main(vertical=์ˆ˜์ง) axis์— ๋งž์ถฐ center๊ฐ€ ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์‹ค Column ์•ˆ์— ์žˆ๋Š” children๋“ค์€ ์ด๋ฏธ main axis ๋ฐฉํ–ฅ์˜ center๊ฐ€ ๋งž์ถฐ์ ธ ์žˆ๋‹ค. ์ฆ‰, ๊ฐ€๋กœ ์„ผํ„ฐ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š”๋ฐ, ์ ์šฉ๋˜์ง€ ์•Š์€ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค.

๊ทธ ์ด์œ ๋Š”, Column ์ž์ฒด๊ฐ€ ์„ผํ„ฐ๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ, Column์˜ ์„ผํ„ฐ๋ฅผ ๋งž์ถฐ์ฃผ๋ฉด ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์„ผํ„ฐ ์œ„์น˜๋กœ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.

Column์—์„œ ์ „๊ตฌ ์•„์ด์ฝ˜์„ ๋ˆ„๋ฅด๊ฑฐ๋‚˜, cmd . ๋˜๋Š” ctrl . ์„ ๋ˆŒ๋Ÿฌ Refactor menu๋ฅผ ์—ด์–ด์ค€๋‹ค.

Refactor menu -> Wrap with Center

๊ทธ ๊ฒฐ๊ณผ, ํ™”๋ฉด์˜ ์„ผํ„ฐ์— ์œ„์น˜ํ•œ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค !!!

 

์ด์ œ ์กฐ๊ธˆ ๋””ํ…Œ์ผ์ ์ธ UI๋ฅผ ์ˆ˜์ •ํ•  ์ฐจ๋ก€์ด๋‹ค.

  • ์ผ๋‹จ, ์นด๋“œ ์œ„์— ์žˆ๋Š” "A random AWESOME idea:" ํ…์ŠคํŠธ๋Š” ์—†์• ๋„ ๋˜๋ฏ€๋กœ ์ง€์›Œ์ฃผ๊ฒ ๋‹ค.
  • ์นด๋“œ์™€ "Next" ๋ฒ„ํŠผ ์‚ฌ์ด์— ์—ฌ๋ฐฑ์ด ์žˆ์œผ๋ฉด ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ, SizedBox ์œ„์ ฏ์„ ์‚ฌ์šฉํ•ด์„œ ๋‘ ์œ„์ ฏ ์‚ฌ์ด์— '๊ณต๊ฐ„'์„ ๋งŒ๋“ค์–ด์ค€๋‹ค

MyHomePage์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

 

lib/main.dart

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BigCard(pair: pair),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                appState.getNext();
              },
              child: Text('Next'),
            ),
          ],
        ),
      ),
    );
  }
}

// ...

์ด์ œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์ฒ˜์Œ์— ๋ชฉํ‘œํ•œ ์ด๋ฏธ์ง€์™€ ์ผ์น˜ํ•˜๋‹ค !!!!!

 

์ด๋ ‡๊ฒŒ.. ๊ธธ์—ˆ๋˜ step5๊ฐ€ ๋๋‚ฌ๋‹ค..!!!

๊ทธ์ € ๋ณด๊ณ  ๋งŒ๋“ค๊ธฐ๋งŒ ํ–ˆ๋‹ค๋ฉด, ๋นจ๋ฆฌ ๋๋‚ฌ์„ํ…Œ์ง€๋งŒ, ์ดํ•ดํ•˜๊ณ , ์ด๋ฅผ ์ •๋ฆฌํ•˜๋‹ค๋ณด๋‹ˆ ๊ต‰์žฅํžˆ ๊ธธ๊ฒŒ ๋Š๊ปด์กŒ๋‹ค...

 

๊ทธ๋งŒ ์ ๊ณ  ์‹ถ์€ ์ˆœ๊ฐ„๋„ ๋งŽ์ด ์žˆ์—ˆ์ง€๋งŒ...!!!!

 

๊ทธ๋ž˜๋„ step 5 ๋ !!

 

์•„์ฐธ! ํ˜น์‹œ ๋ชฐ๋ผ ํ•„์š”ํ•œ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ์ „์ฒด ์ฝ”๋“œ...!!

 

lib/main.dart

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }
}

// ...

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            BigCard(pair: pair),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
                appState.getNext();
              },
              child: Text('Next'),
            ),
          ],
        ),
      ),
    );
  }
}

class BigCard extends StatelessWidget {
  const BigCard({
    Key? key,
    required this.pair,
  }) : super(key: key);

  final WordPair pair;

  @override
  Widget build(BuildContext context) {
    var theme = Theme.of(context);
    var style = theme.textTheme.displayMedium!.copyWith(
      color: theme.colorScheme.onPrimary,
    );

    return Card(
      color: theme.colorScheme.primary,
      child: Padding(
        padding: const EdgeInsets.all(20),

        // ↓ Make the following change.
        child: Text(
          pair.asLowerCase,
          style: style,
          semanticsLabel: pair.asPascalCase,
        ),
      ),
    );
  }
}

// ...
728x90
๋ฐ˜์‘ํ˜•

+ Recent posts