본문 바로가기

iOS/iOS 기술 면접

Struct는 뭐고 어떻게 사용할까?

구조체와 클래스 (Structures and Classes)

 

구조체와 클래스 (Structures and Classes) - Swift

실제로 값 타입에 대해 이전 챕터에서 광범위하게 다뤘습니다. 실제로 Swift에서 정수, 부동 소수점, 부울, 문자열, 배열 그리고 딕셔너리와 같은 기본 타입의 모두는 값 타입이고 구조체로 구현

bbiguduk.gitbook.io

오늘은 구조체에 대해서 알아보겠습니다!

저번에는 구조체, 클래스, 열거형을 비교하면서 간단하게 알아봤었는데 구조체에 대해 좀 집중적으로 볼게요!

Struct

  • 상수나 변수 메서드 등을 내부적으로 정의해 사용자 정의 타입을 만들 때 사용되는 타입
  • 인스턴스로 생성해서 직접 사용할 수 있음

공식문서에서 제공하는 구조체의 기능은 다음과 같습니다. (클래스와 공통 기능)

  • 값을 저장하는 프로퍼티 정의
  • 기능 제공을 위한 메서드 정의
  • 서브 스크립트 구문을 사용하여 값에 접근을 제공하는 서브 스크립트 정의
  • 초기화 상태를 설정하기 위한 초기화 정의
  • 기본 구현을 넘어 기능적 확장을 위한 확장
  • 특정 종류의 표준 기능을 제공하는 프로토콜 준수

구조체는 class 키워드를 이용해서 정의할 수 있습니다!

struct SomeStructure {
    // structure definition goes here
}

그리구 하나의 타입을 정의하는 것이므로 UpperCamelCase를 사용해서 선언해야 합니다.

 

위와 같이 정의를 하였고 실제로 사용하기 위해서는 인스턴스를 생성해야 합니다.

let someResolution = Resolution()

 

 

또한 여기서 클래스와 한가지 차이점이 있따면

struct Resolution {
    var width: Int
    var height: Int
}

var someResolution = Resolution(width: 10, height: 10)
print(someResolution)

구조체는 Initializers를 지정해주지 않아도 됩니다.

얼마 전에 공부할 때 사용자 구조체, 클래스 등을 사용하기 위해서는 생성자가 끝나기 전 모든 프로퍼티들이 초기화되어 있어야 한다고 했던거 같은데…

근데 위 코드에서는 값이 없자나여?? 근데 왜 될까요???

(class는 Initializers가 있어야 함)

 

그건 구조체에 memberwise initializer를 기본적으로 제공하기 때문입니다.

 

그래서 굳이 우리가 사용하지 않아도 됐던거임.

하지만 쓰고 싶으면 써두 되고, 모든 프로퍼티의 초기화를 진행해줘야 하는 것은 마찬가지입니다!

 

구조체 내 프로퍼티 접근은 .(dot)을 이용해서 할 수 있습니다.

새로운 값을 할당할 경우에도 마찬가지 입니다!

print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 10"

someResolution.width = 100
print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 100"

구조체는 값 타입!!!!!!

앞에서도 여러번 말했지만 구조체는 값 타입(value type)입니다.

인스턴스 생성 시마다 각각의 값이 복사가 되며, CoW(Copy-on-Write)라는 방법을 통해 복사 비용을 줄인다고 설명했습니다!

다음은 공식문서에 나와있는 설명입니다.


배열, 딕셔너리, 문자열과 같은 표준 라이브러리에 정의된 콜렉션은 최적화를 사용하여 복사 성능 비용을 줄입니다.

즉시 복사본을 만드는 대신에 이러한 콜렉션은 원본 인스턴스와 복사본 간에 요소가 저장된 메모리를 공유합니다.

콜렉션의 복사본 중 하나가 수정되면 요소는 수정되기 직전에 복사됩니다.

코드에서 보이는 동작은 항상 바로 복사가 일어나는 것처럼 보입니다.


값 타입의 속성은 인스턴스 메서드 내에서 수정할 수 없다.

  • 값 타입의 프로퍼티는 인스턴스 메서드 내에서 수정할 수가 없습니다!
    • 이 때문에 mutating 키워드가 존재함!
struct Resolution {
    var width: Int
    var height: Int
    
    func changeWidth() {
        self.width = 500 // Cannot assign to property: 'self' is immutable
    }
}
//  --------------- mutating 키워드를 func 앞에 사용해야 함 ---------------

struct Resolution {
    var width: Int
    var height: Int
    
    mutating func changeWidth() {
        self.width = 500
    }
}

 

근데 클래스는 상관없는데 구조체는 왜 mutating 키워드가 필요하지??

[Swift] 왜 struct에선 mutating을 사용해야하는가?

 

[Swift] 왜 struct에선 mutating을 사용해야하는가?

How is struct(immutability) related to thread safety? Posted in r/swift by u/vingrish • 1 point and 14 comments www.reddit.com Swift and mutating struct There is something that I don't entirely understand when it comes to mutating value types in Swift. A

skytitan.tistory.com

위 블로그를 참고했습니다!

 

이 내용을 이해하기 위해서 블로그를 참조해 작성해보자면

구조체는 mutable, immutable 2가지 모드가 있다고 합니다.

mutable - var 이고 immutable - let 이겠죠???

(이 개념은 구조체에만 있음. 클래스는 ‘참조’이므로 항상 mutable)

 

아 그래서 클래스는 인스턴스를 let으로 선언해도 값을 바꿀 수 있구나 싶은데 맞나?

 

잠깐 딴 길로 빠졌는데 다시 돌아와서 위와 마찬가지로 메소드도 2가지 종류를 가진다고 합니다.

plain, mutating 이렇게요

여기서 plain 상태의 메서드는 앞에 아무 키워드도 없는 default 상태이고 이 때는 immutable 하다고 합니다.

따라서 저 규칙을 지키기 위해 내부 프로퍼티 값을 변경할 수 없는거져

mutating 은 우리가 지금 공부하는 mutating 키워드 이구여

 

그럼 왜 plain 상태(immutable)이 기본값일까요?

만약에 기본 상태가 mutating이라면 값이 변할 수 있으니까 미래의 상태 예측이 어렵고 버그 발생 가능성이 높아서 이라고 합니다~~!!!!!

 

그럼 마지막으로 이것도 저번에 한번 작성했찌만 복습의 개념으루다가

언제 구조체를 사용해야 할까? ( 클래스는 언제?)

Choosing Between Structures and Classes | Apple Developer Documentation

 

Choosing Between Structures and Classes | Apple Developer Documentation

Decide how to store data and model behavior.

developer.apple.com

  • 기본적으로 구조체를 사용
  • Objective-C 와 interoperability(상호 운영성…?)이 필요할 때는 클래스를 사용
    • 머 옵씨 코드랑 같이 으쌰으쌰 해야할 경우를 의미하는 듯
  • Identity를 제어할 필요가 있다면 클래스를 사용
    • Class는 참조 유형이기 때문에 ID 개념이 내장되어 있음.
  • 공유가 필요한 속성을 만들고 싶을 때는 구조체, 프로토콜을 사용하자
    • 상속은 클래스만 되지만, 프로토콜은 클래스, 열거형, 구조체 모두가 채택할 수 있음

사실 여기서 세 번째 말이 잘 이해가 안됐는데 identity가 뭐지…? 싶었음

 

여기서부터는 구조체보단 클래스에 대한 내용이라 참고만 하세요!

 

구조체는 값타입, 클래스는 참조타입! 진짜 입이 닳도록 말했짜나여

그럼 인스턴스를 만들고, 할당할 때 메모리에 저장되는 건 뭘까여

구조체는 그 인스턴스의 값 자체! 가 저장이 될테고, 클래스는 메모리의 주소가 저장이 됩니다.

주소가 가리키는 곳에 실제 인스턴스의 값이 할당이 되는것이 죠!

이때 이 메모리 주소를 identity 입니다! 그리고 주소는 identity operator(===)을 통해 비교할 수 있습니다!

이를 이용해서 클래스의 참조 객체를 관리하거나 할 수 있다고 합니다!


진짜 마지막으로!

클래스는 let으로 선언해도 인스턴스의 프로퍼티 값을 변경할 수 있는 거 아시나요??

import Foundation

class Resolution {
    var width: Int = 10
    var height: Int = 10
    
    func changeWidth() {
        self.width = 500
    }
}

let res1 = Resolution()

print(res1.height) // 10
res1.height = 100

print(res1.height) // 100

그 이유는 위에서 말했듯이 할당되는 값이 인스턴스 의 값 자체가 아닌 메모리 주소라 그렇습니다!

저희가 코드에서 바꾸려고 한 것은 메모리 주소가 아니라 인스턴스의 프로퍼티 값이기 때문에

수정이 가능했던 거구요!

(그래서 사실 height 프로퍼티가 let이라면 변경이 안되는건 당연!)

 

[Swift] 구조체(struct)와 클래스(class)의 공통점과 차이점, 클래스 인스턴스의 identity 의 개념

 

[Swift] 구조체(struct)와 클래스(class)의 공통점과 차이점, 클래스 인스턴스의 identity 의 개념

스위프트의 사용자 정의 타입으로는, 구조체(struct)와 클래스(class), 열거형(enum) 등이 있다. 이번 글에서는 구조체와 클래스의 공통점과 차이점에 대해 정리하고, 어떤 기준으로 둘 중에 하나를

bicycleforthemind.tistory.com

 

'iOS > iOS 기술 면접' 카테고리의 다른 글

KVO(Key-Value Observing)  (0) 2023.11.09
Optional  (1) 2023.11.02
AnyObject  (0) 2023.11.02
Convenience init  (1) 2023.10.31
Copy On Write는 어떤 방식으로 동작할까?  (0) 2023.10.31