λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
⌨️ Language/swift

[Swift] λ³€μˆ˜μ™€ ν”„λ‘œνΌν‹°1

by hyebin (Helia) 2024. 3. 15.
λ°˜μ‘ν˜•

* 2023λ…„ Apple Developer Academy @ POSTECH μ—μ„œ swift μŠ€ν„°λ””λ₯Ό ν•˜λ©° κ³΅λΆ€ν•œ λ‚΄μš©μž…λ‹ˆλ‹€

 

1. λ³€μˆ˜/ν”„λ‘œνΌν‹°μ˜ κ°œλ…

λ³€μˆ˜μ˜ κ°œλ…

  • ν”„λ‘œκ·Έλž¨μ—μ„œ 데이터λ₯Ό μ €μž₯ν•˜λŠ” λ©”λͺ¨λ¦¬ 곡간
  • 이름, ν˜•, λ©”λͺ¨λ¦¬ μ£Όμ†Œ, κ°’, μ˜μ—­ λ“±μœΌλ‘œ νŠΉμ„±μ„ ꡬ뢄지어 λ³Ό 수 있음
var number1 : Int = 20
  • 이름 = λ³€μˆ˜λ₯Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ μ‚¬μš© ⇒ number1
    • 고유 이름을 ‘μ‹λ³„μž’(Identifier)’라고 함
  • ν˜• = νƒ€μž… = λ°μ΄ν„°μ˜ μžλ£Œν˜• ⇒ Int
  • κ°’ = λ³€μˆ˜μ— λ“€μ–΄κ°€λŠ” 데이터 ⇒ 20
  • μ˜μ—­ = λ³€μˆ˜κ°€ μ‚¬μš© κ°€λŠ₯ν•œ λ²”μœ„

λ³€μˆ˜μ™€ μƒμˆ˜

λ³€μˆ˜

  • λ³€ν•  수 μžˆλŠ” 값을 μ €μž₯
  • var λ³€μˆ˜λͺ… : 데이터 νƒ€μž… = κ°’
  • 데이터 νƒ€μž…μ€ μƒλž΅ κ°€λŠ₯

μƒμˆ˜

  • λ³€ν•˜μ§€ μ•ŠλŠ” μΌμ •ν•œ 값을 μ €μž₯
  • let μƒμˆ˜λͺ… : 데이터 νƒ€μž… = κ°’
  • 데이터 νƒ€μž… μƒλž΅ κ°€λŠ₯

ν”„λ‘œνΌν‹°μ˜ κ°œλ…

  • 클래슀(class), ꡬ쑰(structure), ν˜Ήμ€ μ—΄κ±°ν˜•(enumeration) λ“±μ˜ νŠΉμ • μΈμŠ€ν„΄μŠ€μ™€ κ΄€λ ¨λœ κ°’
  • dot notation syntaxλ₯Ό μ‚¬μš©ν•˜μ—¬ μ ‘κ·Όν•˜κ±°λ‚˜ μˆ˜μ •ν•  수 있음
class MyClass {
    static var numberOfInstances = 0
    
    init() {
        MyClass.numberOfInstances += 1
    }
    
    static var currentNumberOfInstances: Int {
        return numberOfInstances
    }
}

let instance1 = MyClass()
let instance2 = MyClass()
print(MyClass.currentNumberOfInstances) // Output: 2

 

❓ λ³€μˆ˜μ™€ ν”„λ‘œνΌν‹°μ˜ 차이?

  • μ˜μ—­
    • λ³€μˆ˜: ν•¨μˆ˜μ™€ 같이 νŠΉμ • μ½”λ“œ 블둝 μ•ˆμ—μ„œ μ‚¬μš©/선언될 수 있음
    • ν”„λ‘œνΌν‹°: ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€λ₯Ό μ°Έμ‘°ν•˜λŠ” μ–΄λ–€ μ½”λ“œμ— μ˜ν•΄μ„œλ“  μ ‘κ·Ό/μˆ˜μ •λ  수 있음
  • μ ‘κ·Ό ν†΅μ œ
    • λ³€μˆ˜: private, internal, publicκ³Ό 같이 μ–΄λŠ λΆ€λΆ„μ˜ μ½”λ“œκ°€ ν•΄λ‹Ή λ³€μˆ˜μ— μ ‘κ·Όν•  수 μžˆλŠ”μ§€ κ²°μ •ν•  수 있음
    • ν”„λ‘œνΌν‹°: ν”„λ‘œνΌν‹° κ·Έ μžμ²΄κ°€ μ•„λ‹ˆλΌ ν”„λ‘œνΌν‹°μ™€ κ΄€λ ¨λœ getter 그리고/ν˜Ήμ€ setter λ©”μ†Œλ“œμ— λŒ€ν•œ 접근을 ν†΅μ œν•˜κΈ° μœ„ν•΄ μ‚¬μš©
  • μ΄ˆκΈ°ν™”
    • λ³€μˆ˜: μ‚¬μš©ν•˜κΈ° 전에 무쑰건 μ΄ˆκΈ°ν™”λ˜μ–΄μ•Ό 함
    • ν”„λ‘œνΌν‹°
      • μƒμ„±μž(initializer)λ₯Ό ν†΅ν•΄μ„œ 초기 값을 μ΄ˆκΈ°ν™”
      • 초기 값이 μ œκ³΅λ˜μ§€ μ•ŠλŠ”λ‹€λ©΄ κΈ°λ³Έ 값을 ν†΅ν•΄μ„œ μžλ™μ μœΌλ‘œ μ΄ˆκΈ°ν™”
  • μš©λ„
    • λ³€μˆ˜: μ½”λ“œ 블둝 μ•ˆμ—μ„œ μž„μ‹œ κ°’ ν˜Ήμ€ 쀑간 값을 λ‹΄κΈ° μœ„ν•΄ μ‚¬μš©
    • ν”„λ‘œνΌν‹°: νƒ€μž…μ˜ μΈμŠ€ν„΄μŠ€μ™€ κ΄€λ ¨ν•˜μ—¬ 값을 μ €μž₯ν•˜κ±°λ‚˜ κ²€μƒ‰ν•˜κΈ° μœ„ν•΄ μ‚¬μš©

 

2. λ³€μˆ˜/ν”„λ‘œνΌν‹°μ˜ μ’…λ₯˜

λ³€μˆ˜μ˜ μ’…λ₯˜

  • μ˜μ—­/λ©”λͺ¨λ¦¬ κΈ°μ€€
    • μ§€μ—­ λ³€μˆ˜
      • 블둝(ex - ν•¨μˆ˜)λ‚΄μ—μ„œ μ„ μ–Έλ˜μ–΄ 블둝 λ‚΄μ—μ„œλ§Œ μ‚¬μš©ν•  수 μžˆλŠ” λ³€μˆ˜
      • μ²˜λ¦¬κ°€ λλ‚œ μ΄ν›„μ—λŠ” ν•΄λ‹Ή λ³€μˆ˜ 이용 λΆˆκ°€
      • μƒμœ„ ν˜Ήμ€ λ‹€λ₯Έ 블둝에 같은 μ΄λ¦„μ˜ λ³€μˆ˜κ°€ μžˆλ”λΌλ„ λ©”λͺ¨λ¦¬ 곡간이 λ‹€λ₯΄λ―€λ‘œ λ‹€λ₯Έ λ³€μˆ˜μž„
    • μ „μ—­ λ³€μˆ˜
      • ν”„λ‘œκ·Έλž¨ λ‚΄ μ „μ²΄μ—μ„œ μ‚¬μš© κ°€λŠ₯ν•œ λ³€μˆ˜
    • 맀개 λ³€μˆ˜
      • λ‹€λ₯Έ 블둝에 μ „λ‹¬λ˜λŠ” λ³€μˆ˜
      • λ³€μˆ˜μ— μ €μž₯λ˜μ–΄μžˆλŠ” κ°’ 뿐만 μ•„λ‹ˆλΌ, ν•΄λ‹Ή λ©”λͺ¨λ¦¬ 곡간 자체λ₯Ό ν™œμš©ν•˜κΈ° μœ„ν•˜μ—¬ λ©”λͺ¨λ¦¬ κ³΅κ°„μ˜ μ£Όμ†Œκ°’μ„ 이용 (포인터)
  • νƒ€μž… κΈ°μ€€
μ’…λ₯˜ μ„€λͺ…
μˆ«μžν˜• λ³€μˆ˜ (Numeric variables) - μ •μˆ˜, λΆ€λ™μ†Œμˆ˜μ  숫자 λ“±μ˜ 숫자 데이터λ₯Ό μ €μž₯ν•˜λŠ” λ³€μˆ˜
-  Int  ,  Float  ,  Double  λ“±
λ¬Έμžν˜• λ³€μˆ˜ (Character variables) - 단일 문자 데이터λ₯Ό μ €μž₯ν•˜λŠ” λ³€μˆ˜
-  Character 
λ¬Έμžμ—΄ λ³€μˆ˜ (String variables) - λ¬Έμžμ—΄ 데이터λ₯Ό μ €μž₯ν•˜λŠ” λ³€μˆ˜
-  String 
λΆˆλ¦¬μ–Έ λ³€μˆ˜ (Boolean variables) - 논리값( true λ˜λŠ”  false )을 μ €μž₯ν•˜λŠ” λ³€μˆ˜
-  Bool 
λ°°μ—΄ λ³€μˆ˜ (Array variables) - μ—¬λŸ¬ 개의 데이터λ₯Ό 순차적으둜 μ €μž₯ν•˜λŠ” λ³€μˆ˜
-  Array 
ꡬ쑰체 λ³€μˆ˜ (Struct variables) - μ„œλ‘œ λ‹€λ₯Έ 데이터 νƒ€μž…μ„ μ‘°ν•©ν•˜μ—¬ μƒˆλ‘œμš΄ 데이터 νƒ€μž…μ„ λ§Œλ“œλŠ” 데 μ‚¬μš©λ˜λŠ” λ³€μˆ˜
-  struct 
μ—΄κ±°ν˜• λ³€μˆ˜ (Enum variables) - μ„œλ‘œ λ‹€λ₯Έ μœ ν˜•μ˜ 값을 κ°€μ§„ 데이터λ₯Ό ν•˜λ‚˜λ‘œ λ¬ΆλŠ” 데 μ‚¬μš©λ˜λŠ” λ³€μˆ˜
-  enum 
μ˜΅μ…”λ„ λ³€μˆ˜ (Optional variables) - 값이 없을 수 μžˆλŠ” 데이터λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λ³€μˆ˜
-  Optional 

 

ν”„λ‘œνΌν‹°μ˜ μ’…λ₯˜

μ €μž₯ ν”„λ‘œνΌν‹° (Stored Property)

struct Person {
    var name: String
    var age: Int
}

var john = Person(name: "John", age: 30)
print(john.age) // Output: 30
  • μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ™€ μƒμˆ˜
  • 값을 μ €μž₯ν•  λ•Œ μ‚¬μš©
  • μ΄ˆκΈ°κ°’μ„ μ„€μ • ν•  수 있고, 클래슀 κ΅¬μ‘°μ²΄μ—μ„œλŠ” μΈμŠ€ν„΄μŠ€μ™€ μ—°κ΄€λœ 값을 μ €μž₯함.
  • ꡬ쑰체, ν΄λž˜μŠ€μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯
  • μ§€μ—° μ €μž₯ ν”„λ‘œνΌν‹°:  lazy var 
class Position {
  lazy var point: CoordinatePoint = CoordinatePoint()
}
  • 호좜 되기 전에 κ°’ μ΄ˆκΈ°ν™”X
  • λΆˆν•„μš”ν•œ μ„±λŠ₯ μ €ν•˜, λ©”λͺ¨λ¦¬ μ‚¬μš© κ°μ†Œ
  • 클래슀 κ΅¬μ‘°μ²΄μ—λ§Œ μ‚¬μš© κ°€λŠ₯
  • lazy ν‚€μ›Œλ“œλ₯Ό μ„ μ–Έ μ•žμ— μž‘μ„±ν•΄μ„œ μ‚¬μš©ν•¨.
  • μƒμˆ˜(let)μ—λŠ” μ‚¬μš© κΈˆμ§€ → μƒμˆ˜λŠ” μΈμŠ€ν„΄μŠ€κ°€ μ™„μ „νžˆ μƒμ„±λ˜κΈ° 전에 μ΄ˆκΈ°ν™” ν•΄μ•Όν•˜λ―€λ‘œ μ–΄μšΈλ¦¬μ§€ μ•ŠμŒ

μ—°μ‚° ν”„λ‘œνΌν‹° (Computed Property)

struct Rectangle {
    var width: Double
    var height: Double
    
    var area: Double {
        return width * height
    }
}

var rect = Rectangle(width: 5.0, height: 10.0)
print(rect.area) // Output: 50.0
  • μ‹€μ œλ‘œ 값을 μ €μž₯ν•˜μ§€λŠ” μ•Šκ³ , getκ³Ό set ν‚€μ›Œλ“œλ‘œ 값을 κ°„μ ‘μ μœΌλ‘œ μ„€μ •ν•˜κ±°λ‚˜ λ°›λŠ” ν”„λ‘œνΌν‹°
  • 일반적으둜 λ‹€λ₯Έ μ—°μ‚°μ΄λ‚˜ λ‹€λ₯Έ ν”„λ‘œνΌν‹°λ₯Ό 기반으둜 값을 μ–»μ–΄λ‚΄κΈ° μœ„ν•΄ μ‚¬μš©
  • 클래슀 ꡬ쑰체 μ—΄κ±°ν˜•μ—λ„ μ‚¬μš©
  •  getter 
struct Circle {
    var radius: Double
    
    var area: Double {
        get {
            return Double.pi * radius * radius
        }
    }
}

var circle = Circle(radius: 5.0)
print(circle.area) // Output: 78.53981633974483
  • μΈμŠ€ν„΄μŠ€ λ‚΄λΆ€, μ™ΈλΆ€μ˜ 값을 μ—°μ‚°ν•˜μ—¬ μ μ ˆν•œ 값을 λŒλ €μ£ΌλŠ” μ—­ν• 
  • μ—°μ‚°λœ 값을 μ €μž₯ν•  ν”„λ‘œνΌν‹°κ°€ μžˆμ–΄μ•Ό 함(ν•„μˆ˜λŠ” μ•„λ‹ˆμ§€λ§Œ 일반적)
  •  setter 
class Car {
    private var _fuelLevel: Double = 0.0
    
    var fuelLevel: Double {
        get {
            return _fuelLevel
        }
        set {
            _fuelLevel = min(max(0.0, newValue), 1.0)
        }
    }
}

var car = Car()
car.fuelLevel = 0.5 // call the setter method
print(car.fuelLevel) // Output: 0.5
  • ν”„λ‘œνΌν‹° 값을 κ°„μ ‘μ μœΌλ‘œ μ„€μ •ν•˜λŠ” μ—­ν• (λ‚΄λΆ€κ°€ μ€λ‹‰ν™”λœ 경우 유용)
    • 은닉화: μ™ΈλΆ€μ—μ„œ 객체 λ‚΄λΆ€μ˜ μ ‘κ·Ό/μˆ˜μ • κΆŒν•œμ„ 막은 것
  • λ§€κ°œλ³€μˆ˜ 이름을 μƒλž΅ ν•˜λ©΄ newValueλ₯Ό 톡해 μ ‘κ·Ό κ°€λŠ₯

νƒ€μž… ν”„λ‘œνΌν‹° (Type Property)

struct AudioChannel {
    static let level = 10
    static var maxLevel = 0
}

print(AudioChannel.level) 
print(AudioChannel.maxLevel)
  • μΈμŠ€ν„΄μŠ€μ˜ 속성이 μ•„λ‹Œ, νƒ€μž…μ— λ”°λ₯Έ 속성을 μ •μ˜ν•  수 있음
  • μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹ˆλΌ, νŠΉμ • νƒ€μž…μ—μ„œ μ‚¬μš©ν•¨
  • λ”°λΌμ„œ νƒ€μž… μžμ²΄μ— μ†ν•˜λŠ” ν”„λ‘œνΌν‹°μ΄λ©°, 값이 κ³ μœ ν•¨
  • λͺ¨λ“  μΈμŠ€ν„΄μŠ€κ°€ κ³΅ν†΅μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 값에 μ‚¬μš©
  • μ €μž₯ ν”„λ‘œνΌν‹°, μ—°μ‚° ν”„λ‘œνΌν‹° λͺ¨λ‘ μ‚¬μš© κ°€λŠ₯
  • static ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ κ°’ νƒ€μž…μ—μ„œ νƒ€μž… ν”„λ‘œνΌν‹°λ₯Ό μ„€μ •ν•  수 있음
  • class ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•΄μ„œ 클래슀 νƒ€μž…μ—μ„œ νƒ€μž… ν”„λ‘œνΌν‹°λ₯Ό μ„€μ •ν•  수 있음
  • 값을 κ°€μ Έμ˜¬λ•ŒλŠ” 클래슀의 이름을 ν†΅ν•΄μ„œ κ°€μ Έμ˜¬ 수 있음

ν”„λ‘œνΌν‹° μ˜΅μ €λ²„ (Property Observer)

class Account {
    var credit: Int = 0 {
        willSet {
            print("μž”μ•‘μ΄ \\(credit)μ—μ„œ \\(newValue)μ›μœΌλ‘œ 변경될 μ˜ˆμ •μž…λ‹ˆλ‹€.")
        }
        
        didSet {
            print("μž”μ•‘μ΄ \\(oldValue)μ—μ„œ \\(credit)μ›μœΌλ‘œ λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
        }
    }
}

let myAccount = Account()
myAccount.credit = 1000
  • ν”„λ‘œνΌν‹°μ˜ 값이 λ³€κ²½ 될 λ•Œ μ§€μ •λœ μ½”λ“œλ₯Ό μ‹€ν–‰
  • ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μ‚¬μš©ν•˜λ €λ©΄, 값이 λ°˜λ“œμ‹œ μ΄ˆκΈ°ν™”λ˜μ–΄μžˆμ–΄μ•Ό 함
  • ν˜„μž¬μ™€ 같은 값을 ν• λ‹Ήν•˜λ”λΌλ„ ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λŠ” 호좜됨
  • Lazy ν”„λ‘œνΌν‹°μ—λŠ” μ‚¬μš©λ  수 μ—†κ³ , μ €μž₯ ν”„λ‘œνΌν‹°μ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯
    • μ—°μ‚° ν”„λ‘œνΌν‹°μ—λŠ” μ‚¬μš© λΆˆκ°€λŠ₯
    • ν•˜μ§€λ§Œ 상속받은 μ—°μ‚° ν”„λ‘œνΌν‹°μ—λŠ” overrideλ₯Ό 톡해 μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. 즉, λΆ€λͺ¨ ν΄λž˜μŠ€μ— μ—°μ‚°ν”„λ‘œνΌν‹°κ°€ μžˆλ‹€. μ—¬κΈ°μ„œλŠ” ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μ‚¬μš© λͺ»ν•˜μ§€λ§Œ, 상속받은 μžμ‹ν΄λž˜μŠ€μ—μ„œλŠ” 이 ν”„λ‘œνΌν‹°λ₯Ό override ν•˜μ—¬ ν”„λ‘œνΌν‹° μ˜΅μ €λ²„λ₯Ό μ •μ˜ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλ‹€.
  • Property의 값이 λ³€κ²½λ˜κΈ° 직전에 willSet이 호좜되고, λ³€κ²½λœ μ§ν›„μ—λŠ” didSet이 호좜됨
  • willSetμ—μ„œλŠ” newValueκ°€, didSetμ—μ„œλŠ” oldValueκ°€ μžλ™μœΌλ‘œ 전달됨

 

3. λ³€μˆ˜/ν”„λ‘œνΌν‹°μ˜ μ—­ν• 

λ³€μˆ˜μ˜ μ—­ν• 

  • 데이터 μ €μž₯
    • λ³€μˆ˜λŠ” λ©”λͺ¨λ¦¬μ— 데이터λ₯Ό μ €μž₯
    • ex-μ‚¬μš©μžμ˜ 이름, λ‚˜μ΄, μ „ν™”λ²ˆν˜Έ λ“±
  • 데이터 μ‘°μž‘
    • λ³€μˆ˜λŠ” μ €μž₯된 데이터λ₯Ό μ½κ±°λ‚˜ μˆ˜μ •
    • ex-μ‚¬μš©μžμ˜ λ‚˜μ΄λ₯Ό μ¦κ°€μ‹œν‚€κ±°λ‚˜ μ „ν™”λ²ˆν˜Έλ₯Ό λ³€κ²½
  • 데이터 전달
    • λ³€μˆ˜λŠ” ν”„λ‘œκ·Έλž¨ λ‚΄μ—μ„œ 데이터λ₯Ό μ „λ‹¬ν•˜λŠ” 데 μ‚¬μš©
    • ex-ν•œ ν•¨μˆ˜μ—μ„œ λ‹€λ₯Έ ν•¨μˆ˜λ‘œ 데이터λ₯Ό μ „λ‹¬ν•˜κ±°λ‚˜ λ·° μ»¨νŠΈλ‘€λŸ¬μ—μ„œ 뷰둜 데이터λ₯Ό 전달
  • μ½”λ“œμ˜ μž¬μ‚¬μš©
    • λ³€μˆ˜λŠ” 값을 μ €μž₯ν•˜κ³  λ‹€μ‹œ μ‚¬μš©ν•  수 μžˆμœΌλ―€λ‘œ μ½”λ“œμ˜ μž¬μ‚¬μš©μ„±μ„ λ†’μ—¬μ€Œ
    • ex-μ‚¬μš©μžμ˜ 이름을 μ—¬λŸ¬ κ³³μ—μ„œ μ‚¬μš©
  • ν”„λ‘œκ·Έλž¨μ˜ μƒνƒœ 관리
    • λ³€μˆ˜λŠ” ν”„λ‘œκ·Έλž¨μ˜ μƒνƒœλ₯Ό κ΄€λ¦¬ν•˜λŠ” 데 μ‚¬μš©
    • ex-κ²Œμž„μ—μ„œ ν˜„μž¬ 점수λ₯Ό μ €μž₯ν•˜κ±°λ‚˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ‚¬μš©μžκ°€ λ§ˆμ§€λ§‰μœΌλ‘œ λ°©λ¬Έν•œ νŽ˜μ΄μ§€λ₯Ό μ €μž₯

ν”„λ‘œνΌν‹°μ˜ μ—­ν• 

: ν”„λ‘œνΌν‹°λŠ” λͺ¨λΈ 데이터와 λ™μž‘μ„ μ •μ˜ν•˜κΈ° μœ„ν•œ μœ μ—°ν•˜κ³  κ°•λ ₯ν•œ 방법을 제곡

  • κ°’ μ €μž₯/검색
  • μΊ‘μŠν™”
    • 데이터 ν˜Ήμ€ λ™μž‘μ„ μΊ‘μŠν™”ν•  수 μžˆλŠ” 방식 제곡
    • μ™ΈλΆ€ μ½”λ“œκ°€ 직접 λ‚΄λΆ€ μΈμŠ€ν„΄μŠ€μ˜ μƒνƒœμ— λŒ€ν•΄ μ ‘κ·Όν•˜κ±°λ‚˜ μˆ˜μ •ν•˜λŠ” 것을 λ°©μ§€
  • μ˜΅μ €λ²„
    • μ˜΅μ €λ²„: μ‚¬λžŒμ΄ ν”„λ‘œνΌν‹°μ˜ κ°’μ˜ 변화에 μ‘λ‹΅ν•˜λ„λ‘ ν—ˆμš©
    • willSet: 값이 μ„€μ •λ˜κΈ° 전에 호좜
    • didSet: 값이 μ„€μ •λœ 후에 호좜
    • ν”„λ‘œνΌν‹°μ˜ 값이 λ³€ν™”ν•  λ•Œ 좔가적인 μ•‘μ…˜μ„ μˆ˜ν–‰
  • Type-level behavior
    • λ™μž‘μ˜ νƒ€μž… κ·Έ μžμ²΄μ™€ κ΄€λ ¨ν•˜μ—¬ λ™μž‘μ„ μ •μ˜
λ°˜μ‘ν˜•