[1편] 목차
1. Swift의 등장 배경
2. Swift의 특징
3. Objective-C와 구별되는 기능
[2편] 목차 👈
4. Swift의 프로그래밍 패러다임4.1. 패러다임에 대한 배경지식
4.2. 객체지향 프로그래밍 패러다임
4.3. 함수형 프로그래밍 패러다임
4.4. 프로토콜지향 프로그래밍 패러다임
Swift의 프로그래밍 패러다임은 내용이 조금 길어져 "Swift 언어에 대해서 알아보자 1편"에 이어서 작성해보겠다.
Swift는 다중 패러다임 프로래밍 언어(multiparadigm programming language)로 아래 3가지 패러다임을 모두 지원한다.
- 객체지향 프로그래밍 패러다임
- 함수형 프로그래밍 패러다임
- 프로토콜지향 프로그래밍 패러다임
👨🏫 Swift에서 지원하는 기능에 이 3가지 패러다임이 모두 녹아져 있는 것이 사실이지만, iOS 프레임워크가 객체지향형 프로그래밍으로 구현되어 있기 때문에 객체지향으로 구현하는 것이 권장된다.
4.2~4.4에서는 Swift에서 각각의 패러다임들이 어떻게 녹아져있는지 간략하게 보고 넘어가겠다. 구체적으로 코드가 어떻게 적용되었는지는 추후 좀 더 자세하게 다루겠다.
- '명령형' 프로그래밍 패러다임은 어떤 문제를 "how(어떻게)" 수행할지의 관점에서 수행해야될 명령들을 순차적으로 적어 프로그래밍하는 방식이다.
- '객체 지향형'과 '절차 지향형'은 명령형 프로그래밍 패러다임에 포함된다.
- '선언형' 프로그래밍 패러다임은 어떤 문제에 대해 "what(무엇)"을 나타낼지의 관점에서 프로그래밍하는 방식이다.
- '함수형'과 '논리형'은 선언형 프로그래밍 패러다임에 포함된다.
👨🏫 객체지향 프로그래밍 패러다임은 Java와 C++의 패러다임으로 이미 유명하고 다들 익히 알고 있기 때문에 간단하게만 설명하고 넘어가겠다.
1) 소프트웨어 개발이 간편해진다.
➡️ 클래스의 상속을 통해 코드를 재사용함함으로써 개발이 쉬워진다.
2) 응집력은 강화되고 결합력은 약한 프로그램을 개발할 수 있다.
➡️ 프로퍼티와 메서드를 클래스로 캡슐화하면 응집력은 강화시키고 결합력은 약화시킬 수 있기 때문이다.
3) 이로써 유지보수가 또한 간편해진다.
- Swift에서는 일반 객체지향 프로그래밍과 동일하게 객체를 만드는 장치인 Class가 있다.
- iOS 프레임워크들이 객체지향으로 구현되어 있다.
🤔 함수형 프로그래밍 패러다임은 다소 생소한 부분이 있어 조금 더 자세하게 정리해보았다.
함수형 프로그래밍은 계산을 수학적 함수의 조합으로 생각하고, 이러한 함수들의 조합으로 프로그램을 작성하는 프로그래밍 패러다임이다.
따라서 이 패러다임에서는 함수 자체의 응용을 중요하게 여긴다.
함수형 패러다임에서 사용되는 함수는 순수함수여야 하며 고차함수의 개념을 활용한다.
- '순수함수(Pure Function)'는 입력값이 같으면 항상 같은 결과값을 반환하고,부작용(Side Effect)이 없는 함수를 의미한다.
- 여기서 말하는 '부작용(Side Effect)'이란 함수 내부에서 함수 외부의 어떤 변수나 상태를 변경하는 것을 의미한다.
- '고차함수(Higher order function)'는 함수 작성시 함수를 전달인자로 받거나 함수실행의 결과를 함수로 반환하는 함수를 의미한다.
1) 대규모 병렬처리가 굉장히 쉬워진다.
➡️ 순수 함수는 동일한 입력값에 대해서는 항상 동일한 출력값을 반환하므로, 병렬 처리를 쉽게 작성할 수 있는 이점이 있다.2) 코드 유지보수성이 높아진다.
➡️ 순수함수 및 고차함수로 코드를 작성하다 보면 코드가 간결해지고 부작용(Side Effect) 없이 예측 가능한 동작을 보장할 수 있게되기 때문이다.
물론 함수형 프로그래밍 패러다임에 단점도 있다.
1) 학습곡선이 높다.
- 객체 지향 프로그래밍과는 다른 개념과 방법론이 사용되기 때문에, 처음에는 학습 곡선이 높을 수 있다.
- 함수형 프로그래밍은 부작용이 없는 함수들로 이루어지므로, 이러한 함수들을 작성하고 이해하는 데 초반에는 시간이 필요하다.
2) 성능이 저하될 수 있다.
- 함수형 프로그래밍에서는 재귀함수나 람다식을 자주 사용한다. 이러한 함수들은 잘못 사용할 경우 메모리 사용량이 많아지고, 실행 시간도 길어질 수 있다. 따라서 성능이 중요한 경우 함수형 프로그래밍보다 다른 방식이 더 적합할 수 있다.
따라서 위와 같은 장단점을 고려하여, 함수형 프로그래밍을 사용할지 여부를 결정해야 한다.
그래셔 Swift에서는 어떻게 함수형 프로그래밍 패러다임을 지원하는가?
- Swift에는 표준 라이브러리로 고차함수인 filter, map, flatMap, reduce 등의 기능을 제공하며 함수형 프로그래밍으로 구현되어 있다.
- 주로 배열을 응용해서 사용할 때 많이 사용되는 라이브러리다.
🤔 '프로토콜(Protocol)'이라는 기능과 '프로토콜지향 프로그래밍 패러다임'은 Swift를 공부하면서 처음 알게된 개념이었던 것 같다. 객체지향보다는 조금 더 자세하게 적어보겠다.
'프로토콜지향 프로그래밍 패러다임(POP, Protocol Oriented Programming)'이란 필요한 부분만 프로토콜로 분리하여 프로그래밍하고, 참조타입보다는 값 타입을 더 효율적으로 사용하여 오류를 줄이는 방법이다.
Swift 2.0 버전에 프로토콜과 익스텐션 기능이 추가되면서 프로토콜지향 패러다임을 지원하게 되었다. (WWDC에서 애플이 Swift가 세계 최초의 프로토콜 지향 프로그래밍 언어라고 발표했다.)
참고로 Swift에서 대부분의 Type은 구조체로 구현이되어 있는데, 상속도 불가능한 구조체가 다양하고 공통된 기능을 가질 수 있었던 이유는 Swift의 프로토콜 기능때문이다. (객체지향 패러다임을 지향하는 언어의 Type은 대부분 class로 구현되어 있다.)
OOP(객체지향 프로그래밍)는 상속을 통해 코드 재사용이 가능하지만 아래와 같은 단점 2가지가 존재한다.
1) 불필요한 요소까지 상속
서브클래싱의 경우 Sub Class는 Super Class의 불필요한 변수와 함수를 상속받아야 한다.2) Reference Type으로만 사용 가능
Class를 상속받으면 무조건 참조타입으로 생성되기 때문에, 값 타입으로 생성해도 되는 객체를 참조타입으로 생성하게되어 참조비용이 발생하게 된다.
이를 해결할 수 있는 것이 프로토콜 기능이다.
프로토콜(protocol)이란?
- '프로토콜(protocol)' 이란 특정 기능에 필요한 메소드, 프로퍼티만 따로 선언만해 놓은 것을 말한다. (Java의 Interface와 유사)
- 프로토콜은 채택시 해당 프로토콜에 선언된 프로퍼티와 메서드는 반드시 정의해야 하는 특징을 갖고 있다.
- 그럼 "class와 마찬가지로 불필요한 것까지 다 구현해야 하는거는 똑같지 않나?🤔" 라고 생각할 수 있다.
- 프로토콜은 애초에 Super Class와 독립적으로 내가 필요한 기능들만 다로 떼서 구현하겠다에서 출발한 개념이다.
- 따라서 프로토콜을 사용함으로써 필요한 기능들만 압축적으로 구현할 수 있다.
프로토콜지향 프로그래밍 패러다임은 다음과 같은 장점이 있다.
1) 다중 상속의 한계 극복
- 클래스는 다중 상속이 불가능하여 단 하나의 슈퍼클래스만 상속받아 구현해야 한다는 단일 상속의 원칙을 따른다.
- 하지만 프로토콜은 여러 프로토콜을 채택하여 구현이 가능하다.
2) 값 타입(Value Type) 사용 가능
- 클래스를 상속받아 사용할 경우 무조건 '참조 타입(Reference Type)'으로 생성이 되지만, 프로토콜의 경우 '값 타입(Value Tupe)'과 '참조 타입(Reference Type)' 모두 지원한다.
- 따라서 값 타입 사용 시, 상속을 할 수 없으므로 매번 기능을 다시 구현해야 했던 한계를 극복할 수 있게 되었다.
3) 필요한 기능만 구현
- SuperClass에 독립적으로 불필요한 API를 제외하고 정의한 API만 가져와 구현이 가능해졌다.
- 또한, 무엇을 구현해야 하는지가 명확해졌다고 할 수 있다.
그럼 class 대신에 protocol만 사용하면 되는거 아닐까?
- 물론 Swift에서 값타입인 struct 사용을 권장한다. 따라서 참조타입만 지원하는 class보다는 참조타입과 값타입을 모두 지원하는 protocol을 사용하는 것이 나을 수 있다. (struct와 enum 같은 값타입이 class 만큼 자주 사용되는 것을 볼 수 있다.)
- class는 프로그램 모델링시 수직적으로 구현하고, protocol은 수평적이라는 특징이 있다.
- 현실세계에 있는 것을 프로그램으로 그대로 옮길 때, protocol만 사용해서 구현이 가능할수도 있지만 class와 protocol을 상황에 따라 적절한 것을 채택하여 구현하는 것이 적절하다고 볼 수 있을 것 같다.