32YB SOPT/swift 문법 스터디

[SOPT] 야우쓰_5주차(구조체 vs 클래스, 메모리 구조)

신_이나 2023. 5. 24. 22:04

 

 

야우쓰란? "야 우리도 스위프트 할 수 있어"

in SOPT iOS

 

 

 

 

 

 

 

 

5주차의 키워드는 구조체 vs 클래스 메모리 구조다. 

너무 간단하게 조사하였습니다. 제송합니당,,

 

 

 

- 메모리 구조 

swift 의 메모리 구조는 Code, Data, Heap, Stack 으로 이루어진다. 

 

Code 영역

우리가 작성한 소스 코드가 기계어 형태로 저장되어 있으며, 컴파일 타임에 결정되고, read-only 형태로 저장된다.

 

Data 영역

전역 변수, static 변수가 저장된다 프로그램 시작과 동시에 할당되며, 프로그램이 종료되어야 메모리에서 해제된다. 변수 값들이 새로운 값을 받을 수 있으니 read-write 로 지정된다.

 

Heap 영역

ARC에 의하여 Reference Countin 이 관리되는 영역이다. 유일하게 runtime 이 결정되기 때문에 데이터 크기가 확실하지 않은 가변적인 데이터 타입들이 Heap 영역에 할당된다.

 

Stack 영역

함수 호출 시 함수의 지역변수, 매개변수, 리턴 값 등등이 저장되고, 함수가 종료되면 메모리도 해제된다. 컴파일 타임에 결정되기 때문에 무제한 할당이 불가능하다.

 

 

 

 

- 클래스와 구조체의 공통점

 Class 와 Struct 는 둘 다 property 와 function을 가지고 있는 타입이다. 따라서 당연히 비슷한 부분이 많은데, 함수적 기능을 하는 메서드를 선언할 수 있다, 내부 값에 '.'을 사용하여 접근할 수 있다, 생성자를 사용해 기능을 확장할 수 있다, extension을 사용하여 기능을 확장할 수 있다, protocol을 채택하여 기능을 설정할 수 있다.

이렇게 공통점이 많지만 근본적으로는 매우 다르다. 아래에서 살펴보자!

 

 

 

- Value Type과 Reference Type의 차이 (메모리저장 방식, 값 copy 방식 기준)

 값타입은 값 자체를 변수명과 함께 스택에 저장하고, 참조 타입은 값은 별도의 메모리에 저장하고 주소값을 스택에 저장한다. 따라서 컬렉션타입은 값타임이라고 할 수 있다. Swift 는 주소값보단 값 자체를 저장하는 값타입이 다른 언어보다 특화되어 있다고 한다. 값타입을 선언할 때는 struct 를 사용하고, 참조 타입을 선언할 때는 class 를 선언한다. 참조타입의 대표적인 것이 closure 인데, 값 자체를 전달하는 것이 아닌 참조만 공유하는 것이다.

 

 

 

 

클래스와 구조체는 값타입일까, 참조타입일까? (객체 Copy 방식에 대한 차이점을 기준)

 Class 는 참조타입으로 변수를 관리하며 따라서 ARC로 메모리를 관리한다. 따라서 Class 는 메모리 영역중에서 heap 영역에 할당되며 메모리에 할당된 class 는 인스턴스 또는 객체라고 불린다. 따라서 그 인스턴스를 참조하는 변수를 참조함수라고 칭한다. 이를 통해 알 수 있듯이 변수를 선언할 때 '='을 사용할 경우 참조 값을 복사한다. 앞서 언급한 ARC에 대해서는 세미나 복습을 하며 다룬 적이 있다. 한 번 더 보자

Struct 는 값타입이다. 따라서 참조나 주소값이 아닌 값 자체를 선언하고 해제한다. 따라서 상속이 가능한 class 와 달리 struct는 상속이 불가능하다. 메모리 영역 중에서는 Stack, Heap, Data Memory 공간에 할당된다. Class 와 다르게 변수 선언시 '='을 사용할 때 property의 값을 복사한다.

이렇게 근본적으로 다른 Class 와 Struct 을 객체 Copy 방식을 중심으로 비교해보고자한다. 우선, 객체 Copy 방식이란 무엇일까? 말 그대로 데이터를 복사하는 방법으로, 깊은 복사와 얕은 복사로 나뉜다. class 와 struct의 차이점이었던 참조 타입과 값 타입은 복사 방식을 다르게 취하는데, 참조 타입은 얕은 복사를, 값 타입은 깊은 복사를 진행한다. 먼저 얕은 복사란, 최소한으로만 진행하는 것으로 복사를 해도 새로 인스턴스 메모리가 생기는 것이 아닌 주소값만을 공유하게 된다. 깊은 복사는 데이터 자체를 복사하는 방법이기에 복사한 인스턴스의 데이터를 바꾸더라도 원본에 영향을 주지 않는다. 사실 깊은 복사는 듣기만 해도 느낄 수 있듯이 굉장히 비효율적으로 느껴진다. 따라서 이를 보완하기 위해 Copy on write = COW 의 방식이 등장하였다. 이는  데이터 복사시 실제로 값이 복사되는 것이 아니라, 동일한 값을 참조하다가 데이터 변경이 발생될 시에 복사해 값을 변경하는 방식이다.

 

클래스와 구조체의 성능 비교

 결론부터 말하자면 메모리 절약은 Class, 속도는 Struct!

지금까지 작성한 class 와 struct의 성질들을 종합해보면 위와 같은 간단한 결과가 나온다. 보통 나는 class 를 자주 사용하여 앱을 구현하곤 하였는데, 그렇다면 struct는 언제 사용해야 할까? 그건 바로, 적절히 균형있게! 하하 모호하군! 명시하자면 변수의 크기가 16바이트미만 정도로 작거나, 자주 변경하지 않는 객체거나, 기본형식과 유사하게 간단한 값을 갖을 때 구조체를 사용해주는 것이 좋다.