클래스와 프로토콜의 차이
Swift에서는 클래스 상속과 프로토콜 채택을 활용하여 코드의 재사용성을 높일 수 있습니다. 언뜻 보면 비슷해 보이지만, 각각의 역할과 사용 목적이 다릅니다. 어떤 상황에서 클래스를 사용하고, 언제 프로토콜을 사용하는 것이 더 적절한지 고민해보았습니다.
클래스의 상속
클래스 상속은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 부모 클래스의 기능을 자식 클래스가 물려받아 사용할 수 있습니다.
예를 들어, iOS 개발에서 UIViewController를 상속하면 기본적인 화면 관리 기능을 그대로 사용할 수 있습니다.
class CustomViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("CustomViewController Loaded")
}
}
클래스 상속의 장점은 다음과 같습니다.
- 코드 재사용성
- 공통 기능을 부모 클래스에서 정의하고, 여러 하위 클래스에서 재사용할 수 있습니다.
- 다형성(Polymorphism)
- 부모 클래스의 기능을 하위 클래스에서 **오버라이딩(override)**하여 커스터마이징할 수 있습니다.
하지만 상속은 다음과 같은 단점을 지니고 있습니다.
- 상속을 위해 캡슐화가 깨질 수 있습니다.
- 상속의 장점은 다형성을 구현할 수 있다는 것이 있는데, Swift 언어에선 외부 클래스에서도 접근할 수 있는 단점이 존재합니다. Java는 protected 라는 키워드를 통해 외부 클래스에서의 접근이 불가능하지만, Swift에서는 외부 클래스의 접근을 막을 수 없어 캡슐화가 깨질 수 있습니다.
- 상위 클래스에 의존적입니다. (강한 결합)
- 부모 클래스의 변경이 하위 클래스에 영향을 미쳐 예기치 않은 버그를 초래할 수 있습니다.
- 불필요한 기능 상속
- SOLID 원칙 중 ISP(인터페이스 분리 원칙) 을 위반할 가능성이 있습니다. (필요하지 않은 기능까지 상속받아야 할 수도 있음)
- 다중 상속이 불가능합니다.
- Swift는 다중 상속을 지원하지 않으므로, 한 개의 클래스만 상속받을 수 있습니다.
프로토콜
프로토콜(Protocol)은 특정 행동(행위)을 정의하는 규약으로, 클래스뿐만 아니라 구조체(struct), 열거형(enum)도 채택할 수 있습니다.
예를 들어, UITableViewDataSource 프로토콜을 채택하여 테이블뷰의 데이터 소스를 설정할 수 있습니다.
protocol Animal {
func makeSound()
}
class Dog: Animal {
func makeSound() {
print("Woof!")
}
}
class Cat: Animal {
func makeSound() {
print("Meow!")
}
}
프로토콜의 장점은 다음과 같습니다.
- 유연한 설계
- 특정 기능을 개별적으로 추가할 수 있어, 단일 책임 원칙(SRP)을 지킬 수 있습니다.
- 다중 채택 가능
- 여러 개의 프로토콜을 동시에 채택할 수 있어, 다중 상속의 한계를 극복할 수 있습니다.
- 프로토콜을 통해 불필요한 기능을 줄일 수 있어, ISP(인터페이스 분리 원칙)를 준수할 수 있게 됩니다.
- 프로토콜을 꼭 필요한 행위에 대해서만 정의하기 때문에 해당 프로토콜을 준수한다는 것은 ‘해당 프로토콜에 정의된 내용은 꼭 사용해야 함’을 의미하는 것입니다. 즉, 불필요한 기능에 대해 추가가 되지 않을 수 있지만, 상속을 하게 되면 모든 기능을 상속받기 때문에 불필요한 기능 또한 상속받을 가능성이 존재합니다.
- 클래스 외에도 적용 가능
- 구조체, 열거형도 프로토콜을 채택할 수 있어, 값 타입을 활용한 설계가 가능합니다.
- 의존성 제거
- 특정 클래스를 상속받지 않고도, 공통된 기능을 정의할 수 있습니다.
하지만 프로토콜 또한 다음과 같은 사항을 주의해야 합니다.
- 구현 강제
- 프로토콜을 채택하면 요구된 모든 메서드를 반드시 구현해야 합니다.
- 복잡성 증가
- 지나치게 많은 프로토콜을 사용하면 코드가 분산되고, 유지보수가 어려워질 수 있습니다.
클래스와 프로토콜의 적절한 사용 기준
클래스와 프로토콜의 역할과 특징을 기반으로 클래스는 새로운 객체(컴포넌트)를 만들 때 사용하고, 프로토콜은 특정 행위를 정의할 때 사용하는 것이 적절하다고 생각하였습니다.
예를 들어 UIViewController나 UITableViewCell처럼 특정 기능을 가진 컴포넌트를 만들 때 클래스 상속을 활용하면 기본 기능을 재사용할 수 있어 코드의 중복을 줄일 수 있습니다. 상속을 통해 부모 클래스의 속성과 메서드를 가져올 수 있으며, 필요한 경우 오버라이딩하여 동작을 변경할 수도 있습니다.
반면, 프로토콜은 객체의 유형(Type)을 정의하는 것이 아니라, 그 객체가 어떤 기능을 수행해야 하는지를 선언하는 역할을 합니다. 예를 들어, UITableViewDataSource나 UITableViewDelegate 같은 프로토콜을 채택하면, 특정 기능을 수행해야 한다는 것을 보장할 수 있습니다. 프로토콜은 다중 채택이 가능하기 때문에, 하나의 객체가 여러 가지 역할을 수행해야 할 때 유용합니다. 또한, 클래스뿐만 아니라 구조체와 열거형에서도 채택할 수 있어, 보다 유연한 설계를 가능하게 합니다.
따라서, 컴포넌트를 만들고 재사용성을 높이기 위해서는 클래스를 사용하고, 특정한 기능을 정의하고 유연성을 높이기 위해서는 프로토콜을 활용하는 것이 더 적절하다고 판단하였습니다. 추후 개발부터는 뷰 컨트롤러나 모델 객체를 설계할 때 클래스를 사용하고, 뷰 컨트롤러 간의 데이터 전달이나 특정 이벤트 처리를 할 때는 프로토콜을 활용하고자 합니다.
'Swift' 카테고리의 다른 글
[Swift] 스위프트 - Character를 Int로 변환 (wholeNumberValue) (0) | 2024.01.01 |
---|---|
[Swift] 스위프트 - 배열에 있는 문자와 문자열 간단하게 출력하기 (String, joined, sorted) (0) | 2024.01.01 |
[Swift] 스위프트에서의 ,와 &&의 차이점 (2) | 2023.12.28 |
[Swift] Swift의 메모리 구조 (0) | 2023.08.18 |
[Swift] Swift API Design Guidelines 요약 및 정리 (0) | 2023.08.14 |
클래스와 프로토콜의 차이
Swift에서는 클래스 상속과 프로토콜 채택을 활용하여 코드의 재사용성을 높일 수 있습니다. 언뜻 보면 비슷해 보이지만, 각각의 역할과 사용 목적이 다릅니다. 어떤 상황에서 클래스를 사용하고, 언제 프로토콜을 사용하는 것이 더 적절한지 고민해보았습니다.
클래스의 상속
클래스 상속은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 부모 클래스의 기능을 자식 클래스가 물려받아 사용할 수 있습니다.
예를 들어, iOS 개발에서 UIViewController를 상속하면 기본적인 화면 관리 기능을 그대로 사용할 수 있습니다.
class CustomViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("CustomViewController Loaded")
}
}
클래스 상속의 장점은 다음과 같습니다.
- 코드 재사용성
- 공통 기능을 부모 클래스에서 정의하고, 여러 하위 클래스에서 재사용할 수 있습니다.
- 다형성(Polymorphism)
- 부모 클래스의 기능을 하위 클래스에서 **오버라이딩(override)**하여 커스터마이징할 수 있습니다.
하지만 상속은 다음과 같은 단점을 지니고 있습니다.
- 상속을 위해 캡슐화가 깨질 수 있습니다.
- 상속의 장점은 다형성을 구현할 수 있다는 것이 있는데, Swift 언어에선 외부 클래스에서도 접근할 수 있는 단점이 존재합니다. Java는 protected 라는 키워드를 통해 외부 클래스에서의 접근이 불가능하지만, Swift에서는 외부 클래스의 접근을 막을 수 없어 캡슐화가 깨질 수 있습니다.
- 상위 클래스에 의존적입니다. (강한 결합)
- 부모 클래스의 변경이 하위 클래스에 영향을 미쳐 예기치 않은 버그를 초래할 수 있습니다.
- 불필요한 기능 상속
- SOLID 원칙 중 ISP(인터페이스 분리 원칙) 을 위반할 가능성이 있습니다. (필요하지 않은 기능까지 상속받아야 할 수도 있음)
- 다중 상속이 불가능합니다.
- Swift는 다중 상속을 지원하지 않으므로, 한 개의 클래스만 상속받을 수 있습니다.
프로토콜
프로토콜(Protocol)은 특정 행동(행위)을 정의하는 규약으로, 클래스뿐만 아니라 구조체(struct), 열거형(enum)도 채택할 수 있습니다.
예를 들어, UITableViewDataSource 프로토콜을 채택하여 테이블뷰의 데이터 소스를 설정할 수 있습니다.
protocol Animal {
func makeSound()
}
class Dog: Animal {
func makeSound() {
print("Woof!")
}
}
class Cat: Animal {
func makeSound() {
print("Meow!")
}
}
프로토콜의 장점은 다음과 같습니다.
- 유연한 설계
- 특정 기능을 개별적으로 추가할 수 있어, 단일 책임 원칙(SRP)을 지킬 수 있습니다.
- 다중 채택 가능
- 여러 개의 프로토콜을 동시에 채택할 수 있어, 다중 상속의 한계를 극복할 수 있습니다.
- 프로토콜을 통해 불필요한 기능을 줄일 수 있어, ISP(인터페이스 분리 원칙)를 준수할 수 있게 됩니다.
- 프로토콜을 꼭 필요한 행위에 대해서만 정의하기 때문에 해당 프로토콜을 준수한다는 것은 ‘해당 프로토콜에 정의된 내용은 꼭 사용해야 함’을 의미하는 것입니다. 즉, 불필요한 기능에 대해 추가가 되지 않을 수 있지만, 상속을 하게 되면 모든 기능을 상속받기 때문에 불필요한 기능 또한 상속받을 가능성이 존재합니다.
- 클래스 외에도 적용 가능
- 구조체, 열거형도 프로토콜을 채택할 수 있어, 값 타입을 활용한 설계가 가능합니다.
- 의존성 제거
- 특정 클래스를 상속받지 않고도, 공통된 기능을 정의할 수 있습니다.
하지만 프로토콜 또한 다음과 같은 사항을 주의해야 합니다.
- 구현 강제
- 프로토콜을 채택하면 요구된 모든 메서드를 반드시 구현해야 합니다.
- 복잡성 증가
- 지나치게 많은 프로토콜을 사용하면 코드가 분산되고, 유지보수가 어려워질 수 있습니다.
클래스와 프로토콜의 적절한 사용 기준
클래스와 프로토콜의 역할과 특징을 기반으로 클래스는 새로운 객체(컴포넌트)를 만들 때 사용하고, 프로토콜은 특정 행위를 정의할 때 사용하는 것이 적절하다고 생각하였습니다.
예를 들어 UIViewController나 UITableViewCell처럼 특정 기능을 가진 컴포넌트를 만들 때 클래스 상속을 활용하면 기본 기능을 재사용할 수 있어 코드의 중복을 줄일 수 있습니다. 상속을 통해 부모 클래스의 속성과 메서드를 가져올 수 있으며, 필요한 경우 오버라이딩하여 동작을 변경할 수도 있습니다.
반면, 프로토콜은 객체의 유형(Type)을 정의하는 것이 아니라, 그 객체가 어떤 기능을 수행해야 하는지를 선언하는 역할을 합니다. 예를 들어, UITableViewDataSource나 UITableViewDelegate 같은 프로토콜을 채택하면, 특정 기능을 수행해야 한다는 것을 보장할 수 있습니다. 프로토콜은 다중 채택이 가능하기 때문에, 하나의 객체가 여러 가지 역할을 수행해야 할 때 유용합니다. 또한, 클래스뿐만 아니라 구조체와 열거형에서도 채택할 수 있어, 보다 유연한 설계를 가능하게 합니다.
따라서, 컴포넌트를 만들고 재사용성을 높이기 위해서는 클래스를 사용하고, 특정한 기능을 정의하고 유연성을 높이기 위해서는 프로토콜을 활용하는 것이 더 적절하다고 판단하였습니다. 추후 개발부터는 뷰 컨트롤러나 모델 객체를 설계할 때 클래스를 사용하고, 뷰 컨트롤러 간의 데이터 전달이나 특정 이벤트 처리를 할 때는 프로토콜을 활용하고자 합니다.
'Swift' 카테고리의 다른 글
[Swift] 스위프트 - Character를 Int로 변환 (wholeNumberValue) (0) | 2024.01.01 |
---|---|
[Swift] 스위프트 - 배열에 있는 문자와 문자열 간단하게 출력하기 (String, joined, sorted) (0) | 2024.01.01 |
[Swift] 스위프트에서의 ,와 &&의 차이점 (2) | 2023.12.28 |
[Swift] Swift의 메모리 구조 (0) | 2023.08.18 |
[Swift] Swift API Design Guidelines 요약 및 정리 (0) | 2023.08.14 |