도니의 iOS 프로그래밍 세상

[Swift] Struct와 Class의 차이(Value Type, Reference Type) - 기초편 본문

Swift

[Swift] Struct와 Class의 차이(Value Type, Reference Type) - 기초편

Donee 2022. 12. 31. 22:35

Struct, Class

Struct와 Class는 일반적으로 프로그램의 구성요소로서 범용적이고 유연한 구조를 자랑합니다.
Swift문서의 설명인데 조금 원론적인 것 같네요.
쉽게 말해서, Struct와 Class는 한 객체안에 많은 정보를 담고 싶을때 가장 자주 쓰이는 형태입니다.
두 값은 굉장히 자주 사용되는데, 두가지의 차이점은 무엇이 있을까요?

Reference Type, Value Type

두 값의 차이에서 가장 큰 점은 Class는 Reference Type, Struct는 Value Type이라는 점입니다.

Value Type인 Structure, Enum

Structure와 Eum은 Value Type으로서 변수나 상수에 할당될때, 함수에 전달될 때 값이 복사됩니다.
즉, 변수끼리 값을 전달할 때 값이 복사되어서 나가게 됩니다.
간단한 예제를 보면서 확인해볼께요!

var example = 3
var another = example
another = 4
print(example)

위 예시의 답이 무엇일까요?
example은 3이 됩니다.
이유가 무엇인지 알기 위해, 기본적으로 Value Type이 메모리에서 어떻게 값을 서로 전달하는지 알아봅시다.

var example = 3

처음 example을 선언하게 되면 메모리에 3이라는 값을 가진 공간이 할당됩니다. 이를 example이 가르키고 있는 것이지요.

그리고 another에 example을 할당해주면 어떻게 될까요?

둘다 같은 공간을 가르키는것이 아니고, example과 동일한 상수값 "3"을 가진 공간이 새롭게 할당됩니다.
그리고 another은 이를 가르키고 있는 것이지요

결과적으로 another의 값을 바꾼다고 할지라도 example이 가르키는 공간에 값을 바꾸지 않았기 때문에 바뀌지 않습니다.

(하지만 늘 이렇게 Copy형태로 되는 것은 아닙니다. copying을 통해 메모리 공간에 늘리는 것은 결국 리소스를 사용하는 행위이기 때문입니다. 따라서 Swift는 COW(Copy On Write)를 통해 array, dictionary, String등은 별도의 동작방식을 사용합니다. 이는 다음 COW편에서확인하시면 됩니다!)

Reference Type인 Class

value type들과 다르게, reference type은 변수나 상수에 할당될때, 함수에 전달될 때 값이 복사되지 않습니다.
대신 동일한 객체에 대한 참조가 사용됩니다.
쉽게 말해서, 아까처럼 새로운 공간에 값을 저장해두고 그걸 사용하는게 아니고, 기존의 공간을 두 변수가 함께 사용하도록 합니다.
간단한 예제를 보면서 확인할게요!

class Sample {
    var number = 3
}
var example = Sample()
var another = example
another.number = 4
print(example.number)

위 프린트문에는 어떤값이 출력될까요?
앞선 예제와 거의 동일한 구조인데요, 출력값은 "4"로 나타납니다.
왜 이런 값이 출력될까요?

var example = Sample() 
var another = example

첫번째 구문을 통해서 Sample 객체가 하나 생성됩니다.
그 뒤, another은 exampler과 동일한 객체를 가르키도록 선언됩니다.
따라서 그림을 보면 다음과 같습니다.

결국 another는 example과 같은 instance를 가르키고 있습니다.

따라서 another 내부 number를 바꾸게 되면 결국 example의 내부 값도 변하게 되는 것입니다.

응용예제

1. Strcutre 응용문제

func test(number: Int) {
    var another = number
    another = 4
}

var example = 3
test(number: example)
print(example)

위 값의 정답은 무엇일까요?
바로 3입니다.
왜그럴까요?
example의 3이라는 값은 함수에 복사 형태로 전달됩니다.
이를 another가 한번더 복사하게 되고, 해당 값을 바꾸게 됩니다.
그리하여 서로 다른 공간의 값을 바꾼것이기 때문에 example에는 아무런 영향을 주지 않게 됩니다.
(정학히, Stack에 test 함수의 공간이 만들어지고, 해당 내부에 another가 가질 3이라는 값을 위한 공간이 할당됩니다. example이 존재하는 Stack공간과 별도의 공간이기 때문에 아무런 영향을 줄 수 없습니다.)

2. Class응용문제

class ClassSample {
    var number: Int = 3
}

func test(classSample: ClassSample) {
    var another = classSample
    another.number = 4
}

var classSample = ClassSample()
test(classSample: classSample)
print(classSample.number)

위에서 classSample의 number 값은 무엇일까요?
정답은 4입니다.
왜 그럴까요? Class는 reference type이기 때문에, 함수에 참조 형태로 전달됩니다.
그리하여 another는 classSample과 동일한 공간을 가르키고 있습니다. 동일한 공간의 값을 바꾸기 때문에, classSample의 값의 영향을 미치게 됩니다. (정학히, class의 instance들은 heap이라는 공간에 만들어집니다. Stack에 test 함수의 공간이 만들어지고, 해당 내부에 another가 만들어지는데 another는 힙의 공간을 가르키고 있습니다. 이는 example이 가르키는 instance와 동일한 값을 가르키고 있습니다. 따라서 동일한 heap 공간안에 값을 가르키고 있기 때문에 값을 바꿀시 서로간의 영향을 줍니다. )

결론

  1. Structure, Class의 가장 큰 차이중 하나는 "Value Type"과 "Reference Type"이라는 점이다.
  2. Value Type은 값의 복사가 이루어지기 때문에 별도의 메모리가 할당되어 그곳을 사용할 수 있다.
  3. Reference Type은 값의 복사가 아닌, 값의 참조가 이루어진다. 공동으로 자원을 관리하기 때문에 주의를 해야한다.

출처

https://developer.apple.com/swift/blog/?id=10

Comments