기어가더라도 제대로

[10일차] struct 본문

Swift - 기초

[10일차] struct

Damagucci-juice 2022. 9. 28. 20:17

오늘은 

  • 어떻게 struct 를 만드는지
  • 동적으로 프로퍼티를 계산하는 방법
  • 프로퍼티의 값이 바뀌면 행동을 취하는 방법

등을 배워 봅시다. 

struct 를 만드는 방법

  • Int, String, Array 등의 타입처럼 struct를 만들면 됩니다. 우리가 만드려는 struct 는 첫 글자를 대문자로 써야합니다. 
  • 그 내부의 정보를 포함하고 있는 프로퍼티는 첫글자를 소문자로 하는 Cammel Case 를 사용하면 됩니다. 

생성할 땐 속성으로 만들어놓은 것들을 정의해줘야 새로운 struct 를 생성할 수 있습니다. 

그전에 용어 정리를 한번 하면 좋겠습니다. 

struct 안에 저장되어있는 상수나 변수를 Property(속성)라고 부릅니다. 

struct 안에 선언된 함수를 메서드라고 부릅니다. 

struct Employee {
    let name: String
    var vacationRemaining: Int

    func takeVacation(days: Int) {
        if vacationRemaining > days {
            vacationRemaining -= days
            print("I'm going on vacation!")
            print("Days remaining: \(vacationRemaining)")
        } else {
            print("Oops! There aren't enough days remaining.")
        }
    }
}

위와 같은 구조체가 있다고 할 때, 이거는 에러를 냅니다. 

왜 와이? vacationRemaining 프로퍼티가 내부 메서드로 변경이 되기 때문인데요. 이때 func 앞에 mutating 키워드를 붙여주어야합니다. struct 내부의 프로퍼티를 변경할 수도 있다는 것을 알려주는 것이기 때문이죠. 근데 오케이 괜찮습니다. 그치만 이 Employee 라는 구조체 자체가 let 키워드로 선언되어있다면 또 에러를 낼거에요. 왜냐면 Struct 의 특징인데요. struct 의 인스턴스가 let 으로 선언이 되어있다면 내부의 프로퍼티도 var 이든 let이든 let으로 선언된 효과를 냅니다. 

gucci 라는 직원을 let으로 선언했는데요. 비록 메서드 앞에 mutating 이라는 키워드를 사용한다고 해도 인스턴스 자체가 let 으로 선언되어있다면 내부 프로퍼티를 수정하는 메서드를 사용할 수 없다는 것이죠. 정리하자면 struct 내부의 프로퍼티를 변경하기 위해서는 

  1. struct의 인스턴스가 생성될 때 var 로 생성될 것
  2. struct 내부의 속성도 var 로 생성이 될것
  3. mutating func 으로 선언할것

이 되겠네요.  mutating 은 어떤 기능을 제공해 주는 것일까요? 

Swift 에게 mutating 이 붙은 메서드는 'let' 으로 생성된 인스턴스에서 실행될 수 없다는 것을 알려줍니다. 실제로 그 메서드가 struct 내부의 속성을 바꾸는지 아닌지는 중요하지 않고, 바꾼다고 선언하여 믿게끔하는 것이지요. 다시 말하면 mutating 이 붙지 않은 메서드는 내부 프로퍼티의 값을 변경하는 메서드를 실행할 수 없습니다. 

생성자도 이런 메서드의 일종이에요. 우리가 struct 을 생성하면 명시적으로 선언을 하든 하지 않든 init 이라는 생성자 메서드가 생성이 됩니다. 그래서 

var gucci = Employee(name: "gucci", remainingVacation: 0)
var bucci = Employee.init(name: "bucci", remainingVacation: 0)

위와 아래는 같은 거에요. 앞으로 더 알아가보도록 해요. 좋습니다. 

프로퍼티의 값을 동적으로 계산하는 방법

말이 어려운데요, 연산 프로퍼티(computed property)를 설명하는 겁니다. 

struct 는 내부 프로퍼티로 두 종류의 프로퍼티를 가질 수 있습니다. 

  • 저장 프로퍼티
    • 일반 적으로 var, let 으로 선언해서 데이터의 값을 저장하는 프로퍼티입니다. 여태까지 저희가 만든 let, var(클로저제외) 등이 여기에 해당합니다. 
  • 연산 프로퍼티
    • var 로 선언하고, 이 프로퍼티에 접근할 때마다 동적으로 값을 계산해서 나타내는 프로퍼티입니다. 
    • 저장 프로퍼티와 함수의 합작품이라고 보시면 되겠습니다. 값의 인출은 저장 프로퍼티 처럼 하는데, 실제로 행위는 함수처럼 하는 것이지요. 

재밌는 것은 연산프로퍼티로 선언한 속성은 값을 저장할 수가 없습니다. 왜 그러냐면 명시적으로 우리가 해주진 않았지만, getter 만 설정을 해준것과 같거든요. getter, setter 는 어렵지만 말이 어려운 거지 내용은 쉽습니다. 

  • getter
    • 읽을 코드 
  • setter
    • 저장할 코드 

아주 간편하죠. 이렇게 하면 됩니다. 그럼 우리가 설정한 연산프로퍼티는 getter 는 기본적으로 설정된거라고 보면 됩니니다. 값도 저장하게 하고 싶다면 setter 도 명시적으로 선언해주면 되겠죠. 

프로퍼티의 값이 변하면 행동을 취하는 방법

이것은 더 재밌습니다. 

getter, setter 를 이해하셨다면 이것도 쉽게 이해할 수 있습니다.

보면 tax 가 기존에 200이라는 값을 들고 있는데 여기에 새로운 값인 300이 들어간다고 해볼게요. 

그러면 willset { } 에서는 

  • willSet
    • newValue = 300 
    • tax(기존)  = 200
  • didSet
    • tax(바뀐값) = 300
    • oldValue = 200 

요렇게 인식할 수 있는 일종에 코드 블록이 있는 거에요. 그래서 프로퍼티에 변화가 발생하면 willSet, didSet 에 해야할 일을 정리해 놓으면 변화할 때마다 그것을 하겠죠? 

willSet 은 속성의 값이 변화하기 전에 호출이 되고 didSet 은 변화한 후에 호출이 됩니다. 

Comments