욤찌의 개발 일기
[Swift] value type & reference type (구조체와 클래스) 본문
현재 swift를 공부하면서 UIKit과 SwiftUI를 왔다리~ 갔다리~ 하고 있당 (그래서 대충 힘들다는 뜻..)
UIKit과 SwiftUI를 조금씩 맛보기하면서 둘의 차이를 정말 많이 느끼는 중이다.
사실 무엇 하나가 특~별히 좋다! 라는 느낌보다는 둘의 차이가 확실하기 때문에 두 개의 장단점을 비교할 수 있어서 흥미롭다.
아무래도 둘 사이의 여러가지 차이점이 있겠지만, 지금까지 이 iOS 응애가 느낀 최대의 차이점은
class로 앱을 구성하는가 struct로 구성하는가의 차이가 아닐까 싶다.
클래스와 구조체,, 늬들 같은 집안인줄 알았는데 왜 그렇게 다른데ㅠ!! 라는 마음에서 시작하는
오늘의 TIL~
swift를 말할 수 있는 스위프트의 여러가지 특성들이 있겠지만,
그 중에서 가장 중요하다고 여겨지는 것 중의 하나가 객체지향 프로그래밍 언어라고 생각한다.
(나중에 제대로 공부해서 객체지향에 대해서 다뤄봐야지,,)
swift에는 열거형(Enum), 구조체(Struct), 클래스(Class)라고 불리는 객체가 있고,
연관 있는 데이터들을 묶어서 잘 관리할 수 있도록 사용자가 정의해서 사용할 수 있는 사용자 정의 타입이다.
이 객체들은 메모리 저장 방식에 의해서 두 가지로 나뉠 수 있는데, 그것이 바로
값 타입(value type)과 참조 타입(reference type)이다.
enum과 struct는 값 타입, class는 참조 타입으로 분류된다.
이 메모리 저장방식은 Data 영역에 저장되는 정의된 각 객체의 인스턴스가 생성될 때
그 인스턴스가 어디에 저장되고, 그 저장방식으로 어떻게 작동하는지에 차이를 두고 있다.
1) 값 타입 (value type)
값 타입에 대표적인 타입은 바로 구조체(struct)이다.
struct Fruit {
var name: String = ""
var price: Int = 0
}
var fruit1: Fruit = Fruit()
여기 Fruit 라는 구조체가 있다. (나는 과일이 먹고 싶다,,)
이 구조체를 가지고 fruit1이라는 인스턴스를 생성했다. 이렇게 구조체에서 인스턴스를 생성하게 되면
Data 영역에 저장된 Fruit라는 구조체에서 fruit1이라는 인스턴스가 생성되어 stack(스택) 영역에 저장된다.
var fruit1: Fruit = Fruit()
fruit1.name = "딸기"
fruit1.price = 13000
var fruit2 = fruit1
fruit2.name = "샤인머스캣"
fruit2.price = 15000
print(fruit1.name) // "딸기"
print(fruit1.price) // 13000
print(fruit2.name) // "샤인머스캣"
print(fruit2.price) // 15000
여기서 fruit1의 name과 price 저장 속성의 값을 바꾸어 주었다. (나는 딸기 귀신이다)
그 후에 fruit1을 fruit2라는 변수에 할당해서 (복사하는거라고 생각하면 됨) 새로운 인스턴스를 생성했다.
그 후에 다시 fruit2의 저장속성들을 변경했다.
그리고 print 함수를 통해 그 값을 확인해 보면 각각의 인스턴스에 저장한 값이 나오는 것을 알 수 있다.
값 타입은 생성된 인스턴스의 실제 값을 가지고 복사본을 생성하기 때문에
원본과는 별개로 독자적인 데이터의 값을 가지게 된다.
(서로 독자적인 값을 가지고 스택영역에 저장된다. 그래서 이름이 값 타입인 듯)
그렇기 때문에, 구조체로 타입을 선언한 경우에는 하나의 인스턴스에 대한 복사본이 여러 개 존재할 수 있고
그 복사본들은 원본에 전혀 영향을 주지 않는 자신만의 데이터를 가지게 된다.
(fruit3, fruit4,... 이렇게 여러 개의 독자적인 데이터를 갖게 되는 것이다.)
2) 참조 타입 (reference type)
그렇다면 참조타입은 어떻게 다른지 알아보자!
참조타입의 가장 대표적인 타입은 class이다.
class Book {
var name: String = ""
var price: Int = 0
}
var book1: Book = Book()
Book이라는 클래스를 정의하고, Book 타입을 가진 book1이라는 인스턴스를 생성했다.
참조타입에 경우에는 값 타입과는 다르게 book1 인스턴스의 실제 메모리는 Heap(힙) 영역에 저장되고
stack 영역에는 인스턴스의 실제 위치인 Heap 영역에 있는 메모리 주소가 저장이 된다.
var book1: Book = Book()
book1.name = "스위프트"
book1.price = 20000
print(book1.name) // "스위프트"
print(book1.price) // 20000
var book2 = book1
book2.name = "iOS"
book2.price = 15000
print(book1.name) // "iOS"
print(book1.price) // 15000
print(book2.name) // "iOS"
print(book2.price) // 15000
값 타입에서 했던 것과 마찬가지로 book1 인스턴스에 저장속성을 새롭게 할당했고 print 함수를 통해 결과를 확인했다.
book1에 새롭게 할당한 대로 잘 출력이 되는 것을 볼 수 있다.
그리고 다시 book2라는 새로운 인스턴스를 생성하고 다시 값을 할당해 주었다.
그리고 book1과 book2의 값들을 다시 print 함수를 통해 확인했다.
근데 이것이 머선 일..⁉️
두 인스턴스의 값이 book2로 할당한 값으로 같아진 것을 확인할 수 있었다.
이것이 바로 참조타입이다..!!!
스택 영역에 직접 값을 저장하는 값 타입과는 달리
참조 타입은 스택영역에 실제적인 값을 저장하는 것이 아니라
인스턴스가 위치하고 있는 메모리 주소 값을 복사해서 저장한다.
그래서 book1을 book2에 새롭게 할당을 하게 되면 book1의 값이 아닌 메모리 주소를 복사하는 거라서
book1과 book2가 같은 주소를 참조하게 된다. (like 넌 나고,, 난 너야,,)
그래서 book2(참조체)가 변경되면 동일한 주소를 참조하는 book1에도 같은 작업이 수행된다.
위의 값타입에서 하나의 인스턴스에 대한 복사본이 여러 개 존재할 수 있고
그 복사본들은 원본에 전혀 영향을 주지 않는 자신만의 데이터를 가지게 된다고 했는데
참조타입은 인스턴스를 새롭게 복사하게 되면 하나의 클래스 인스턴스가 있고 그 인스턴스의 주소를 참조하는
여러 개의 참조체가 존재하는 것이다.
(만약 book3을 만들어서 또 다른 값을 할당하게 되면, 같은 주소를 참조하고 있는 인스턴스들의
값은 다 ~~ 모조리~~ 바뀌게 된다.
그래서 독자적으로 사용하려면 복사가 아닌 새롭게 초기화해서 인스턴스를 생성해야함.)
이렇게 보니까,, 일단 스택에 어떤 것이 저장되는지를 보면 되는 것 같다.
스택에 직접적인 값이 저장이 되느냐(값 타입) 아니면 참조 주소가 복사되는가(참조 타입)!
아무래도 스택은 사용하면 바로바로 사라지는 영역이기 때문에 상대적으로 가볍게 사용할 수 있는
구조체는 그 자체로 저장할 수 있지만
상속도 해야 하고 여러모로 오랜 기간 저장해야 하는 클래스의 경우에는 스택에 저장하기가 힘들기 때문에
실제적인 메모리는 힙 영역에 저장하고 그 주소만 스택에 저장하는 것 같다
(일단은 이렇게 이해해 보았다,, 모든 반박 다 받습니다 제발 알려주세요!!!!!)
애플에서는 웬만하면 구조체 사용을 권장한다고 한다.
구조체가 클래스보다 더 효율적이고 멀티 스레드 코드를 사용하는데 더 안정적이라고 한다.
그래서 웬만한 타입들이 상속처럼 클래스로만 구현할 수 있는 것이 아니라면 구조체로 정의되어 있다.
(클래스로 되어있는 것들도 구조체로 바꾸고 있다고 들었다)
그렇다면 구조체가 클래스보다 더 좋은것인고니? 그건 아니다 !!!!!!
내가 하는 프로젝트에 어떤 타입을 쓰는 것이 더 효율적일지를 생각해서 하는 것이 정답이라고 한다.
상황에 맞게 클래스와 구조체를 적절히 사용하면 될 것 같다!
이외에도 값 타입과 참조 타입을 비교해야 할 부분이 많아서 앞으로 더 공부를 해봐야겠다.
그리고 이런 부분들을 생각해서 UIKit과 SwiftUI로 각각 구현할 때 어떤 점을 더 신경 써야 할지를 생각해야겠다.
어제 시작했지만 오늘 끝난 TIL 끝~
(완져니 응애 개발자입니다. 수정 사항 있으면 언제든 답글 남겨쥬세용🔥)
📖 Reference ❤️
https://www.yes24.com/Product/Goods/89421220
핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍 - YES24
SwiftUI는 물론 애플리케이션 개발과 출시를 위한 모든 과정을 담았다!이 책의 목적은 SwiftUI와 Xcode 11, 그리고 스위프트 5 프로그래밍 언어를 사용하여 iOS 13 애플리케이션 제작 기술을 전달하는 데
www.yes24.com
https://babbab2.tistory.com/25
iOS) 메모리 구조 (Code, Data, Stack, Heap)
안녕하세여~~ 소들입니다 :-))))) 오늘 웬 듣보잡 버그 한 놈이 나왔는데 처음에 메모리 참조 오류인 줄 알고 하루 종일 메모리에 대해서 공부 했는데 버그 원인은 메모리가 아니었음ㅋ (디코딩 네
babbab2.tistory.com
https://woozzang.tistory.com/29
[Swift] 값타입과 참조타입 ( Value Type vs Reference Type )
1차 수정: 2021.06.06 안녕하세요. 이번 글에서는 스위프트의 값타입과 참조타입의 차이점을 메모리에 저장되는 관점에서 다루어보겠습니다🐶 *속성감시자에서 값타입과 참조타입의 작동차이가
woozzang.tistory.com
https://goods99.tistory.com/176
값타입과 참조타입 차이점
swift에 자료구조들은 두가지 타입으로 존재한다 값 타입 (Value Type) 참조 타입(Reference Type) - 구조체 (Struct) - 열거체 (Enum) - 튜플 (Tuple) - 클래스 (Class) - 클로저 (Closure) 값 타입 대표 '구조체' 와 참
goods99.tistory.com
'Swift' 카테고리의 다른 글
[Swift] Any랑 AnyObject 공부했다. 근데 TypeCasting을 곁들인,,(1) (3) | 2023.11.03 |
---|---|
[Swift] 나는 그저 Convenience Initializers 가 알고싶었을 뿐인데,,~ (0) | 2023.11.01 |
[Swift] Class 성능 높이는거,, 그거 어떻게 하는건데,, (1) | 2023.10.31 |
[Swift] ARC(Auto Reference Counting) (2) (0) | 2023.07.17 |
[Swift] ARC(Auto Reference Counting) (1) (0) | 2023.07.16 |