πŸ§‘πŸ»β€πŸ’» ν•¨μˆ˜2❗️❗️❗️(μ€‘μš”)

DEVJUNΒ·2022λ…„ 5μ›” 22일
0

Swift 문법

λͺ©λ‘ 보기
7/14
post-thumbnail

1. 일급 κ°μ²΄λ‘œμ„œμ˜ ν•¨μˆ˜

Β  μŠ€μœ„ν”„νŠΈλŠ” 객체지ν–₯ μ–Έμ–΄μ΄μž λ™μ‹œμ— ν•¨μˆ˜ν˜• 언어이닀. ν•¨μˆ˜ν˜• μ–Έμ–΄λ₯Ό ν•™μŠ΅ν•˜κ²Œ 되면 λ°˜λ“œμ‹œ 일급 객체(First-Class Object)λΌλŠ” μš©μ–΄λ₯Ό μ ‘ν•˜κ²Œ λœλ‹€.

1-1 일급 ν•¨μˆ˜μ˜ νŠΉμ„±

Β  객체가 λ‹€μŒ 쑰건을 λ§Œμ‘±ν•˜λŠ” 경우 이 객체λ₯Ό 일급 객체둜 κ°„μ£Όν•œλ‹€.

  1. 객체가 λŸ°νƒ€μž„μ—λ„ 생성이 κ°€λŠ₯ν•΄μ•Ό ν•œλ‹€.
  2. μΈμžκ°’μœΌλ‘œ 객체λ₯Ό 전달할 수 μžˆμ–΄μ•Ό ν•œλ‹€.
  3. λ°˜ν™˜κ°’μœΌλ‘œ 객체λ₯Ό μ‚¬μš©ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.
  4. λ³€μˆ˜λ‚˜ 데이터 ꡬ쑰 μ•ˆμ— μ €μž₯ν•  수 μžˆμ–΄μ•Ό ν•œλ‹€.
  5. 할당에 μ‚¬μš©λœ 이름과 관계없이 κ³ μœ ν•œ ꡬ별이 κ°€λŠ₯ν•΄μ•Ό ν•œλ‹€.

Β  ν•¨μˆ˜κ°€ 이런 쑰건을 λ§Œμ‘±ν•˜λ©΄ μΌκΈ‰ν•¨μˆ˜(First-Class Function) 이라고 ν•˜κ³  ν•¨μˆ˜ν˜• μ–Έμ–΄λ‘œ λΆ„λ₯˜ν•˜κ³ , ν•¨μˆ˜κ°€ 일급 객체둜 λŒ€μš°λ°›λŠ”λ‹€.

Β  1. λ³€μˆ˜λ‚˜ μƒμˆ˜μ— ν•¨μˆ˜λ₯Ό λŒ€μž…ν•  수 있음

	func foo(base: Int) -> String {
    	return "결과값은 \(base + 1)"
    }
    
    let fn1 = foo(base: 5)
    // 결과값은 6

Β  μœ„ μ½”λ“œλŠ” λ‹¨μˆœνžˆ ν•¨μˆ˜μ˜ 결과값을 λŒ€μž…ν•˜κ³  μžˆλ‹€. κ·ΈλŸ¬λ‚˜ 'λ³€μˆ˜λ‚˜ μƒμˆ˜μ— ν•¨μˆ˜λ₯Ό λŒ€μž…ν•œλ‹€'λŠ” ν•¨μˆ˜ 자체λ₯Ό λŒ€μž…ν•˜λŠ” 것이닀. ν•¨μˆ˜ 자체λ₯Ό λ³€μˆ˜μ— ν• λ‹Ήν•˜λ©΄ λ³€μˆ˜λ„ ν•¨μˆ˜μ²˜λŸΌ μΈμžκ°’μ„ λ°›μ•„ 싀행이 κ°€λŠ₯ν•˜κ³ , 값을 λ°˜ν™˜ν•  수 μžˆλ‹€.

    let fn2 = foo
    fn2(5)
    // 결과값은 6

Β  μƒμˆ˜ fn2에 foo ν•¨μˆ˜ 자체λ₯Ό λŒ€μž…ν•˜κ³  fn2에 ν•¨μˆ˜ 호좜 μ—°μ‚°μžμΈ( )와 μΈμžκ°’5λ₯Ό λ„£μ–΄ ν˜ΈμΆœν•  μˆ˜λ„ 있고 결과값을 받을 μˆ˜λ„ μžˆλ‹€. fn2λŠ” ν•¨μˆ˜μ΄λ‹€.

Β  λ˜ν•œ ν•¨μˆ˜λ₯Ό λŒ€μž…ν•˜κΈ° μœ„ν•΄ νƒ€μž…(Type)에 λŒ€ν•΄μ„œλ„ μ•Œμ•„μ•Όν•œλ‹€. ν•¨μˆ˜ νƒ€μž…μ€ ν•¨μˆ˜μ˜ ν˜•νƒœμ— 따라 μ…€ 수 없을 만큼 λŒœμ–‘ν•œ ꡬ쑰λ₯Ό κ°–λŠ”λ‹€. λ³€μˆ˜μ— μ •μˆ˜λ₯Ό λŒ€μž…ν•˜λ©΄ Int νƒ€μž…μ΄, λ¬Έμžμ—΄μ„ λŒ€μž…ν•˜λ©΄ String νƒ€μž…μ΄ λ˜λŠ” κ²ƒμ²˜λŸΌ, λ³€μˆ˜μ— ν•¨μˆ˜λ₯Ό λŒ€μž…ν•˜λ©΄ ν•¨μˆ˜ νƒ€μž…μ΄ λ˜λŠ” 것이닀.

	func boo(age: Int) -> String {
    	return "\(age)"
    } 
    
    //μœ„ ν•¨μˆ˜λ₯Ό ν•¨μˆ˜ νƒ€μž…μœΌλ‘œ ν‘œν˜„
    (Int) -> String
    
    
    // μœ„μ— ν•¨μˆ˜λ₯Ό μƒμˆ˜μ— ν• λ‹Ήν–ˆμ„ λ•Œ νƒ€μž… μ–΄λ…Έν…Œμ΄μ…˜μ„ ν¬ν•¨ν•œ ν• λ‹Ή ꡬ문
    let fn: (Int) -> String = boo
    
    
    // 두 개의 μΈμžκ°’μ„ λ°›λŠ” ν•¨μˆ˜
    func boo(age: Int, name: String) -> String {
    	return "\(name)"의 λ‚˜μ΄λŠ” \(age)"
    }
    
    // μœ„ ν•¨μˆ˜λ₯Ό ν•¨μˆ˜ νƒ€μž…μœΌλ‘œ μž‘μ„±
    (Int, String) -> String
    
    // μ •ν™•ν•œ μ‹λ³„μžλ₯Ό μ‚¬μš©ν•œ 경우
    let s: (Int, String) -> String = boo(age:name:)
    
    
    
    β—οΈκ°œ μ€‘μš”β—οΈ
    
    func boo(age: Int) -> String {
    	return "\(age)"
    } 
    
    func boo(age: Int, name: String) -> String {
    	return "\(name)"의 λ‚˜μ΄λŠ” \(age)"
    }
    
    let t = boo(X) // 였λ₯˜
    
    
    이런 경우 μ–΄λŠ ν•¨μˆ˜λ₯Ό κ°€λ₯΄ν‚€λŠ”지 μ •ν™•ν•˜κ²Œ νŒλ‹¨ν•  수 μ—†μœΌλ―€λ‘œ 였λ₯˜κ°€ λ‚œλ‹€.
    
    // ν•΄κ²° 방법 1) νƒ€μž… μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 μž…λ ₯받을 ν•¨μˆ˜μ˜ νƒ€μž…μ„ 지정
    let t1: (Int, String) -> String = boo
    
    // ν•΄κ²° 방법 2) ν•¨μˆ˜μ˜ 식별값을 톡해 μž…λ ₯받을 μ •ν™•ν•œ ν•¨μˆ˜λ₯Ό 지정
    let t2 = boo(age:name:)

Β  νƒ€μž… μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” μž…λ ₯받을 κ°’μ˜ νƒ€μž…μ΄ λͺ…ν™•ν•˜κΈ° λ•Œλ¬Έμ—, boo κ°€ κ°€λ₯΄ν‚€λŠ” ν•¨μˆ˜κ°€ λ‹€μ†Œ λΆˆν™•μ‹€ν•˜λ”λΌλ„ μ»΄νŒŒμΌλŸ¬κ°€ μ°Ύμ•„μ„œ λŒ€μž…ν•  수 μžˆλ‹€. 식별값을 톡해 μ§€μ •ν•˜λŠ” κ²½μš°μ—λ„ μ •ν™•ν•œ ν•¨μˆ˜λ₯Ό μ°Ύμ•„ λŒ€μž…ν•  수 있기 λ•Œλ¬Έμ— λ¬Έμ œκ°€ λ˜μ§€ μ•ŠλŠ”λ‹€.

	// μΈμžκ°’μ΄ μ—†λŠ” ν•¨μˆ˜μΈ 경우
    func foo() -> String {
    	return "Empty Values"
    }
    
    // μΈμžκ°’μ΄ μ—†λŠ” 경우 ν•¨μˆ˜ νƒ€μž…
    () -> String
    
    
    // λ°˜ν™˜κ°’μ΄ μ—†λŠ” 경우
    func boo(base: Int) {
    	print("param = \(base)")
    }
    
     // λ°˜ν™˜κ°’μ΄ μ—†λŠ” 경우 ν•¨μˆ˜ νƒ€μž…
    (Int) -> ()
    (Int) -> Void // μ΄λ ‡κ²Œλ„ κ°€λŠ₯
    
    
    // μΈμžκ°’, λ°˜ν™˜κ°’μ΄ λͺ¨λ‘ μ—†λŠ” 경우
    func too() {
    	print("empty values")
    }
    
    // μΈμžκ°’, λ°˜ν™˜κ°’μ΄ λͺ¨λ‘ μ—†λŠ” 경우 ν•¨μˆ˜νƒ€μž…
    () -> ()
    () -> Void

Β  2. ν•¨μˆ˜μ˜ λ°˜ν™˜ νƒ€μž…μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 있음

Β  일급 ν•¨μˆ˜λŠ” μ‹€ν–‰ 결과둜 μ •μˆ˜, μ‹€μˆ˜, λ¬Έμžμ—΄ λ“±μ˜ κΈ°λ³Έ μžλ£Œν˜•μ΄λ‚˜ 클래슀, ꡬ쑰체 λ“±μ˜ 객체λ₯Ό λ°˜ν™˜ν•  수 μžˆμ„ 뿐 μ•„λ‹ˆλΌ ν•¨μˆ˜ 자체λ₯Ό λ°˜ν™˜ν•  μˆ˜λ„ μžˆλ‹€.

	func desc() -> String {
    	return "this is desc()"
    }
	
    func pass() -> () -> String {
    	return desc
    }

	let p = pass()
    p() // "this is desc()"

Β  μœ„ μ½”λ“œμ—μ„œ desc λΌλŠ” λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜κ°€ 있고, pass ν•¨μˆ˜κ°€ desc ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— () -> String 으둜 ν•¨μˆ˜μ˜ νƒ€μž… ν‘œν˜„μ„ ν•˜κ³  μžˆλ‹€. 이 ν•¨μˆ˜ νƒ€μž…μ˜ ν‘œν˜„μ΄ pass ν•¨μˆ˜μ˜ λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μ‚¬μš©λ˜κ³  μžˆλŠ” 것이닀.

Β  μ΄μ–΄μ„œ μƒμˆ˜ pλŠ” pass ν•¨μˆ˜μ˜ μ‹€ν–‰ 결과값을 ν• λ‹Ήλ°›κ³  μžˆλ‹€. pass ν•¨μˆ˜μ˜ μ‹€ν–‰ κ²°κ³ΌλŠ” desc ν•¨μˆ˜μ΄λ―€λ‘œ μƒμˆ˜ pμ—λŠ” desc ν•¨μˆ˜κ°€ ν• λ‹Ήλœλ‹€. 이제 μƒμˆ˜ pλŠ” desc ν•¨μˆ˜λ‚˜ λ§ˆμ°¬κ°€μ§€μ΄λ‹€. p에 ν•¨μˆ˜ 호좜 μ—°μ‚°μž( ) λ₯Ό λΆ™μ—¬ μ‹€ν–‰ν•˜λ©΄ desc ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ” 것이닀.

	
    // ν•¨μˆ˜μ˜ λ°˜ν™˜νƒ€μž…μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 예제

	func plus(a: Int, b: Int) -> Int {
    	return a + b
    }
	
    func plus(a: Int, b: Int) -> Int {
    	return a - b
    }
    
    func plus(a: Int, b: Int) -> Int {
    	return a * b
    }
    
    func plus(a: Int, b: Int) -> Int {
    	guard b !0 = else {
        	return 0
        }
    	return a / b
    }
    
    func calc(_ operand: String) -> (Int, Int) -> Int {
        switch operand {
        case "+" :
            return plus
        case "-" :
            return minus
        case "*" :
            return time
        case "/" :
            return divide
        default :
            return plus
        }
    }

  let res = calc("+")
  res(3,4) // plus(3, 4) = 7

  calc("-")(10, 10) // 0

Β  이처럼 ν•¨μˆ˜μ˜ μ‹€ν–‰ 결과둜 λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•  수 μžˆλŠ” 것이 일급 ν•¨μˆ˜μ˜ νŠΉμ„±μ΄λ‹€.

Β  3. ν•¨μˆ˜μ˜ μΈμžκ°’μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 있음

Β  일급 ν•¨μˆ˜λŠ” λ°˜ν™˜κ°’μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆμ„ 뿐 μ•„λ‹ˆλΌ λ‹€λ₯Έ ν•¨μˆ˜μ˜ μΈμžκ°’μœΌλ‘œ ν•¨μˆ˜λ₯Ό 전달할 수 μžˆλŠ” νŠΉμ„±λ„ μžˆλ‹€. μžλ°”μŠ€ν¬λ¦½νŠΈμ™€ λ§ˆμ°¬κ°€μ§€λ‘œ μŠ€μœ„ν”„νŠΈμ—λ„ μ½œλ²‘ν•¨μˆ˜(CallBack Function)κ°€ μžˆλŠ”λ° 콜벑 ν•¨μˆ˜λŠ” νŠΉμ • ꡬ문의 싀행이 λλ‚˜λ©΄ μ‹œμŠ€ν…œμ΄ ν˜ΈμΆœν•˜λ„λ‘ 처리된 ν•¨μˆ˜λ‘œ, 콜벑 ν•¨μˆ˜λ₯Ό λ“±λ‘ν•œλ‹€λŠ” 것은 μ‹€ν–‰ν•˜κ³ μž ν•˜λŠ” ꡬ문을 담은 ν•¨μˆ˜λ₯Ό μΈμžκ°’μœΌλ‘œ λ„£λŠ” 것을 μ˜λ―Έν•œλ‹€. 이 λ•Œ μ‚¬μš©λ˜λŠ” κ°œλ…μ΄ 'ν•¨μˆ˜λ₯Ό μΈμžκ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€' 이닀.

	//ν•¨μˆ˜λ₯Ό μΈμžκ°’μœΌλ‘œ μ „λ‹¬ν•˜λŠ” 예제
    
	func incr(param: Int) -> Int {
    	return param + 1
    }
    
    
    //λ§€μ§μ½”λ“œλΌκ³ λ„ 함
    func broker(base: Int, function fn: (Int) -> Int) -> Int {
        return fn(base)
    }

    broker(base: 3, function: incr) // 4
    

1 - 2 ν•¨μˆ˜μ˜ 쀑첩

Β  μŠ€μœ„ν”„νŠΈμ—μ„œ ν•¨μˆ˜λŠ” μ€‘μ²©ν•˜μ—¬ μž‘μ„±ν•  수 μžˆλ‹€. ν•¨μˆ˜ 내에 λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό μž‘μ„±ν•΄μ„œ μ‚¬μš©ν•  수 μžˆλŠ” 것이닀. μ€‘μ²©ν•¨μˆ˜(Nested Function)은 ν•¨μˆ˜ 내에 μž‘μ„±λœ ν•¨μˆ˜μΈ λ‚΄λΆ€ ν•¨μˆ˜(InnerFunction)와 λ‚΄λΆ€ ν•¨μˆ˜λ₯Ό ν¬ν•¨ν•˜λŠ” λ°”κΉ₯μͺ½ ν•¨μˆ˜μΈ μ™ΈλΆ€ ν•¨μˆ˜(Outer Function)으둜 ꡬ뢄할 수 μžˆλ‹€.

Β  ν•¨μˆ˜λ₯Ό μ€‘μ²©ν•΄μ„œ μ •μ˜ν•˜λ©΄ λ‚΄λΆ€ ν•¨μˆ˜λŠ” μ™ΈλΆ€ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ” μˆœκ°„ μƒμ„±λ˜κ³ , μ’…λ£Œλ˜λŠ” μˆœκ°„ μ†Œλ©Έν•œλ‹€. μ™ΈλΆ€ ν•¨μˆ˜λŠ” ν”„λ‘œκ·Έλž¨μ΄ 싀행될 λ•Œ μƒμ„±λ˜κ³  ν”„λ‘œκ·Έλž¨μ΄ μ’…λ£Œλ  λ•Œ μ†Œλ©Έν•˜μ§€λ§Œ, λ‚΄λΆ€ ν•¨μˆ˜λŠ” μ™ΈλΆ€ ν•¨μˆ˜μ˜ μ‹€ν–‰κ³Ό μ’…λ£Œ μ‚¬μ΄μ—μ„œ 생겼닀가 사라진닀. 이것이 λ‚΄λΆ€ ν•¨μˆ˜μ˜ 생λͺ…μ£ΌκΈ°(Life Cycle)이닀.

Β  λ‚΄λΆ€ ν•¨μˆ˜λŠ” 일반적으둜 μ™ΈλΆ€ ν•¨μˆ˜λ₯Ό κ±°μΉ˜μ§€ μ•ŠμœΌλ©΄ μ ‘κ·Όν•  수 μ—†λ‹€ 이 λ•Œλ¬Έμ— λ‚΄λΆ€ ν•¨μˆ˜λŠ” μ™ΈλΆ€μ˜ μ½”λ“œλ‘œλΆ€ν„° μ°¨λ‹¨λ˜λŠ” κ²°κ³Όλ₯Ό κ°€μ Έμ˜€λŠ”λ° 이λ₯Ό ν•¨μˆ˜μ˜ 은닉성이라고 ν•˜λ©° μ€‘μ²©λœ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λ©΄ ν•¨μˆ˜μ˜ 은닉성을 높일 수 μžˆλ‹€.

	// μ™ΈλΆ€ ν•¨μˆ˜
    func outer(base: Int) -> String {
    	// λ‚΄λΆ€ ν•¨μˆ˜
        func inner(inc: Int) -> String {
        	return "\(int)λ₯Ό λ°˜ν™˜"
        }
        let result = inner(inc: base +1)
        return result
    }
	
    outer(base: 3) // 4λ₯Ό λ°˜ν™˜

Β  μœ„ μ½”λ“œμ—μ„œ innerλΌλŠ” ν•¨μˆ˜λŠ” μ™ΈλΆ€μ—μ„œ μ°Έμ‘°ν•  수 μ—†μœΌλ©° 였직 outer ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλ§Œ μ°Έμ‘°ν•  수 μžˆλ‹€. inner ν•¨μˆ˜λŠ” μ™ΈλΆ€λ‘œλΆ€ν„° μ€λ‹‰λ˜μ–΄ μžˆλŠ” 것이닀.

Β  λ‚΄λΆ€ν•¨μˆ˜μ˜ 생λͺ… 주기에 λŒ€ν•΄ μ•Œμ•„λ³Έλ‹€λ©΄, 일반적으둜 ν•¨μˆ˜λŠ” μžμ‹ μ„ μ°Έμ‘°ν•˜λŠ” 곳이 있으면 μƒμ„±λ˜μ—ˆλ‹€κ°€ μ°Έμ‘°ν•˜λŠ” 곳이 사라지면 μ œκ±°λ˜λŠ” 생λͺ… μ£ΌκΈ°λ₯Ό κ°–λŠ”λ‹€. ν•¨μˆ˜μ˜ 생λͺ…μ£ΌκΈ°λŠ” μ°Έμ‘° μΉ΄μš΄νŠΈμ™€ κ΄€λ ¨λ˜μ–΄ μžˆλ‹€. μ°Έμ‘° μΉ΄μš΄νŠΈκ°€ 0μ—μ„œ 1이 λ˜λŠ” μˆœκ°„ μƒμ„±λ˜μ–΄ 1 이상인 λ™μ•ˆ μœ μ§€λ˜λ‹€κ°€, 0이 되면 μ†Œλ©Έν•˜λŠ” 과정을 λ°˜λ³΅ν•˜λŠ” 것이닀.

	μ€‘μš”β—οΈ

	func outer(param: Int) -> (Int) -> String {
    	// λ‚΄λΆ€ ν•¨μˆ˜
        func inner(inc: Int) -> String {
        	return "\(inc)λ₯Ό 리턴"
        }
    	return inner
    }
    
    let fn1 = outer(param: 3) // outer()κ°€ μ‹€ν–‰λ˜κ³ , κ·Έ 결과둜 innerκ°€ λŒ€μž…λ¨
    let fn2 = fn1(30) // inner(inc: 30)κ³Ό 동일
    

Β  μœ„ μ½”λ“œμ—μ„œ μ™ΈλΆ€ν•¨μˆ˜ outerλŠ” let fn1 = outer(param: 3) ꡬ문의 μ‹€ν–‰ μ’…λ£Œμ™€ ν•¨κ»˜ μ œκ±°λ˜μ§€λ§Œ λ‚΄λΆ€ ν•¨μˆ˜μΈ innerκ°€ κ²°κ³Όκ°’μœΌλ‘œ λ°˜ν™˜λ˜μ–΄ μƒμˆ˜ fn1에 μ°Έμ‘°λ˜μ—ˆμœΌλ―€λ‘œ μ°Έμ‘° μΉ΄μš΄νŠΈκ°€ μ‘΄μž¬ν•˜κ³ , μ™ΈλΆ€ν•¨μˆ˜μΈ outerκ°€ μ£½μ—ˆλ”λΌλ„ λ‚΄λΆ€ν•¨μˆ˜μΈ innerλŠ” μ‚΄μ•„μžˆλŠ” 것이닀.

	μ€‘μš”β—οΈ

	func basic(param: Int) -> (Int) -> Int {
    	
        let value = param + 20
        // λ‚΄λΆ€ ν•¨μˆ˜
        func append(add: Int)> Int {
        	return value + add
        }
    	return append
    }
    
   	let result = basic(param: 10)
    result(10) // 였λ₯˜κ°€ μ•ˆλ‚˜κ³  κ²°κ³Ό: 40 ?
    

Β  μœ„ μ½”λ“œμ—μ„œ value에 μ£Όλͺ©ν•΄λ³΄μž!! ν•¨μˆ˜ λ‚΄μ—μ„œ μ •μ˜λœ 값듀은 ν•¨μˆ˜κ°€ μ’…λ£Œλ˜κΈ° μ§μ „κΉŒμ§€λ§Œ μ‘΄μž¬ν•˜λ―€λ‘œ value μƒμˆ˜κ°€ let result = basic(param: 10) 이 ꡬ문이 μ’…λ£Œλ˜κΈ° μ§μ „κΉŒμ§€λ§Œ μ‘΄μž¬ν•΄μ•Ό ν•œλ‹€. λ”°λΌμ„œ 였λ₯˜κ°€ λ°œμƒν•  것이라고 μ˜ˆμƒν–ˆμ§€λ§Œ 40μ΄λΌλŠ” κ²°κ³Όκ°€ λ‚˜μ™”λ‹€. μ΄λŠ” append ν•¨μˆ˜κ°€ ν΄λ‘œμ €(Closure)λ₯Ό κ°–κΈ° λ•Œλ¬Έμ΄λ‹€. ν΄λ‘œμ €λž€ λ‚΄λΆ€ ν•¨μˆ˜μ™€ λ‚΄λΆ€ ν•¨μˆ˜μ— 영ν–₯을 λ―ΈμΉ˜λŠ” μ£Όλ³€ ν™˜κ²½(Context)을 λͺ¨λ‘ ν¬ν•¨ν•œ 객체이닀. μ—¬κΈ°μ„œ μ£Όλ³€ ν™˜κ²½μ΄λž€ λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œ μ°Έμ‘°ν•˜λŠ” λͺ¨λ“  μ™ΈλΆ€ λ³€μˆ˜λ‚˜ μƒμˆ˜ κ°’, 그리고 λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œ μ°Έμ‘°ν•˜λŠ” λ‹€λ₯Έ κ°μ²΄κΉŒμ§€λ₯Ό λ§ν•œλ‹€.

Β  ν΄λ‘œμ €λŠ” κ°μ²΄μžμ²΄κ°€ μ•„λ‹Œ 값을 ν¬ν•¨ν•˜λŠ” 것이닀. λ”°λΌμ„œ let result = basic(param: 10)이 싀행됬을 λ•Œ result에 μ €μž₯λ˜λŠ” ν΄λ‘œμ €λŠ” λ‹€μŒκ³Ό 같은 ν˜•νƒœλ‘œ μ €μž₯λ˜λŠ” 것이닀.

	func append(add: Int)> Int {
        	return 30 + add
    }


2. ν΄λ‘œμ €β—οΈ

Β  μœ„μ—μ„œ μ΄μ•ΌκΈ°ν–ˆλ˜ ν΄λ‘œμ €λŠ” μ†Œν”„νŠΈμ›¨μ–΄ μ•„ν‚€ν…μ²˜μ μΈ κ°œλ…μ΄μ—ˆκ³  μ‹€μ œλ‘œ μŠ€μœ„ν”„νŠΈμ—μ„œμ˜ ν΄λ‘œμ €λŠ” 일회용 ν•¨μˆ˜λ₯Ό μž‘μ„±ν•  수 μžˆλŠ” ꡬ문이닀. 읡λͺ…ν•¨μˆ˜(Anonymous) ν•¨μˆ˜λΌκ³  λΆ€λ₯΄κΈ°λ„ ν•œλ‹€.

Β  μŠ€μœ„ν”„νŠΈμ—μ„œ ν΄λ‘œμ €λΌκ³  λΆ€λ₯΄λŠ” κ°μ²΄λŠ” λ‹€μŒ μ„Έ 가지 경우 쀑 ν•˜λ‚˜μ΄λ‹€.

  1. μ „μ—­ ν•¨μˆ˜: 이름이 있고. μ£Όλ³€ ν™˜κ²½μ—μ„œ μΊ‘μ²˜ν•  μ–΄λ–€ 값도 μ—†λŠ” ν΄λ‘œμ €
  2. 쀑첩 ν•¨μˆ˜: 이름이 있고 μžμ‹ μ„ λ‘˜λŸ¬μ‹Ό ν•¨μˆ˜λ‘œλΆ€ν„° 값을 μΊ‘μ²˜ν•  수 μžˆλŠ” ν΄λ‘œμ €
  3. ν΄λ‘œμ € ν‘œν˜„μ‹ 이름이 μ—†κ³  μ£Όλ³€ ν™˜κ²½μœΌλ‘œλΆ€ν„° 값을 μΊ‘μ²˜ν•  수 μžˆλŠ” κ²½λŸ‰ λ¬Έλ²•μœΌλ‘œ μž‘μ„±λœ ν΄λ‘œμ €

2 - 1 ν΄λ‘œμ € ν‘œν˜„μ‹

	{ (λ§€κ°œλ³€μˆ˜) -> λ°˜ν™˜ νƒ€μž… in 
    	μ‹€ν–‰ν•  ꡬ문
    }
    
    
    { () -> () in
    	print("ν΄λ‘œμ € μ‹€ν–‰")
    }
    
    
    // μž‘μ„±λœ ν΄λ‘œμ € ν‘œν˜„μ‹μ€ 그자체둜 ν•¨μˆ˜λΌκ³  ν•  수 있음
    let f = { () -> Void in
    	print("ν΄λ‘œμ € μ‹€ν–‰")
    }
    f() // ν΄λ‘œμ € μ‹€ν–‰
    
    
    // ν΄λ‘œμ € ν‘œν˜„μ‹μ„ 할당받을 μƒμˆ˜ fλ§ˆμ € μƒλž΅ν•˜κ³  싢을 λ•Œ μ΄λ ‡κ²Œ μž‘μ„±ν•΄λ„ 됨
    ({ () -> Void in
    	print("ν΄λ‘œμ € μ‹€ν–‰")
    })()  // ν΄λ‘œμ € μ‹€ν–‰
    



2 - 2 ν΄λ‘œμ € ν‘œν˜„μ‹κ³Ό κ²½λŸ‰ 문법

	var val = [1,9,5,7,3,2]
    
    func order(s1: Int, s2: Int) -> Bool {
    	if s1 > s2 {
        	return true
        } else {
        	return false
        }
    }
    
    val.sort(by: order)
    
    
    // ν΄λ‘œμ € ν‘œν˜„μ‹μœΌλ‘œ
    {
    	(s1: Int, s2: Int) -> Bool {
    	if s1 > s2 {
        	return true
        } else {
        	return false
        }
    }

    val.sorted(by: {
        (s1: Int, s2: Int) -> Bool in
        if s1 > s2{
            return true
        }else {
            return false
        }
    })

    //κ°„κ²°ν™”
    val.sort(by: {(s1: Int, s2: Int) -> Bool in return s1 > s2})

    val.sort(by: {(s1:Int, s2: Int) in return s1 > s2})

    val.sort(by: {s1, s2 in return s1 > s2})

    val.sort(by: { $0 > $1})



2 - 3 트레일링 ν΄λ‘œμ €(Trailing Closure)

Β  트레일링 ν΄λ‘œμ €λŠ” ν•¨μˆ˜μ˜ λ§ˆμ§€λ§‰ μΈμžκ°’μ΄ ν΄λ‘œμ €μΌ λ•Œ, 이λ₯Ό μΈμžκ°’ ν˜•μ‹μœΌλ‘œ μž‘μ„±ν•˜λŠ” λŒ€μ‹  ν•¨μˆ˜μ˜ 뒀에 꼬리처럼 뢙일 수 μžˆλŠ” 문법을 μ˜λ―Έν•œλ‹€.

	
    //κ·Έλƒ₯ ν΄λ‘œμ €
    value.sort(by: {(s1, s2) in
    	return s1 > s2
    })
	
    //트레일링 ν΄λ‘œμ €
	value.sort() { (s1, s2) in
    	return s1 > s2
    }

Β  μœ„μ—μ„œ κ·Έλƒ₯ ν΄λ‘œμ €μ™€ 트레일링 ν΄λ‘œμ €λŠ” 달라 λ³΄μ΄λŠ” 것이 거의 μ—†λ‹€. κ·ΈλŸ¬λ‚˜ μΈμžκ°’μœΌλ‘œ μ‚¬μš©λ˜λ˜ ν΄λ‘œμ €κ°€ ν†΅μ§Έλ‘œ λ°”κΉ₯으둜 λΉ μ Έλ‚˜μ˜¨ λ‹€μŒ, sort( ) λ©”μ†Œλ“œμ˜ λ’€μͺ½μ— 달라 뢙은 것을 λ³Ό 수 μžˆλ‹€.

Β  μ΄λ ‡κ²Œ κ΄„ν˜Έ ν•˜λ‚˜ 차이 μ΄μ§€λ§Œ μ—΄κ³  λ‹«λŠ” λ²”μœ„κ°€ 넓어지면 ν—·κ°ˆλ¦΄μˆ˜λ„ μžˆλ‹€. λ˜ν•œ 밑에 트레일링 ν΄λ‘œμ €λŠ” μš°λ¦¬κ°€ 자주 μ‚¬μš©ν•˜λŠ” if λ¬Έκ³Ό μ½”λ“œμ˜ κ΄„ν˜Έ ν˜•νƒœκ°€ λΉ„μŠ·ν•˜κΈ° λ•Œλ¬Έμ— 훨씬 μ΅μˆ™ν•˜λ‹€λŠ” μž₯점이 μžˆλ‹€.

	value.sort { (s1, s2) in
    	return s1 > s2
    }

Β  μœ„ μ½”λ“œμ™€ 같이 μΈμžκ°’μ΄ ν•˜λ‚˜μΌ 경우 sort λ©”μ†Œλ“œ λ’€μ˜ κ΄„ν˜Έ() λ˜ν•œ μƒλž΅ν•  수 μžˆλ‹€. κ·ΈλŸ¬λ‚˜ μΈμžκ°’μ΄ μ—¬λŸ¬κ°œλΌλ©΄ λ¬΄μž‘μ • κ΄„ν˜Έλ₯Ό μƒλž΅ν•΄μ„œλŠ” μ•ˆλœλ‹€.


2 - 4 Β  @escapingκ³Ό @autoescape

Β  ν΄λ‘œμ €λ₯Ό ν•¨μˆ˜λ‚˜ λ©”μ†Œλ“œμ˜ μΈμžκ°’μœΌλ‘œ μ‚¬μš©ν•  λ•Œμ—λŠ” μš©λ„μ— 따라 @escapingκ³Ό @autoclosure 속성을 λΆ€μ—¬ν•  수 μžˆλ‹€.

@escaping

Β  @escaping 속성은 μΈμžκ°’μœΌλ‘œ μ „λ‹¬λœ ν΄λ‘œμ €λ₯Ό μ €μž₯ν•΄ λ‘μ—ˆλ‹€κ°€, λ‚˜μ€‘μ— λ‹€λ₯Έ κ³³μ—μ„œλ„ μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν—ˆμš©ν•΄μ£ΌλŠ” 속성이닀.

	func callback(fn: () -> Void) {
    	fn()
    }
	
    callback {
    	print("Closure μ‹€ν–‰")
    }
	
    // Closure μ‹€ν–‰

Β  μ •μ˜λœ ν•¨μˆ˜ callback(fn:)은 λ§€κ°œλ³€μˆ˜λ₯Ό 톡해 μ „λ‹¬λœ ν΄λ‘œμ €λ₯Ό ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‹€ν–‰ν•˜λŠ” 역할을 ν•œλ‹€.

	func callback(fn: () -> Void) {
    	let f = fn // ν΄λ‘œμ €λ₯Ό μƒμˆ˜ f에 λŒ€μž…
        f() // λŒ€μž…λœ ν΄λ‘œμ €λ₯Ό μ‹€ν–‰
    }
    
    //였λ₯˜: Non-escaping parameter 'fn' may only be called

Β  κ·ΈλŸ¬λ‚˜ λ‹€μŒκ³Ό 같이 μ½”λ“œλ₯Ό λ°”κΎΈλ©΄ Non-escaping νŒŒλΌλ―Έν„°μΈ 'fn'은 였직 직접 ν˜ΈμΆœν•˜λŠ” κ²ƒλ§Œ κ°€λŠ₯ν•˜λ‹€κ³  였λ₯˜κ°€ λ‚œλ‹€.
기본적으둜 μŠ€μœ„ν”„νŠΈμ—μ„œλŠ” ν•¨μˆ˜μ˜ μΈμžκ°’μœΌλ‘œ μ „λ‹¬λœ ν΄λ‘œμ €(읡λͺ…ν•¨μˆ˜)λŠ” 기본적으둜 νƒˆμΆœλΆˆκ°€(non-escape)의 성격을 가진닀. μ΄λŠ” ν•΄λ‹Ή ν΄λ‘œμ €λ₯Ό ν•¨μˆ˜λ‚΄μ—μ„œ, 직접 싀행을 μœ„ν•΄μ„œλ§Œ μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 것을 μ˜λ―Έν•˜λ©° ν•¨μˆ˜λ‚΄λΆ€λΌκ³  ν•˜λ”λΌλ„ λ³€μˆ˜λ‚˜ μƒμˆ˜μ— λŒ€μž…ν•  수 μ—†λ‹€.

Β  λ³€μˆ˜λ‚˜ μƒμˆ˜μ— λŒ€μž…ν•˜λŠ” 것을 ν—ˆμš©ν•œλ‹€λ©΄ λ‚΄λΆ€ ν•¨μˆ˜λ₯Ό ν†΅ν•œ 캑처(Capture) κΈ°λŠ₯을 μ΄μš©ν•˜μ—¬ ν΄λ‘œμ €κ°€ ν•¨μˆ˜ λ°”κΉ₯으둜 νƒˆμΆœν•  수 있기 λ•Œλ¬Έμ΄λ‹€. μ—¬κΈ°μ„œ λ§ν•˜λŠ” νƒˆμΆœμ΄λž€, ν•¨μˆ˜ λ‚΄λΆ€ λ²”μœ„λ₯Ό λ²—μ–΄λ‚˜μ„œ μ‹€ν–‰λ˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

Β  λ˜ν•œ μΈμžκ°’μœΌλ‘œ μ „λ‹¬λœ ν΄λ‘œμ €λŠ” μ€‘μ²©λœ λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œλ„ μ‚¬μš©ν•  수 μ—†λ‹€. λ‚΄λΆ€ ν•¨μˆ˜μ—μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν—ˆμš©ν•  경우, 이 μ—­μ‹œ μ»¨ν…μŠ€νŠΈ(Context)의 캑처λ₯Ό 톡해 νƒˆμΆœλ  수 있기 λ•Œλ¬Έμ΄λ‹€.

	func callback(fn: () -> Void) {
    	func innerCallback() {
        	fn()
        }
    }

Β  λ”°λΌμ„œ μœ„ μ½”λ“œλ₯Ό μ‹€ν–‰ν•˜λ©΄ 였λ₯˜κ°€ λ‚œλ‹€.


ν•˜μ§€λ§Œ μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ‹€ 보면 ν΄λ‘œμ €λ₯Ό λ³€μˆ˜λ‚˜ μƒμˆ˜μ— λŒ€μž…ν•˜κ±°λ‚˜ 쀑첩 ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œ μ‚¬μš©ν•΄μ•Ό ν•  κ²½μš°κ°€ μžˆλ‹€. μ΄λ•Œ μ‚¬μš©ν•˜λŠ” 것이 @escaping 속성이닀.

	func callback(fn: @escaping() -> Void) {
    	let f = fn // ν΄λ‘œμ €λ₯Ό μƒμˆ˜ f에 λŒ€μž…
        f() // λŒ€μž…λœ ν΄λ‘œμ €λ₯Ό μ‹€ν–‰
    }
    	
    callback {
    	print("Closure μ‹€ν–‰")
    }
	
    // Closure μ‹€ν–‰

Β  μœ„μ—μ„œ 였λ₯˜κ°€ λ‚¬λ˜ ν•¨μˆ˜μΈλ° μ—¬κΈ°μ„œ λ§€κ°œλ³€μˆ˜ νƒ€μž…μ— μ•žμ— @escaping 속성을 λΆ™μ—¬ μ£Όλ‹ˆ 였λ₯˜ 없이 정상 λ™μž‘ν•˜μ˜€λ‹€.

Β  이제 μž…λ ₯된 ν΄λ‘œμ €λŠ” λ³€μˆ˜λ‚˜ μƒμˆ˜μ— μ •μƒμ μœΌλ‘œ ν• λ‹Ήλ˜κ³ , μ€‘μ²©λœ λ‚΄λΆ€ ν•¨μˆ˜μ— μ‚¬μš©ν•  수 있고, ν•¨μˆ˜ λ°”κΉ₯μœΌλ‘œλ„ 전달할 수 μžˆλ‹€.

Β  νƒˆμΆœ κ°€λŠ₯ν•œ ν΄λ‘œμ €κ°€ λœκ²ƒμ΄λ‹€.

@autoclosure

Β  @autoclosure 속성은 μΈμžκ°’μœΌλ‘œ μ „λ‹¬λœ 일반 κ΅¬λ¬Έμ΄λ‚˜ ν•¨μˆ˜ 등을 ν΄λ‘œμ €λ‘œ λž˜ν•‘(Wrapping)ν•˜λŠ” 역할을 ν•œλ‹€. μ‰½κ²Œ 말해 일반 ꡬ문을 μΈμžκ°’μœΌλ‘œ 넣더라도 μ»΄νŒŒμΌλŸ¬κ°€ μ•Œμ•„μ„œ ν΄λ‘œμ €λ‘œ λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•œλ‹€λŠ” 것이닀.

	func condition(stmt: () -> Bool) {
    	if stmt() == true {
        	print("κ²°κ³ΌλŠ” μ°Έμž…λ‹ˆλ‹€.")
        } else {
        	print("κ²°κ³Όκ°€ κ±°μ§“μž…λ‹ˆλ‹€.")
        } 
    }
    
    // μ‹€ν–‰ 방법 1: 일반 ꡬ문
    condition(stmt: {
    	4 > 2
    })
    
    
    //μ‹€ν–‰ 방법 2: κ²½λŸ‰ν™” 문법
    
 	// κ²½λŸ‰ν™” λ˜μ§€ μ•Šμ€ ν΄λ‘œμ € 전체 문법
    condition{ () -> Bool in
    	return (4 > 2)
    }
    
    // ν΄λ‘œμ € νƒ€μž… μ„ μ–Έ μƒλž΅
    condition{
    	return (4 > 2)
    }
   
   
    // ν΄λ‘œμ € λ°˜ν™˜κ΅¬λ¬Έ μƒλž΅
    condition {
    	4 > 2
    }

Β  μœ„μ½”λ“œμ—μ„œ ν•¨μˆ˜κ°€ 있고 κ·Έ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” μ—¬λŸ¬κ°€μ§€ 방법을 λ³΄μ•˜λ‹€. ν΄λ‘œμ €μ˜ κ²½λŸ‰ν™” 문법을 μ΄μš©ν•˜λ©΄μ„œ 더 짧고 κ°„κ²°ν•œ μ½”λ“œλ‘œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆμ—ˆλ‹€.

Β  @autoclosure둜 λ‹€μ‹œ λŒμ•„κ°€λ³΄λ©΄ μœ„μ—μ„œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ μ›ν•˜λŠ” ꡬ문을 '{}'ν˜•νƒœλ‘œ 감싸 ν΄λ‘œμ € ν˜•νƒœλ‘œ λ§Œλ“  λ‹€μŒμ— μΈμžκ°’μœΌλ‘œ λ§Œλ“€μ–΄ 전달해야 ν•œλ‹€λŠ” μ œμ•½μ΄ μžˆλ‹€. ν•˜μ§€λ§Œ @autoclosure() 속성을 μ‚¬μš©ν•œλ‹€λ©΄

	func condition(stmt: @autoclosure() -> Bool) {
    	if stmt() == true {
        	print("κ²°κ³ΌλŠ” μ°Έμž…λ‹ˆλ‹€.")
        } else {
        	print("κ²°κ³Όκ°€ κ±°μ§“μž…λ‹ˆλ‹€.")
        } 
    }
    
    //ν•¨μˆ˜ μ‹€ν–‰
    condition(stmt: (4 > 2))

Β  λ‹€μŒκ³Ό 같이 μΈμžκ°’μ„ '{}' ν˜•νƒœκ°€ μ•„λ‹Œ '()' ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ ν•΄μ€€λ‹€. 훨씬 μ΅μˆ™ν•˜κ³  μžμ—°μŠ€λŸ¬μš΄ ꡬ문으둜 λ§Œλ“€μ–΄μ£ΌλŠ” μ…ˆμ΄λ‹€.

Β  λ˜ν•œ @autoclosure속성을 μ‚¬μš©ν•˜λ©΄ '지연 μ‹€ν–‰'을 ν•  수 μžˆλ‹€.

	//빈 λ°°μ—΄
    var arrs = [String]()
    
    func addVars(fn: @autoclosure () -> Void) {
    	// λ°°μ—΄ μš”μ†Œλ₯Ό 3κ°œκΉŒμ§€ μΆ”κ°€ν•˜μ—¬ μ΄ˆκΈ°ν™”
        arrs = Array(repeating: "", count: 3)
        // μΈμžκ°’μœΌλ‘œ μ „λ‹¬λœ ν΄λ‘œμ € μ‹€ν–‰
        fn()
    }
    
    // ꡬ문 1: μ•„λž˜ ꡬ문은 였λ₯˜κ°€ λ°œμƒν•œλ‹€. 
    arrs.insert("KR", at: 1)
    
    // ꡬ문 2: 였λ₯˜ λ°œμƒν•˜μ§€ μ•ŠμŒ
    addVars(fn: arrs.insert("KR", at: 1))

Β  빈 λ°°μ—΄ arrsλ₯Ό μ •μ˜ν•˜μ˜€κ³  addVars(fn:) ν•¨μˆ˜ λ‚΄λΆ€μ—μ„œλŠ” 이 λ°°μ—΄μ˜ μ‚¬μ΄μ¦ˆλ₯Ό 3으둜 ν™•μž₯ν•˜κ³  빈 κ°’λ“€λ‘œ μ΄ˆκΈ°ν™”ν–ˆλ‹€.

Β  addVars(fn:) ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜κΈ° μ „κΉŒμ§€ 이 ν•¨μˆ˜μ˜ μΈλ±μŠ€λŠ” 0κΉŒμ§€ 밖에 μ—†μ–΄ arrs.insert(at:) λ©”μ†Œλ“œλŠ” 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

Β  κ·ΈλŸ¬λ‚˜ λ™μΌν•œ ꡬ문을 addVars(fn:) ν•¨μˆ˜μ˜ μΈμžκ°’μœΌλ‘œ λ„£μœΌλ©΄ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. μ›λž˜ ꡬ문은 μž‘μ„±ν•˜λŠ” μˆœκ°„μ— μ‹€ν–‰λ˜μ§€λ§Œ, ν•¨μˆ˜ 내에 μž‘μ„±λœ ꡬ문은 ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜κΈ° μ „κΉŒμ§€λŠ” μ‹€ν–‰λ˜μ§€ μ•Šμ•„ 이λ₯Ό 지연 싀행이라고 ν•œλ‹€. @autoclosure 속성이 λΆ€μ—¬λœ μΈμžκ°’μ€ 일반 ꡬ문 ν˜•νƒœμ΄μ§€λ§Œ μ»΄νŒŒμΌλŸ¬μ— μ˜ν•΄ ν΄λ‘œμ €, ν•¨μˆ˜λ‘œ 감싸지기 λ•Œλ¬Έμ— μœ„μ™€ 같이 μž‘μ„±ν•΄λ„ addVars(fn:) ν•¨μˆ˜ μ‹€ν–‰ μ „κΉŒμ§€λŠ” μ‹€ν–‰λ˜μ§€ μ•ŠμœΌλ©°, ν•΄λ‹Ή ꡬ문이 싀행될 λ•Œμ—λŠ” 이미 λ°°μ—΄μ˜ μΈλ±μŠ€κ°€ λŠ˜μ–΄λ‚œ ν›„μ΄λ―€λ‘œ 였λ₯˜κ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ” 것이닀.

profile
πŸ§‘πŸ»β€πŸ’»iOS

0개의 λŒ“κΈ€