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
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•

1. Introduction

ํ•™์Šตํ•  ๋‚ด์šฉ์€!

โœ…  flutter๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€์˜ ๊ธฐ์ดˆ

โœ…  flutter์—์„œ layout ๋งŒ๋“ค๊ธฐ

โœ…  ์•ฑ ๋™์ž‘๊ณผ user interaction์˜ ์—ฐ๊ฒฐ (์ข‹์•„์š” ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋Š” ๊ฒƒ์ด ๊ทธ ์˜ˆ)

โœ…  flutter ์ฝ”๋“œ๋ฅผ ์ •๊ฐˆํ•˜๊ฒŒ ์งœ๋Š” ๊ฒƒ

โœ…  ๋ฐ˜์‘ํ˜• ์•ฑ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ (screen ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ๊ฒŒ ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Œ !)

โœ…  ์•ฑ์˜ ์ผ๊ด€๋œ ํ˜•ํƒœ์™€ ๋Š๋‚Œ์„ ์ฃผ๋„๋ก 

 

2. Set up your Flutter environment (flutter ํ™˜๊ฒฝ ์„ค์ •)

๐Ÿ“ Visual Studio Code ์‚ฌ์šฉ

codelab ๊ณต์‹ ๋ฌธ์„œ์—์„œ vscode๋ฅผ ๋‹ค์šด๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๊ฒฐํ•ด๋‘์—ˆ๋‹ค!

 

๊ณต์‹๋ฌธ์„œ ๋งํฌ โฌ‡๏ธ 

https://codelabs.developers.google.com/codelabs/flutter-codelab-first#1

 

Your first Flutter app  |  Google Codelabs

In this codelab, you’ll learn how to build a Flutter app that generates random, cool-sounding names.

codelabs.developers.google.com

 

๊ฐœ๋ฐœ ํƒ€๊นƒ ์„ค์ •ํ•˜๊ธฐ (๋‹ค์Œ ์ค‘ ์›ํ•˜๋Š” os๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.)

flutter์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด์ž ํŠน์ง•์ธ ๋ถ€๋ถ„์ด๋‹ค.

multi-platform toolkit์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์ฝ”๋“œ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ os๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

os๋Š” ์ฃผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ์€ os๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.

  • iOS
  • Android
  • Windows
  • macOS
  • Linux
  • web

์ด๋•Œ ์ง์ ‘ ๊ธฐ๊ธฐ๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•ด๋„ ๋˜๊ณ , simulator๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœํ•ด๋„ ๋œ๋‹ค.

(๋‚˜๋Š” ์•ฝ 80%๋ฅผ simulator๋กœ ๊ฐœ๋ฐœํ•œ๋‹ค!)

 

Flutter ์„ค์น˜ํ•˜๊ธฐ

Flutter SDK ์„ค์น˜๋Š” ๋‹ค์Œ ๊ณต์‹ ๋ฌธ์„œ์— ์ž์„ธํ•˜๊ฒŒ ์„ค๋ช…๋˜์–ด ์žˆ๋‹ค.

https://docs.flutter.dev/

 

Flutter documentation

Get started with Flutter. Widgets, examples, updates, and API docs to help you write your first Flutter app.

docs.flutter.dev

codelab์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์˜ 3๊ฐ€์ง€๋งŒ ์žˆ์œผ๋ฉด ๋œ๋‹ค.

1. Flutter SDK

2. Visual Studio Code (Flutter plugin์ด ์„ค์น˜๋œ)

3. ๊ฐœ๋ฐœ ํƒ€๊นƒ์— ์š”๊ตฌ๋˜๋Š” software (์˜ˆ๋ฅผ ๋“ค์–ด, Visual Studio Code๋Š” Windows, Xcode๋Š” macOS)

 

(์ด ์™ธ์—, flutter SDK ์„ค์น˜๋‚˜ ํ™˜๊ฒฝ ์„ค์ •์— ์–ด๋ ค์›€์ด ์žˆ๋‹ค๋ฉด, codelab 2๋‹จ๊ณ„์—์„œ ๋ณด์—ฌ์ฃผ๋Š” StackOverflow๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ !)

 

3. Create a project

  • Visual Studio Code๋ฅผ ์‹คํ–‰ํ•˜๊ณ  command palette๋ฅผ Open. (  F1  ๋˜๋Š”  ctrl+Shift+P  ๋˜๋Š”  Shift+Cmd+P  )
  • "flutter new"๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ ๊ฒ€์ƒ‰๋œ Flutter: New Project ๋ฅผ ์„ ํƒํ•œ๋‹ค.
    • ๋งŒ์•ฝ flutter ํ™˜๊ฒฝ ์„ค์ •์ด ์ œ๋Œ€๋กœ ์ด๋ฃจ์–ด์กŒ๋‹ค๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž˜ ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Flutter: New Project ๋ฅผ ์„ ํƒํ•˜๊ณ  Appliction์„ ์„ ํƒํ•œ๋‹ค.
  • ๋‹ค์Œ์œผ๋กœ ํด๋”๋ฅผ ์ƒ์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ์œ„์น˜์™€, ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์„ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋งŒ์•ฝ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹ ๋ขฐ์™€ ๊ด€๋ จํ•œ ์ฐฝ์ด ๋œฌ๋‹ค๋ฉด Yes~~๋ฅผ ์„ ํƒ !

์ถœ์ฒ˜:&nbsp;https://codelabs.developers.google.com/codelabs/flutter-codelab-first#2

์—ฌ๊ธฐ๊นŒ์ง€ ํ–ˆ๋‹ค๋ฉด ์ด์ œ ๋ฐ”๋กœ Flutter ๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค !!

 

codelab์„ ๋”ฐ๋ผํ•˜๊ธฐ ์œ„ํ•ด ์ฃ„์ธก ์ƒ๋‹จ์— ์žˆ๋Š” ์•„์ด์ฝ˜์„ ๋ˆ„๋ฅด๊ณ , pubspec.yaml ํŒŒ์ผ์„ ์„ ํƒํ•œ๋‹ค.

ํ•ด๋‹น ํด๋”์— ์žˆ๋Š” ๋‚ด์šฉ ์ค‘, ๊ฐ€์žฅ ์œ„ ๋‘ ์ค„์„ ์ œ์™ธํ•œ ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ง€์šด ๋’ค, ์ด ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๋ถ™์—ฌ๋„ฃ์–ด์ค€๋‹ค.

(name๊ณผ description๋ถ€๋ถ„์€ ๊ทธ๋Œ€๋กœ ๋‘”๋‹ค !)

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 0.0.1+1

environment:
  sdk: '>=2.18.4 <3.0.0'

dependencies:
  flutter:
    sdk: flutter

  english_words: ^4.0.0
  provider: ^6.0.0

dev_dependencies:
  flutter_test:
    sdk: flutter

  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true

์ด pubspec.yaml์€ ์•ฑ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ํŒŒ์ผ์ด๋‹ค. ์ด ์•ฑ์˜ ํ˜„์žฌ ๋ฒ„์ „, dependencies, assets ๋“ฑ์˜ ์ •๋ณด๊ฐ€ ์žˆ๋‹ค.

 

  • ๋‹ค์Œ์€ ๊ฐ™์€ ์•„์ด์ฝ˜ ๋‚ด์— ์žˆ๋Š” analysis_options.yaml ํŒŒ์ผ์„ ๋ฐ”๊ฟ”์ค€๋‹ค.
    • ์•ˆ์— ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ง€์šฐ๊ณ , ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ถ™์—ฌ๋„ฃ์–ด์ค€๋‹ค.
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    prefer_const_constructors: false
    prefer_final_fields: false
    use_key_in_widget_constructors: false
    prefer_const_literals_to_create_immutables: false
    prefer_const_constructors_in_immutables: false
    avoid_print: false

์ด ํŒŒ์ผ์€ ์–ผ๋งˆ๋‚˜ ์—„๊ฒฉํ•˜๊ฒŒ ์šฐ๋ฆฌ๊ฐ€ ์ง  ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด์•ผ ํ•˜๋Š”์ง€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์–ธ์ œ๋“ ์ง€ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜์Œ ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‰ฝ๊ฒŒ ๋„˜์–ด๊ฐ€์ค˜~ ํ•˜๊ณ  ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

 

- ๋งˆ์ง€๋ง‰์œผ๋กœ main.dart ํŒŒ์ผ์„ ๋ฐ”๊ฟ”์ค€๋‹ค. (์œ„์น˜๋Š” 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();
}

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

    return Scaffold(
      body: Column(
        children: [
          Text('A random idea:'),
          Text(appState.current.asLowerCase),
        ],
      ),
    );
  }
}

์ด์ œ ๋ชจ๋“  setting์ด ๋๋‚ฌ๋‹ค !!!!

์˜ค์˜ˆ !! ๐ŸŽ‰

 

๋ณธ๊ฒฉ์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ์œ„์ ฏ๋“ค์„ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์งœ๋ณด์ž !!

 

4. Add a button

์ด์ œ Next button์„ ๋งŒ๋“ค์–ด๋ณด์ž !

.

.

๊ทธ ์ „์— ์•ฑ์„ Launchํ•ด๋ด์•ผ ํ•œ๋‹ค. 

๋จผ์ €  lib/main.dart  ๋ฅผ ์—ด์–ด target device๊ฐ€ ์„ ํƒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณธ๋‹ค.

vscode์˜ ์šฐ์ธก ํ•˜๋‹จ์„ ๋ณด๋ฉด ํ˜„์žฌ ์ง€์ •๋œ target device๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค๋ฉด, ์ด๋ฅผ ํด๋ฆญํ•ด์„œ ๋ฐ”๊พธ๋ฉด ๋œ๋‹ค.

๋‚˜๋Š” ๊ธฐ์กด์— ์—ฐ๊ฒฐํ•ด๋‘” ๊ธฐ๊ธฐ๊ฐ€ ์žˆ์–ด ๋ฐ”๋กœ ๊ทธ ๊ธฐ๊ธฐ๋กœ ์„ค์ •์ด ๋˜์–ด์žˆ์—ˆ๋‹ค. ๋งฅ์ด๋ผ๋ฉด ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์—ด์–ด ios ๊ธฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ , android studio๋ฅผ ํ†ตํ•ด ์•ˆ๋“œ๋กœ์ด๋“œ ๊ธฐ๊ธฐ๋ฅผ ๋งŒ๋“ค์–ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ๊ธฐ๋ฅผ ์—ฐ๊ฒฐํ–ˆ๋‹ค๋ฉด ! ํ•œ ๋ฒˆ ์‹คํ–‰ํ•ด๋ณด์ž !!

 

์šฐ์ธก ์ƒ๋‹จ์— ์žˆ๋Š” ์‹คํ–‰๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์‹คํ–‰ํ•˜๋ฉด ๋œ๋‹ค!

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œจ๋ฉด ์•„์ฃผ์•„์ฃผ ์ž˜ ๋”ฐ๋ผ์˜จ ๊ฒƒ์ด๋‹ค !!!!

๋งŒ์•ฝ ์ฝ”๋“œ๋ฅผ ๋ฐ”๊พธ์—ˆ๋‹ค๋ฉด, Command+s ๋˜๋Š” Ctrl+s๋ฅผ ํ•˜๋ฉด ๋ฐ”๋กœ๋ฐ”๋กœ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ฝ”๋“œ๋žฉ์—์„œ ์ œ์‹œํ•œ Hot Reload์— ๋Œ€ํ•œ stack overflow๋ฅผ ์ฐธ๊ณ ํ•˜๊ธธ !

 

์ด์ œ ์ง„์งœ ์ง„์งœ ์ง„์งœ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด๋ณผ๊ฑฐ๋‹ค !!!

 

lib/main.dart

// ...

    return Scaffold(
      body: Column(
        children: [
          Text('A random AWESOME idea:'),
          Text(appState.current.asLowerCase),

          // ↓ Add this.
          ElevatedButton(
            onPressed: () {
              print('button pressed!');
            },
            child: Text('Next'),
          ),

        ],
      ),
    );

// ...

๋‹ค์Œ๊ณผ ๊ฐ™์ด scaffold ๋‚ด์— ์žˆ๋Š” Column์— ElevatedButton์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

์ด๋•Œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ฝ˜์†”์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋œจ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ main.dart๊ฐ€ ์–ด๋–ป๊ฒŒ ์‹คํ–‰๋˜๋Š”์ง€๋ฅผ ์ดํ•ดํ•ด๋ณด์ž

lib/main.dart์˜ ๊ฐ€์žฅ ์ƒ๋‹จ์—์„œ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋‹ค.

// ...

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

// ...

์šฐ๋ฆฌ๋Š” main() ์ด๋ผ๋Š” ์ด๋ฆ„์˜ ํ•จ์ˆ˜๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด ํ•จ์ˆ˜ ๋‚ด์— ์žˆ๋Š” ์ฝ”๋“œ๋Š” MyApp์— ์ •์˜๋œ ์•ฑ์„ ์‹คํ–‰ํ•˜๋„๋ก Flutter์— ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

MyApp ํด๋ž˜์Šค๋Š” StatelessWidget์„ ํ™•์žฅํ•œ๋‹ค. ์œ„์ ฏ์€ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ๋ชจ๋“  flutter app์˜ ์š”์†Œ๋“ค์ธ๋ฐ, ์•ฑ ๊ทธ ์ž์ฒด๋„ ์œ„์ ฏ์ด๋‹ค.

MyApp์— ์žˆ๋Š” ์ฝ”๋“œ๋Š” ์ „์ฒด ์•ฑ์„ ๊ตฌ์„ฑํ•œ๋‹ค. ์ด๋Š” app-wide state(๋‚˜์ค‘์— ๋‹ค๋ฃฐ ์˜ˆ์ •!) ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์•ฑ์˜ ์ด๋ฆ„์„ ์ง“๊ณ , ์‹œ๊ฐ์  theme์„ ์ •์˜ํ•˜๊ณ , "home" ์œ„์ ฏ(๊ทธ๋Ÿฌ๋‹ˆ๊นŒ, ์•ฑ์˜ ์‹œ์ž‘ ์ง€์ )์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

lib/main.dart

// ...

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

// ...

flutter์—๋Š” app state๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋‹ค. ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ChangeNotifier์ด๋‹ค.

MyAppState๋Š” function์— ์•ฑ์ด ํ•„์š”๋กœ ํ•˜๋Š” data๋ฅผ ์ •์˜ํ•œ๋‹ค. 

  • state class๋Š” ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๋Š” ChangeNotifier๋ฅผ ํ™•์žฅํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋งŒ์•ฝ ํ˜„์žฌ ๋‹จ์–ด๊ฐ€ ๋ฐ”๋€Œ์—ˆ๋‹ค๋ฉด, ์•ฑ์— ์žˆ๋Š” ์–ด๋–ค ์œ„์ ฏ์ด ์ด๋ฅผ ์•Œ ํ•„์š”๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. 
  • MyApp์— ์‚ฌ์šฉํ–ˆ๋“ฏ์ด, ChangeNotifierProvider๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ƒํƒœ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์•ฑ์— ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด๋Š” ์•ฑ์— ์žˆ๋Š” ์–ด๋–ค ์œ„์ ฏ์ด๋ผ๋„ ์ด ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.
  • ์ฆ‰, ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐํ•˜๋ฉด ChangeNotifier๋ฅผ MyAppState์— ์‚ฌ์šฉํ•˜๋ฉด, ์•ฑ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋ณ€ํ™”๋“ค์„ ๋‹ค๋ฅธ ์œ„์ ฏ๋“ค์ด ์•Œ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
    • MyApp์ด ๊ฐ€์žฅ ์ƒ์œ„ ์œ„์ ฏ์ด๋ฉฐ, ChangeNotifier๋Š” ๋ณ€ํ™”๋ฅผ ์ธ์ง€ํ•˜๊ณ  ์ด๋ฅผ ์œ„์ ฏ์— ์•Œ๋ฆฌ๋Š” ์—ญํ• ์ž„์„ ์ดํ•ดํ•˜๋ฉด ๋” ์‰ฝ๋‹ค

๋งˆ์ง€๋ง‰์œผ๋กœ MyHomePage์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

์ด ์œ„์ ฏ์€ ์šฐ๋ฆฌ๊ฐ€ ์ด๋ฏธ ์ˆ˜์ •ํ•œ ์œ„์ ฏ์ด๋‹ค. ๊ณต์‹๋ฌธ์„œ์—์„œ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์™€์„œ ์กฐ๊ธˆ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ๊ฒƒ์ด๋‹ค.

// ...

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

    return Scaffold(   // ← 3
      body: Column(    // ← 4
        children: [
          Text('A random AWESOME idea:'),        // ← 5
          Text(appState.current.asLowerCase),    // ← 6
          ElevatedButton(
            onPressed: () {
              print('button pressed!');
            },
            child: Text('Next'),
          ),
        ],      // ← 7
      ),
    );
  }
}

// ...
  1. ๋ชจ๋“  ์œ„์ ฏ์€ ์œ„์ ฏ์˜ ํ™˜๊ฒฝ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ˜ธ์ถœ๋˜์–ด ์œ„์ ฏ์ด ํ•ญ์ƒ ์ตœ์‹  ์ƒํƒœ๋ฅผ ๊ฐ–๋„๋ก ํ•˜๋Š” build() method๋ฅผ ์ •์˜ํ•œ๋‹ค.
  2. watch method๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์˜ ๋ณ€ํ™”๋ฅผ ์ถ”์ ํ•˜๊ณ , ์•ฑ์˜ ํ˜„ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  3. ๋ชจ๋“  build ๋ฉ”์„œ๋“œ๋Š” ์œ„์ ฏ ๋˜๋Š” ์ค‘์ฒฉ๋œ ์œ„์ ฏ ํŠธ๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ์ด ๊ฒฝ์šฐ ์ตœ์ƒ์œ„ ์œ„์ ฏ์€ Scaffold์ด๋‹ค. Scaffold๋Š” ์‹ค์ œ๋กœ ๊ต‰์žฅํžˆ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋ฉฐ, main.dart์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋œ๋‹ค.  return Scaffold(); 
  4. Column์€ ์•„์ฃผ ์ž์ฃผ ์“ฐ์ด๋ฉด์„œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ layout widget์ด๋‹ค. ์ด ์œ„์ ฏ์€ ๋งŽ์€ ์ˆ˜์˜ children์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ๋ฐฐ์น˜ํ•œ๋‹ค. default๋กœ column์€ ์ขŒ์ธก ์ƒ๋‹จ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š”๋ฐ, ์ด๋ฅผ center๋กœ ๋ฐ”๊ฟ”์ค„ ์ˆ˜ ์žˆ๋‹ค. (๋’ค์—์„œ ๋‹ค๋ฃฐ ์˜ˆ์ •)
  5. Text("")์˜ ํ˜•ํƒœ๋กœ ์“ฐ์ด๋ฉฐ, "" ์•ˆ์— ์›ํ•˜๋Š” ๋ฌธ์ž์—ด์„ ๋„ฃ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ํ™”๋ฉด์— ๊ทธ๋ ค์ง„๋‹ค.
  6. ์ด Text ์œ„์ ฏ์€ appState๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ด ํด๋ž˜์Šค์˜ member์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. (์—ฌ๊ธฐ์—์„œ๋Š” current). 
    WordPair์€ asPascalCase, asLowerCase ๋˜๋Š” asSnakeCase์™€ ๊ฐ™์ด ์œ ์šฉํ•œ getter๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  7. flutter์—๋Š” ๊ด„ํ˜ธ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ์ด ์“ฐ์ด๋Š”๋ฐ, ์‰ผํ‘œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ํ•˜์ง€๋งŒ, vscode์—์„œ๋Š” ์‰ผํ‘œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ๋ถ„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ž๋™์ •๋ ฌ์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ์— ๋”ฐ๋ผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๋‚˜๋Š” ๊ฒฝ์šฐ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ๋ฐ, ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๋Š”๊ฒŒ ์‹ซ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ๊ตฌ๋ถ„์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด๋‹ค.

 

์ง์ ‘ ํ•ด๋ณด์ž

MyAppState๋กœ ๊ฐ€์„œ getNext method๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

lib/main.dart

// ...

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

  // ↓ Add this.
  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }
}

// ...

getNext() ๋ฉ”์†Œ๋“œ๋Š” current์— ์ƒˆ๋กœ์šด ๋žœ๋ค WordPair๋ฅผ ์žฌํ• ๋‹นํ•ด์ค€๋‹ค. ๋˜ํ•œ ์ด๋ฅผ notifyListeners()๋ผ ๋ถ€๋ฅด๋Š”๋ฐ, (ChangeNotifier์˜ ๋ฉ”์†Œ๋“œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.)์ด๋Š” MyAppState๋ฅผ ๋ณด๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž์—๊ฒŒ ์•Œ๋ฆผ์„ ์ค€๋‹ค.

 

 

 

lib/main.dart

// ...

    ElevatedButton(
      onPressed: () {
        appState.getNext();  // ← This instead of print().
      },
      child: Text('Next'),
    ),

// ...

์ด์ œ Next ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ๋‹จ์–ด๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค !!!

 

์ƒ๊ฐ๋ณด๋‹ค ๋„ˆ๋ฌด ๊ธธ์–ด์ ธ์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ ๊ธ€์— ์ ์–ด์•ผ๊ฒ ๋‹ค !!

 

ํ•„์š”ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์„์ง€ ๋ชฐ๋ผ codelab์˜ step1~step4๊นŒ์ง€์˜ 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>();

    return Scaffold(
      body: Column(
        children: [
          Text('A random idea:'),
          Text(appState.current.asLowerCase),
          ElevatedButton(
            onPressed: () {
              appState.getNext(); // ← This instead of print().
            },
            child: Text('Next'),
          ),
        ],
      ),
    );
  }
}
728x90
๋ฐ˜์‘ํ˜•
728x90
๋ฐ˜์‘ํ˜•

 

728x90

 

๋ฆฌ์—‘ํŠธ.. js, html, css ์ด ์ค‘ ๊ทธ ์–ด๋Š ๊ฒƒ๋„ ๋ฐฐ์šด ์ , ์ ‘ํ•œ ์  ์—†์—ˆ์ง€๋งŒ... ๊ต‰์žฅํžˆ ์งง์€ ์‹œ๊ฐ„์— ๋ฆฌ์—‘ํŠธ๋ฅผ ๊ณต๋ถ€ํ•ด์•ผ๋งŒ ํ–ˆ๋‹ค.

์ฃผ์–ด์ง„ ์‹œ๊ฐ„์— js๋ถ€ํ„ฐ ๋ฐฐ์šฐ๊ณ , ์ฐจ๊ทผ์ฐจ๊ทผ ๊ฐ•์˜๋ฅผ ๋“ค์œผ๋ฉฐ ๊ณต๋ถ€ํ–ˆ๋‹ค.

ํ•˜์ง€๋งŒ.... ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ , ์‹ค์ „์— ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ์ž์‹ ๊ฐ๊ณผ ์ง€์‹์ด ํ„ฑ์—†์ด ๋ถ€์กฑํ–ˆ๋‹ค.

 

์ด๋ฒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋Œ์•„๋ณด๋ฉด ๊ฑฐ์˜ ์‹ค์ „์— ๋ถ€๋”ชํžˆ๋ฉฐ ๋ฐฐ์› ๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

 

๊ทธ ์ค‘ ๋ฆฌ์—‘ํŠธ๋กœ ๋งˆํฌ๋‹ค์šด ์—๋””ํ„ฐ์™€ ๋ทฐ์–ด ๊ตฌํ˜„ํ•˜๋Š” ๋ถ€๋ถ„์„ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

๋„ˆ๋ฌด๋‚˜ ๋‹คํ–‰ํžˆ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ํฌ์ŠคํŒ…์„ ํ•ด๋‘์—ˆ๊ณ , ๋„ˆ๋ฌด๋‚˜ ํŽธ๋ฆฌํ•œ ํŒจํ‚ค์ง€๊ฐ€ ์žˆ์—ˆ๊ธฐ์— ์•„์ฃผ ์‰ฝ๊ณ  ๊ฐ„๋‹จํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

๋ฌผ๋ก  ๋ทฐ์–ด๋ฅผ ํ•˜๋Š” ๊ฒƒ์— ์žˆ์–ด ์•„์ฃผ ์˜ค๋žœ ์‹œ๊ฐ„ ์‚ฝ์งˆ์„ ํ–ˆ๋‹ค๋Š” ๊ฒƒ...์€ ์žŠ์ง€ ๋ชปํ•  ๊ฒƒ ๊ฐ™๋‹ค...ํ•˜ํ•˜

 

1. install

npm i @uiw/react-md-editor

 

2. import

import MDEditor from '@uiw/react-md-editor';

 

3. editor ์‚ฌ์šฉํ•˜๊ธฐ

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

<div className="markarea">
	<div data-color-mode="light">
		<MDEditor height={865} value={mdinfo} onChange={setMD} />
	</div>
</div>

editor ์‚ฌ์šฉ ๊ฒฐ๊ณผ!!

 

 

4. viewer ์‚ฌ์šฉํ•˜๊ธฐ

์‚ฌ์‹ค ์ด ๋ถ€๋ถ„์—์„œ ์‚ฝ์งˆ์„ ๊ฝค ์˜ค๋ž˜ํ–ˆ๋‹ค... ํ•ด๋‹น ํŒจํ‚ค์ง€์— ๋ทฐ์–ด๊ฐ€ ๊ฐ™์ด ์žˆ์—ˆ๋Š”๋ฐ ๊ทธ๊ฑธ ๋ณด์ง€ ๋ชปํ•˜๊ณ  ์ž๊พธ ๋‹ค๋ฅธ viewer ํŒจํ‚ค์ง€๋ฅผ ์ฐพ์•„ ์ ์šฉํ•ด๋ดค๋˜ ๊ฒƒ.... ๊ทธ๋ ‡๋‹ค๋ณด๋‹ˆ ๋งˆํฌ๋‹ค์šด์ด ์ œ๋Œ€๋กœ ๋ณด์—ฌ์ง€์ง€ ์•Š์•˜๋‹ค...

์ด๋ ‡๊ฒŒ .Markdown์„ ์‚ฌ์šฉํ•˜๊ณ , source์— ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์€ ๋งˆํฌ๋‹ค์šด String์„ ๊ฐ€์ ธ์˜ค๋ฉด ๋œ๋‹ค!!!

<div className="markdownDiv" data-color-mode="light" style={{padding:15}}>
	<MDEditor.Markdown
		style={{ padding: 10 }}
		source={mkdStr}
    />
</div>

๋งˆํฌ๋‹ค์šด ๋ทฐ์–ด ๊ฒฐ๊ณผ!!

 

์ด๋ ‡๊ฒŒ ์ฒซ ์›น ๊ฒฝํ—˜์ด์ž ๋ฆฌ์—‘ํŠธ ๊ฒฝํ—˜์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌํ–ˆ๋‹ค!!!

๋งŽ์€ ์šฐ์—ฌ๊ณก์ ˆ์ด ์žˆ์—ˆ์ง€๋งŒ.. ํŒ€์›๋“ค์ด ์—†์—ˆ๋‹ค๋ฉด.......์ •๋ง....๋‚œ ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†์—ˆ์„๊ฑฐ๋‹ค...

 

๋ฆฌ์—‘ํŠธ ์กฐ๊ธˆ ๋” ์นœํ•ด์ ธ๋ณด์ž๊ตฌ.. ๋‚ด๊ฐ€ ์ž˜ ํ• ๊ฒŒ...๐Ÿฅน

 

 

 

๋ฐ˜์‘ํ˜•

 

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

state

props

.

.

 

ํŠน์ • ์ฝ”๋“œ๋“ค์ด ์ฒซ ๋ฒˆ์งธ component render์—์„œ๋งŒ ์‹คํ–‰๋˜๊ฒŒ ํ•˜์ž.

์ฒ˜์Œ ํ•œ ๋ฒˆ๋งŒ..!!

๋‚˜์ค‘์—๋Š” ์ƒํƒœ๊ฐ€ ๋ณ€ํ•ด๋„ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก.

์šฐ๋ฆฌ๊ฐ€ state๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ๋ชจ๋“  code๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋œ๋‹ค. 

ํ•˜์ง€๋งŒ ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†์„ ๊ฒฝ์šฐ!! ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

useEffect๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์ด useEffect๋Š” ๋‘ ๊ฐœ์˜ argument๋ฅผ ๊ฐ€์ง€๋Š”๋ฐ, ์ฒซ ๋ฒˆ์งธ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ์ฝ”๋“œ์ด๋‹ค.

ex) useEffect(function1, [])

๋‘๋ฒˆ์งธ๋Š” ... ๋งˆ๋ฒ•๊ฐ™๋‹ค....?

 

๊ฒฐ๊ตญ, useEffect์— ๋Œ€ํ•ด ๋ฐฐ์› ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ๊ณ„์† ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ. 

ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•ด๋„ ๋˜๋Š” ๊ฒƒ๋“ค์„ ๋‹ค๋ฃจ๋Š” ํ•จ์ˆ˜์ด๋‹ค.

 

๋‘ ๋ฒˆ์งธ argument๋Š”..

์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ํŠน์ •ํ•œ ๋ถ€๋ถ„์ด ๋ณ€ํ–ˆ์„ ๋•Œ๋งŒ ๋‹ค์‹œ ์ฐํžˆ๋„๋ก ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ!

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

๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ„์œผ๋กœ์จ counter๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ๋„ ์˜ํ™”๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

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

useEffect(() => {
 console.log("SEARCH FOR", keyword); //keyword๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ๋งŒ ์‹คํ–‰๋œ๋‹ค.
}, [keyword]);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด keyword๊ฐ€ ๋ณ€ํ™”ํ•  ๋•Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๊ฑฐ๋ผ๊ณ  react.js์—๊ฒŒ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

 

์šฐ๋ฆฌ๊ฐ€ ๋‘ ๋ฒˆ์งธ argument๋ฅผ []๋กœ ๋น„์›Œ๋’€์„ ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋๋˜ ์ด์œ ๋Š” ๋น„์–ด์žˆ์œผ๋ฏ€๋กœ ์ง€์ผœ๋ณผ ๋ณ€ํ™”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ฆ‰, ๋‘ ๋ฒˆ์งธ argument๋ฅผ ์ฑ„์šฐ๋ฉด, 'ํ•ด๋‹น argument๊ฐ€ ๋ณ€ํ™”ํ•˜๋Š”์ง€ ์ง€์ผœ๋ด์ค˜' ๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

 


๋ณต์Šต!!!!

๋ฆฌ์—‘ํŠธ์—์„œ๋Š” ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค UI๋ฅผ refresh ํ•œ๋‹ค๋Š” ํŠน์ง•์ด ์žˆ๋‹ค.

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง์ ‘ ํ•˜์ง€ ์•Š์•„๋„ ๋˜๋ฏ€๋กœ ํŽธํ•˜๋‹ค.

ํ•˜์ง€๋งŒ! ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ ์ฝ”๋“œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ํ˜น์€ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ! ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ•˜๋Š”๊ฐ€!!

์ด ๋•Œ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
์ด ํ•จ์ˆ˜๋Š” ๋‘ ๊ฐœ์˜ argument๋ฅผ ๊ฐ–๋Š”๋ฐ,

์ฒซ ๋ฒˆ์งธ argument๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‹คํ–‰์‹œํ‚ค๊ณ  ์‹ถ์€ ์ฝ”๋“œ์ด๊ณ ,

๋‘ ๋ฒˆ์งธ argument๋Š” dependencies๋ผ๊ณ  ๋ถˆ๋ฆฐ๋‹ค. ์ด๋Š” react.js๊ฐ€ ์ง€์ผœ๋ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์ด ๋ณ€ํ™”ํ•  ๋•Œ ์ฒซ ๋ฒˆ์งธ argument๋ฅผ refresh ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. 

 ๋‘ ๋ฒˆ์งธ argument๋Š” array์ด๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๊ฐœ์˜ component๋ฅผ ๋„ฃ์–ด๋„ ๋œ๋‹ค.

 

๊ฒฐ๋ก 

useEffect๋Š” ์›ํ•˜๋Š” state์ด ๋ณ€ํ•  ๋•Œ๋งŒ ์›ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค!!

react.js๋Š” ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งˆ๋‹ค refresh ํ•˜๋Š”๋ฐ, useEffect๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ refresh ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

[ ํ•„์ˆ˜๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์ž์ฃผ ์“ฐ์ด๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ]

Cleanup function

์ด ํ•จ์ˆ˜๋Š” ๊ทธ๋ƒฅ ํ•จ์ˆ˜์ธ๋ฐ, ์šฐ๋ฆฌ์˜ component๊ฐ€ destroy๋  ๋•Œ ๋ญ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

Cleanup function์€ ๋”ฐ๋กœ ์ด ์ด๋ฆ„์˜ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ useEffect์—์„œ component๊ฐ€ ์—†์–ด์งˆ ๋•Œ ๋ฌด์–ธ๊ฐ€๋ฅผ returnํ•˜๋Š” ๊ฒƒ.

์ด๋Š” component๊ฐ€ ์—†์–ด์งˆ ๋•Œ ์–ด๋–ค ๋ถ„์„ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋‚ด๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ์–ธ์ œ component๊ฐ€ create ๋๋Š”์ง€, ์–ธ์ œ destroy ๋๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

function Hello() {
 function byFn() {
  console.log("bye :(");
 }
 function hiFn() {
  console.log("created :)");
  return byFn; // React.js๊ฐ€ hiFn์„ ์‹คํ–‰ํ•˜๊ณ , hiFn์ด ํŒŒ๊ดด๋  ๋•Œ byFn์„ ์‹คํ–‰ํ•œ๋‹ค.
 }
 useEffect(hiFn, []);
 return <h1>Hello</h1>;
}

 

๋ฌผ๋ก  ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ์ ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

function Hello() {
 useEffect(() => {
  console.log("hi :)");
  return () => console.log("bye :(");
 }, []);

 useEffect(function () {
  console.log("hi :)");
  return function() {
   console.log("bye :(");
  };
 }, []);
 return <h1>Hello</h1>;
}

 

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

์ฒ˜์Œ์œผ๋กœ react๋ฅผ ๊ณต๋ถ€ํ•˜๊ณ  ๋‚˜์„œ css ์‚ฌ์šฉ์— ์ต์ˆ™์น˜ ์•Š๊ณ , ์•„์ง ํ๋ฆ„์„ ์ œ๋Œ€๋กœ ์žก์ง€ ๋ชปํ•œ ์ƒํƒœ์—์„œ ๊ฐœ๋ฐœ์— ์ฐธ์—ฌํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— component ์ด๋ฆ„์„ ์–ด๋–ป๊ฒŒ ์ •ํ•˜๋Š”์ง€๋„ ์ž˜ ์•Œ์ง€ ๋ชปํ•ด ํ˜ผ๋ž€์Šค๋Ÿฌ์› ๋‹ค.

์ผ๋‹จ ํ•ด๋ด์•ผํ•œ๋‹ค๋Š” ์ƒ๊ฐ, html, css, js ๋ชจ๋‘ ์ฒ˜์Œ ์‹œ์ž‘ํ•˜๋Š” ๋งŒํผ ๊ฒฐ๊ณผ๋ฌผ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ์ƒ๊ฐ์— ์ผ๋‹จ ๋›ฐ์–ด๋“ค์—ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ ๋‚˜๋กœ ์ธํ•ด style ๊ฐ„์„ญ์ด ์ผ์–ด๋‚˜๋ฒ„๋ ธ๋‹ค...

 

๊ฒฐ๊ตญ ๋‚˜๋Š” ์ž ์‹œ ํ”„๋กœ์ ํŠธ์— ์†์„ ๋–ผ๊ฒŒ ๋˜์—ˆ์ง€๋งŒ ์ด๋ฒˆ ์ผ์„ ํ†ตํ•ด style ๊ฐ„์„ญ์ด ๋ฌด์—‡์ธ์ง€ ํ™•์‹คํ•˜๊ฒŒ ์•Œ๊ฒŒ ๋˜์—ˆ๊ณ ,

๋‹ค์‹œ๋Š” ๊ฐ™์€ ์‹ค์ˆ˜๋ฅผ ๋ฐ˜๋ณตํ•˜์ง€ ์•Š๊ฒ ๋‹ค๋Š” ๋‹ค์ง์„ ํ–ˆ๋‹ค.

๊ณต์œ  ๋ฐ›์€ styled components์— ๋Œ€ํ•œ ๊ธ€์„ ๊ณต๋ถ€ํ•˜๊ณ , ์ •๋ฆฌํ•œ ๋‚ด์šฉ์ด๋‹ค.

 


styled components์˜ ํ•„์š”์„ฑ

์ค‘๋ณต๋œ ํด๋ž˜์Šค๋ช…์„ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด, ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋ฅธ ๋ชฉ์ ์„ ์œ„ํ•ด ๋งŒ๋“  ํด๋ž˜์Šค๊ฐ€ ๊ฐ™์€ ์ด๋ฆ„์œผ๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉด, ๊ฐ๊ฐ์— ๊ฐ„์„ญํ•˜๊ฒŒ ๋˜์–ด ์˜ํ–ฅ์„ ๋ผ์น˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๊ฐ€ styled components ์ด๋‹ค.

 

Styled components

styled components๋Š” ํŠน์ • ์Šคํƒ€์ผ์ด ์ฒจ๋ถ€๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ํŒจํ‚ค์ง€์ด๋‹ค.

์ด ํŒจํ‚ค์ง€๋ฅผ ์ ์šฉํ•˜๋ฉด ํ•ด๋‹น ์Šคํƒ€์ผ์ด ์ฒจ๋ถ€๋˜๋Š” ์ปดํฌ๋„ŒํŠธ์—๋งŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ณ , ๋‹ค๋ฅธ ๊ฒƒ์—๋Š” ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š๋Š”๋‹ค.

 

styled components ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

1. styled components๋ฅผ npm ์„ค์น˜ ํ•œ๋‹ค.

2. ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ํŒจํ‚ค์ง€ import

 

styled.ํƒœ๊ทธ(๋ฐฑํ‹ฑ) ๊ณผ ๊ฐ™์€ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•œ๋‹ค.  (styled.ํƒœ๊ทธ`` )

๋ฐฑํ‹ฑ ๊ด€๋ จ ๊ตฌ๋ฌธ์„ tagged template literal์ด๋ผ๊ณ  ํ•œ๋‹ค๋Š”๋ฐ,์ด ๋ถ€๋ถ„์€ ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐ„๋‹ค.

(๋ฐฑํ‹ฑ์€ ' (์ž‘์€ ๋”ฐ์˜ดํ‘œ)์™€ ๋น„์Šทํ•˜๊ฒŒ ์ƒ๊ธด ๋ฌธ์ž์ด๋‹ค. ์ด๊ฒƒ์กฐ์ฐจ ๋ชฐ๋ž๋˜ ๋‚˜...)

 

styled๋Š” importํ•˜๋Š” ๊ฐ์ฒด์ด๊ณ , ๊ทธ ์˜†์— ๋ช…์‹œํ•œ 'ํƒœ๊ทธ'์˜ ๋ฉ”์†Œ๋“œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฆ‰, ๋ฐฑํ‹ฑ ์‚ฌ์ด์— ๋“ค์–ด๊ฐ„ ๋ถ€๋ถ„์ด ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ธ๋ฐ, ์ด ๋ฐฑํ‹ฑ ์‚ฌ์ด์— ์žˆ๋Š” ๊ฒƒ์ด ๊ฒฐ๊ตญ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋กœ ์ „๋‹ฌ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ํƒœ๊ทธ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ƒˆ๋กœ์šด ํƒœ๊ทธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

๊ธ€์„ ๊ณ„์† ์ฝ๋‹ค ๋ณด๋‹ˆ styled components๋Š” ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์ง€๋Š”์ง€ ๊ถ๊ธˆํ–ˆ๋‹ค.

์ด๋ฆ„์„ ์–ด๋–ค ์‹์œผ๋กœ ์ƒ์„ฑํ•˜๋Š”๊ฑด์ง€, ์–ด๋–ป๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“œ๋Š”์ง€ ์˜๋ฌธ์ด ์ƒ๊ฒผ๋‹ค.

-> styled components๋กœ ๋งŒ๋“ค์–ด์ง„ ๊ฒƒ๋“ค์˜ class ๋ช…์€ ํ•ด๋‹น ํŒจํ‚ค์ง€์— ์˜ํ•ด '๋™์ '์œผ๋กœ ์ƒ์„ฑ์ด ๋œ๋‹ค.

-> ๋ชจ๋“  ํด๋ž˜์Šค๋Š” ๊ณ ์œ ํ•œ ์ด๋ฆ„์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ ‡๊ธฐ์— ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

 

styled components์—์„œ css pseudo ์„ ํƒ์ž ๋ฐ ์ค‘์ฒฉ ์„ ํƒ์ž

์ด ๋ถ€๋ถ„์„ ์ •๋ฆฌํ•˜๊ธฐ ์ „์— css pseudo ์„ ํƒ์ž์— ๋Œ€ํ•ด ์กฐ๊ธˆ ์•Œ๊ณ  ์‹ถ์—ˆ๋‹ค.

pseudo๋Š” ๋ณดํ†ต ๊ฐ€์ƒ์ธ ๊ฒƒ์— ์ด๋ฆ„์ด ๋ถ™๋Š”๋ฐ, ์ด ๋˜ํ•œ ๊ทธ๋Ÿฌํ–ˆ๋‹ค. ์šฐ๋ฆฌ ๋ง๋กœ๋Š” '๊ฐ€์ƒ ์„ ํƒ์ž'๋ผ๊ณ ๋„ ๋ถ€๋ฅธ๋‹ค.

css pseudo ์„ ํƒ์ž๋Š” html์š”์†Œ๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์„ ํƒํ•˜์ง€ ์•Š๊ณ  ์š”์†Œ์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ์„ ํƒํ•˜์—ฌ ๊พธ๋ฉฐ์ฃผ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

css pseudo ์„ ํƒ์ž์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ์ •๋ณด๋Š” ์ด ๊ธ€์—์„œ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋‹ค. (https://bio-info.tistory.com/67)

 

๋‹ค์‹œ ๋Œ์•„์™€ styled components์—์„œ css pseudo ์„ ํƒ์ž ๋ฐ ์ค‘์ฒฉ ์„ ํƒ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด ๊ฒฝ์šฐ, & ์ด๋ ‡๊ฒŒ ์ƒ๊ธด ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. &:hover ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ค‘์ฒฉ ์„ ํƒ์ž์˜ ๊ฒฝ์šฐ, & label ํ˜น์€ &.invalid์™€ ๊ฐ™์€ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค.

& ๊ธฐํ˜ธ๋Š” ์ƒ์„ฑ๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. 

 

styled components์—์„œ props ์ „๋‹ฌํ•˜๊ธฐ

styled components์— props๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฐฑํ‹ฑ ์•ˆ์—์„œ ๊ทธ props๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํƒ€์ผ์„ ๋™์ ์œผ๋กœ ์‰ฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

์ด๋Š” ๋ฐฑํ‹ฑ ์‚ฌ์ด์— $ ๊ธฐํ˜ธ์™€ ์ค‘๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„œ๋กœ ๋‹ค๋ฅธ ์„ธ ๊ฐ€์ง€ ๋ฐฉ์‹์„ ํ†ตํ•ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

<CircleStyled invalid={true}/>
// case 1
const CircleStyled = styled.div`
  border-radius: 100%;
  background-color: ${({ invalid }) => invalid ? 'red' : 'black'};
`;
// case 2
const CircleStyled = styled.div(({ invalid ) => `
  border-radius: 100%;
  background-color: ${invalid ? 'red' : 'black'};
`);
// case 3
const CircleStyled = styled.div`
  ${({ invalid }) => `
    border-radius: 100%;
    background-color: ${invalid ? 'red' : 'black'};
  `}
`);

 

styled component์—์„œ ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ

๋นˆ์‘ํ˜•์„ ์œ„ํ•ด ๋ฏธ๋””์–ด ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์ด๋ฅผ styled component์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

์ด ๋•Œ๋Š” @media์™€ ์˜† ์กฐ๊ฑด์„ (min-width: 700px)์ฒ˜๋Ÿผ ์ ๊ณ , ํ•ด๋‹น ์ค‘๊ด„ํ˜ธ ์•ˆ์— ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ์‹œ ์ ์šฉ๋  ์Šคํƒ€์ผ์„ ์ ๋Š”๋‹ค.

const Button = styled.button`
	width: 100%;

	@media (min-width: 700px) {
		// ๋ธŒ๋ผ์šฐ์ € ํญ์ด 700px ์ด์ƒ์ธ ๊ฒฝ์šฐ์— ์ ์šฉ๋˜๋Š” ์ฝ”๋“œ
		width: auto;
	}
`

 

 

์ด๋ ‡๊ฒŒ styled component์— ๋Œ€ํ•œ ๋‹ค์Œ ๊ธ€์„ ์ฝ๊ณ  ๊ณต๋ถ€ํ•˜๋ฉฐ ์ •๋ฆฌํ•ด ๋ณด์•˜๋‹ค.

https://velog.io/@jangws/%EC%8A%A4%ED%83%80%EC%9D%BC-%EA%B0%84%EC%84%AD%EC%9D%84-%EB%B0%A9%EC%A7%80%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%9C-styled-components%EC%99%80-css-module

 

์Šคํƒ€์ผ ๊ฐ„์„ญ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ styled components์™€ css module

์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ์— css ํŒŒ์ผ์„ importํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์กด์˜ ์ผ๋ฐ˜์ ์ธ ์Šคํƒ€์ผ๋ง ๋ฐฉ์‹์€ ์Šคํƒ€์ผ์˜ ์Šค์ฝ”ํ”„๊ฐ€ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์—๋งŒ ๊ตญํ•œ๋˜์ง€ ์•Š๋Š”๋‹ค. ํฐ ํ”„๋กœ์ ํŠธ์—์„œ ์ˆ˜๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ฐ™์€ ์ฝ”๋“œ์—์„œ

velog.io

 

์ด์ œ๋Š” ์กฐ๊ธˆ ๋” ์ต์ˆ™ํ•˜๊ฒŒ, ํ๋ฆ„์„ ํŒŒ์•…ํ•˜์—ฌ ์ฆ๊ฒ๊ฒŒ ์ฝ”๋”ฉํ•˜๊ณ  ์‹ถ๋‹ค...

 

(์›น์„ ๋„ˆ๋ฌด ๋งŒ๋งŒํ•˜๊ฒŒ ๋ดค๋˜ ๋‚˜... ๋ฐ˜์„ฑํ•ด...)

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

 

 

 

javac ํด๋ž˜์Šค๋ช….java
java ํด๋ž˜์Šค๋ช…

 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ž๋ฐ” ํŒŒ์ผ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

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

 

์™ธ์ฃผ๋ฅผ ํ•˜๋‹ค ๋ณด๋‹ˆ ๋ฌด์„  ๋””๋ฒ„๊น…์„ ํ•ด์•ผํ•  ์ผ์ด ์ž์ฃผ ์žˆ์—ˆ๋‹ค.

ํ•˜์ง€๋งŒ ios 14์ธ๊ฐ€ 15๋ถ€ํ„ฐ๋Š” '$ flutter run'์œผ๋กœ๋Š” ๋ฌด์„ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

 

 

flutter run -d ๊ธฐ๊ธฐ๋ฒˆํ˜ธ --release

 

๊ธฐ๊ธฐ๋ฒˆํ˜ธ ์ž๋ฆฌ์— ์‹คํ–‰ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ธฐ๊ธฐ์˜ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ํœด๋Œ€ํฐ์— ์•ฑ์ด ์„ค์น˜๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋ช‡ ๊ฐ€์ง€ ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค๋ฉด, xcode์—์„œ ๊ธฐ๊ธฐ๋ฅผ ์„ ํƒํ•˜๊ณ  ๋นŒ๋“œํ•œ ๋’ค ๋‹ค์‹œ ์‹œ๋„ํ•˜๋ฉด ๋œ๋‹ค.

 

์•ฑ์ด ์„ค์น˜๋˜๊ณ  ๋‚˜์„œ๋Š” ์„ ์„ ์ œ๊ฑฐํ•˜๊ณ ๋„ ๋ฌด์„ ์œผ๋กœ ์•ฑ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

 

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

 

728x90
๋ฐ˜์‘ํ˜•

 

728x90
๋ฐ˜์‘ํ˜•

+ Recent posts