5. 클래스와 구조체

두 상자가 있다고 가정해 봅시다.

하나는 어떤 것이라도 다 넣을 수 있는 상자.
나머지는 하나를 넣으면 무조건 자물쇠를 채워야 하는 상자.

눈치 빠른 분이라면 이미 아셨겠지만 전자는 변수 후자는 상수를 말한겁니다.

변수는 어떤 값이라도 넣을 수 있고 또 계속 바꿀 수 있습니다.
상수는 그렇지 못하죠 (변경 불가)

우리가 이런 상자에 데이터를 담는데는 한계가 있습니다. 왜? Int나 String같은 데이터를 담는다면 하나씩 밖에 담지를 못합니다. 그래서 많은 데이터들을 하나하나 담기엔 너무 힘이 드니 한꺼번에 묶어서 관리하는데 이것을 모델링이라 합니다.

예를 들어 당신이 youtube를 보다 이런 썸네일이 보였다고 가정해봅시다.

이미지 출처:코딩애플

썸네일에 보이는건 이미지, 제목, 조회수, 올린 날짜 등이 있는데 모델은 이런 각각의 데이터를 모두 묶은 것을 말합니다. 이런 데이터 모델을 담아 두는 방식이 두 가지가 있는데
하나는 클래스(class)고 다른하나는 구조체(struct)라고 합니다.

구조체

그럼 처음에 구조체를 만들어 봅시다.

// 유튜버 모델 - 구조체 
struct youtuberStruct {
    var name: String
    var subcribersCount : Int
}

var devKim = youtuberStruct(name: "태경", subcribersCount: 99999)
var devKimClone = devKim 
print("값 넣기 전 devKimClone.name : \(devKimClone.name)") //태경
devKimClone.name = "내 이름이 뭐였더라?"
print("값 넣은 후 devKimClone.name : \(devKimClone.name)") //내 이름이 뭐였더라? 
print("값 넣은 후 devKim: \(devKim.name)") // 태경

이름과 구독자수를 가지는 유튜버 구조체를 만들었습니다. 구조체 다음 문장은

youtuberStruct라는걸 메모리에 올리는데 name도 있고 subcribersCount도 있구나? 그걸 이렇게 써주세요~

라는 말입니다.
그 다음 devKimClone이라는 이름의 똑같은 복사본을 만들어 줍니다.
출력을 세번 해서 각각의 출력값을 비교하면 다음과 같이 나옵니다.

1.값 넣기 전 devKimClone.name : 태경
2.값 넣기 후 devKimClone.name : 내 이름이 뭐였더라?
3.값 넣기 후 devKim.name : 태경

엥? 이게 무슨 말일까?
결과를 해석하자면 devKim의 복사본을 만들어서 그 값을 변화 시킨 후 원본에 값과 대조했더니 둘이 달랐다는 것!

클래스

그럼 클래스는?
클래스는 구조체와 똑같은 데이터 덩어리지만 다른점은 생성자가 필요합니다

class youtuberStruct {
    var name: String
    var subcribersCount : Int
    }

생성이라는 말은 메모리에 올린다. 라는 말입니다.

롤에서 "정글아 이니시나 걸어봐라" 할때 그 이니시가 그것입니다.

스위프트에선 init이라고 하는데 즉, 시작(메모리에 올린다)한다 라는 뜻.

이것을 이용해서 코드를 다시 짜봅시다~

class youtuberStruct {
    var name: String
    var subcribersCount : Int
    }
    
    init(name: String, subcribersCount: Int){
        self.name = name
        self.subcribersCount = subcribersCount
    }

init으로 매개변수를 가진 생성자 메소드를 만들어야 매개변수를 넣어서 그 값을 가진 객체를 만들 수 있습니다.
메모리에 올리기 위해선 값이 필요한데 처음엔 값이 없었어요. 그리하여 외부에서 데이터를 넘겨주기 위해서 init()안에서 name과 subcriber를 받게 합니다. 이때 이름은 똑같이 해주지 않아도 되지만 가독성을 위해서 똑같이 해줍니다.

self.name = name의 뜻은 내가(youtuberStruct) 가지고 있는 name을 외부에서 넘어온 name으로 넣을게요 라는 의미. 그리고 구독자수도 마찬가지.
그리고 보통 매개변수를 넣을때는 이름을 쓰고 싶지 않을때도 있는데 그때는 _(언더바)를 사용하면 됩니다.

구조체와 같이 설정한 후 출력해보자!

var Kim = youtuberStruct(name: "태경", subcribersCount: 99999)
var KimClone = Kim // 복사본

print("값 넣기 전 Kim.name : \(Kim.name)") //태경
KimClone.name = "내 이름이 뭐였더라?"
print("값 넣은 후 KimClone.name : \(KimClone.name)") //내 이름이 뭐였더라? 
print("값 넣은 후 Kim.name: \(Kim.name)") // 내 이름이 뭐였더라? 

출력은 다음과 같이 나온다.

1.값 넣기 전 Kim.name : 태경
2.값 넣기 후 KimClone.name : 내 이름이 뭐였더라?
3.값 넣기 전 Kim.name : 내 이름이 뭐였더라?

이럴 수가 구조체와 다르게 원본까지 같이 변해버렸다!
왜 이럴까?

구조체는 아까 말했던 것처럼 서로 같아 보이지만 전혀 연관되지 않은 다른 존재였고 클래스는 서로가 연결되어 있다.

왜 연결 되어있을까? 메모리 주소를 가리키고 있어서 그렇다(참조, 레퍼런스) 어느 한 메모리 공간에다가 a.Kim과 b.Kim 같이 바라보고 있다고 생각하면 된다.

쉽게 이해하자면 구조체는 하나의 똑같은 사본을 만든거고 클래스 같은 경우는 구글 doc같은 것이라 생각하면 된다. 내가 수정하면 다른 쪽에서도 똑같이 수정이 되는 것이라 이해하자.

결론 -> struct : 복사해서 사용하는 개념. 참조하는 값이 바뀌어도 기존 값에는 영향이 없음!
class : 공유해서 사용하는 개념. 참조하는 값이 바뀌면 기존 값도 바뀜!

좋은 웹페이지 즐겨찾기