[Swift] 클래스와 구조체

Woogie·2022년 6월 16일

Swift에서 클래스와 구조체의 비교는 면접 단골질문이며 둘이 성향이 비슷하다보니 많이 다루는 주제이다.
나는 클래스와 구조체를 공부하면서 서로의 장단점을 알게 되었지만 솔직히 말해서 왜 클래스와 구조체를 따로 만들어서 사용하는지는 잘 이해가 안됬다.

특히 애플 공식문서에서는 클래스보다는 구조체를 더 권장한다고 적혀있다고 한다.
처음에 나는 Swift에서는 프로토콜이 있으니까 클래스 보다 구조체를 자주 사용해도 큰 문제는 없겠다고 생각했었지만 앱을 만들다 보면 클래스로 만든 기능들도 많이 볼 수 있었다.

왜 애플은 비슷한 기능을 따로 나누어서 만들었으며 각자의 특성은 무엇인지
클래스는 어떠한 경우에 사용하며 구조체는 언제 사용하는지
과연 애플이 말하는 클래스보다 구조체를 더 권장한다는 소리가 무엇인지 알아보기로 했다.




Class 와 Struct

Structures and classes are general-purpose, flexible constructs that become the building blocks of your program’s code. You define properties and methods to add functionality to your structures and classes using the same syntax you use to define constants, variables, and functions.
Unlike other programming languages, Swift doesn’t require you to create separate interface and implementation files for custom structures and classes. In Swift, you define a structure or class in a single file, and the external interface to that class or structure is automatically made available for other code to use.

apple의 공식문서에 있는 클래스와 구조체의 정의이다. 프로그램 코드의 구성 요소가 되는 범용적이고 유연한 구성 요소라고 정의하고 있으며, 내가 원하는 기능 만들때 속성과 메서드를 정의하여 상수, 변수, 함수를 정의하는데 사용하는 것과 동일한 구문을 사용하여 구체조와 클래스에 기능을 추가한다고 설명하고 있다. 클래스와 구조체는 프로그램의 코드를 조직화 하기 위해 일반적으로 사용하며 객체지향프로그래밍을 하기위한 필요 요소이다.

An instance of a class is traditionally known as an object. However, Swift structures and classes are much closer in functionality than in other languages, and much of this chapter describes functionality that applies to instances of either a class or a structure type. Because of this, the more general term instance is used.

위의 내용은 클래스와 구조체로 만든 객체를 인스턴스(instance)로 일반적인 용어로 사용된다는 내용이다.

또한 클래스,구조체,열거형에서의 객체,속성,함수는 각각 인스턴스(instance), 프로퍼티(Property), 메서드(Method) 로 사용된다고 한다.




Class, Struct 의 공통점

  • 값을 저장하기 위한 프로퍼티(속성)를 정의할 수 있다.
  • 기능을 제공하기 위한 메소드(함수)를 정의할 수 있다.
  • subscript 문법을 이용해 특정 값을 접근할 수 있는 subscript 정의할 수 있다.
  • 초기 상태를 설정할 수 있는 initializer 정의할 수 있다.
  • 기본 구현에서 확장 기능을 사용이 가능하다. (extention)
  • 프로토콜을 준수하여 특정 종류의 표준 기능 제공, 즉 프로토콜이 사용 가능하다.




Class, Struct 의 차이점

Class

  • 참조타입이다.
  • 상속 (Inheritance) : 클래스의 여러 속성을 다른 클래스에 물려 준다
  • 타입 캐스팅 (Type casting) : 런타임에 클래스 인스턴스의 타입을 확인한다
  • 소멸자 (Deinitializers) : 할당된 자원을 해제(free up) 시킨다
  • 참조 카운트 (Reference counting) : 클래스 인스턴스에 하나 이상의 참조가 가능하다
  • 힙 메모리 영역에 할당한다

Struct

  • 값 타입이다.
  • 인스턴스를 생성할 때 마다 새로운 구조체가 할당한다.
  • 값을 변경하더라도 다른 인스턴스에 영향을 주지 않는다.
  • 스택 메모리 영역에 할당한다.



class와 struct의 사용

클래스와 구조체의 정의와 둘의 공통점과 차이점에 대해서 대략적으로 알아보았다.
하지만 저런 차이점만으로는 어느 상황에서 사용해야하는지 확실하지 않기 때문에 나는 좀더 알아보기로 했다.
그러던 도중 또 공식문서를 Choosing Between Structures and Classes라는 글을 보았다.
역시 답은 공식문서에서부터 찾아라 라는말이 맞는거같다..

여기에 애플은 공식적으로 구조체와 클래스가 언제 사용할지 알려준다.

그리고 Use structures by default. 이 글이 내가 평소에 듣던 클래스보다 구조체를 더 권장하다는 말인거 같다


그렇다면 왜 애플은 구조체가 Default라고 말하는 것일까?

Choose Structures by Default
Use structures to represent common kinds of data. Structures in Swift include many features that are limited to classes in other languages: They can include stored properties, computed properties, and methods. Moreover, Swift structures can adopt protocols to gain behavior through default implementations. The Swift standard library and Foundation use structures for types you use frequently, such as numbers, strings, arrays, and dictionaries.

애플은 이렇게 설명하고있다.

swift의 구조체에서는 다른언어의 클래스와는 다르게 제한되지 않은 많은 기능을 포함하고 있으며, swift는 프로토콜을 채택하여 기본 구현을 통해 동작을 얻을 수 있다. 또한 구조체를 사용하면 앱의 전체 상태를 고려할 필요 없이 코드의 일부에 대해 더 쉽게 추론할수 있다. 구조체는 클래스와 다르게 값 유형이기 때문에 구조체에 값의 변경은 앱의 흐름의 일부이며 의도적으로 전달하지 않아서 앱의 나머지 부분에 표시되지 않는다.

이러한 이유때문에 Apple은 클래스보다 구조체를 더 권장한다고 평소에 많이 볼 수 있던 것이다.

그렇다면 실제로 구조체와 클래스를 사용해야하는 경우에 대해서 알아보자

Class를 사용해야 할 때

Use Classes When You Need Objective-C Interoperability

Objective-C 와 상호 운용성이 필요할 때는 클래스를 사용하라고 애플은 알려주고 있다.
데이터를 처리해야 하는 Objective-C API를 사용하거나 Objective-C 프래임워크에 정의된 기존 클래스 계층에 데이터 모델을 맞추어야 하는 경우 데이터를 모델링하기 위해 클래스 및 클래스 상속을 사용해야 할 수 있기 때문에 클래스로 사용해야 한다는 뜻이다.

Use Classes When You Need to Control Identity

Control Identity을 할 때는 클래스를 사용하라고 알려준다.
클래스는 기본적으로 참조 유형이기 때문에 식별자에 대한 개념이 내장되어 있다. 그래서 서로 다른 두 클래스 인스턴스의 저장된 속성 값이 동일한 경우에도 식별자 연사자에 의해 서로 다른 것으로 간주 된다. 또한 앱에서 클래스 인스턴스를 공유할 떄 해당 인스턴스에 대한 변경 사항이 해당 인스턴스에 대한 참조가 있는 코드의 모든 부분에 표시하기도 한다. 인스턴스가 이러한 종류의 식별자를 가져야 할 때 클래스를 사용하라고 알려주고 있다.

즉 인스턴스의 동일성을 보장해야 할 경우에는 구조체가 아닌 클래스를 사용하라는 이야기이다.
또한 애플은 Identity를 조심히 다루라고 알려주고 있다. 앱 전체에서 클래스 인스턴스를 많이 공유한다면 논리 오류가 발생할 가능성이 높아지기 때문에 공유량이 많은 인스턴스를 변경한다면 어떤 결과가 발생할지 모른다고 말한다. 그러므로 이러한 코드들은 올바르게 작성하는 것이 좋다고 경고하고 있다.

Struct를 사용해야 할 때

Use Structures When You Don’t Control Identity

Control Identity를 사용하지 못할 때 구조체를 사용하라고 알려주고 있다.
제어할 수 없는 Identity를 가진 개체에 대한 정보가 포함된 데이터를 모델링할 때는 구조체를 사용해야한다.

Use Structures and Protocols to Model Inheritance and Share Behavior

구조체와 클래스는 모두 상속을 지원한다. 그러나 구조체와 프로토콜은 프로토콜만 채택할 수 있고 클래스를 상속하지 못한다. 그러나 구조체와 프로토콜을 함께 사용하면 클래스의 상속과 같은 계층 구조를 만들어 사용할 수 있다.

처음부터 상속 관계를 구축한다면 프로토콜 상속을 권장한다. 프로토콜은 클래스, 구조체, 열거형에서도 사용할 수 있지만, 클래스는 오직 클래스만 상속할 수 있기 때문이다. 데이터를 어떻게 모델링할지 결정해야 하는 상황이라면, 프로토콜 상속을 통해 데이터 타입의 계층 구조를 설계하고, 구조체가 해당 프로토콜을 채택하는 방식을 사용해라.

결론

이번에는 문법보다는 왜 구조체와 클래스가 왜 나뉘여서 존재하는지에 대해 알아보았고 어떤 상황에서 구조체와 클래스를 사용해야 하는지 알아보았다.

class와 struct를 공부하면서 기능을 사용할때는 개발사가 만든 이유가 있다고 생각이 들었다. 둘 중에 뭐가 좋고 나쁜지는 잘 모르겠다. 하지만 애플을 두 기능을 만들었고 만든데에는 이유가 있으니 나는 적어도 왜 이 기능을 사용해야하는지 의문을 품고 개발을 하는 것이 필요하다고 생각한다.

profile
어쨌든 iOS개발자

0개의 댓글