기초탄탄/Swift

클래스와 구조체, 아직도 난 잘 알지 못한다.

노랑✨ 2025. 1. 15. 02:55

클래스와 구조체의 차이가 뭐냐구요? 아 그거야 참조타입과 값타입이죠! 메모리 힙영역에 주소가 어쩌구... 스택에서는 저쩌구... 이렇게 말할 줄 아니까 저도 제가 아는 줄 알았습니다. 그런데 아니었어요. 안다고 생각하는게 얼마나 위험하고 부질없는 일인지... 이렇게 말로만 해서는 안되겠구나 느낀 하루였습니다. 제가 오늘 했던 삽질을 조금 공유해볼까 합니다. 클래스와 구조체의 차이에 관한 이야기예요.

분명 아는 줄 알았는데 다시 깨닫다니 기쁘고 슬픈 이 기분

 

오늘 제가 만들고 싶었던 화면은 아래와 비슷합니다. 화면 너비에 맞춰 색상과 글자가 들어간 레이블을 다섯개 배치하는 것입니다! 아주 간단하죠?

심플

같은 컴포넌트에, 갯수도 정해져있겠다, 자연스럽게 배열로 관리해보면 어떨까? 라는 생각이 든 것이죠. 그렇게 공간 개수를 지정해서 배열을 만들어주는 Array(repeating:count:) 를 사용해서 아래와 같이 선언을 해보았습니다.

 

이 생성자를 이용해서
UILabel() 객체 생성을 반복해서 다섯번 하고 있으니 레이블 다섯개 들어간 배열 완성?

 

레이아웃상 레이블 다섯개는 subViews 배열로 만들어져서 StackView 에 들어가있고, StackView 에는 fillEqually distribution 과 함께 centerX, top, horizontalEdges, height 정도, 위치를 잡기 위한 제약조건만 잡은 상황입니다. 이렇게 선언하면 화면에서 어떻게 나타날까요?

stackView 의 별다를거 없는 모습

 

바로 이렇게 나타납니다!

왜 너만 나와...?

왜 갑자기 5번만 등장한 걸까, 설마 ZStack 처럼 View 가 겹쳐서 안보이는 걸까? UIKit StackView 에도 그런 기능이 있었나? 금시초문? 별 생각을 오만번 했습니다. 디버깅을 위해 View Hieararchy 를 살펴봅니다.

단 한개

설마 다섯개 뷰가 모두 한 위치에 겹쳐져 있나? 라는 생각과 다르게, 레이블뷰가 단 하나만 그려져있네요. 나머지는 다 어디갔을까? 1부터 5까지 타이틀을 지정해주는 시점에 루프를 하고 있으니 각 레이블을 print 해보기로 합니다.

다섯쌍둥이

레이블뷰 인스턴스가 할당된 메모리 주소가 모두 같은 주소입니다. 이거 어디서 많이 들어본 상황 같네요. 클래스는 메모리 주소를 참조할 뿐.. 배열 생성 시에 repeating 해준 건 같은 주소를 가진 객체를 계속 생성(?)하고 있었던 것이었어요.

 

구조체라면 값이 메모리 스택영역에 복사가 되어서 그대로 사용이 가능했겠지만, 제가 하고 있었던 일은 하나의 UILabel 클래스의 인스턴스를 만들고, 그 인스턴스 주소를 참조하는 같은 객체를 반복해서 만들고 있었던 것이었습니다. 그러니 1부터 5까지 루프로 돌려서 넣은 이름은 계속 덮어씌워져 가장 마지막 값인 5만 남고, 화면에 나타나는 UILabel 도 한개뿐이었던 것이죠.

Array(repeating:count:) 의 사용 예시를 다시 살펴보면, 대부분 값타입인 String 이나 Int 등을 이용하는데요, 값이 그대로 복사되는 성격의 타입들이기 때문에 문제가 없었던 것입니다.

깜빡 속았군

 

repeating 에 대해서도 그 역할을 제대로 알고 있어야 할 것 같아요. "count 만큼 repeat 한다" 의 느낌으로 사용했는데, "어떤 하나의 element 를 count 번 repeat한다" 로 다시 고쳐서 알게 되었습니다. 멘토님께서 알려주신 힌트가 되는 방법이 바로 random Int 배열을 만들어서 프린트 해보는 것인데요, 처음 잘못 생각했던대로라면, 아래 배열은 랜덤 숫자가 10개 나타나야겠죠?

랜덤값 열개?

하지만 결과는 아래와 같습니다. repeating 은 어떤 하나의 element 를 count 만큼 반복해주는 것이기 때문에, 실제로 랜덤값을 뽑는 일은 처음 한번만 실행합니다.

처음에 생성한 랜덤값 하나를 열개!

 

마침 스냅킷을 처음 배우고 있는 상황이라 스냅킷을 제대로 사용하지 못해서 문제가 발생한걸까? 하고 의심했었습니다. 그런데 클래스와 구조체 차이에 의한 문제였다니... 역시 기본기가 탄탄하고, 진짜로 이해하고 있어야 실제 개발할때에 헤매지 않겠구나 느낀 하루였습니다. 오늘 이렇게 알았으니 다음부터는 더 꼼꼼히 확인하겠습니다! 그럼 이만~