Skip to content

Latest commit

 

History

History
247 lines (179 loc) · 12.3 KB

File metadata and controls

247 lines (179 loc) · 12.3 KB

이 글은 Bob the Developer의 Introduction to Protocol Oriented Programming in Swift에 대한 번역입니다.

Swift Protocol Oriented Programming 소개

OOP는 좋습니다. 하지만 더 좋아질 수 있습니다.

저는 아니지만, OOP를 넘어 POP를 사용하는 느낌입니다.

2017년 3월 20일 최종 갱신됨.

소개

이 튜터리얼은 class들과 struct들 사이의 근본적인 차이점에 대해 명확한 해답을 얻지 못한 분들을 위해서 작성되었습니다. 우리 모두가 알다시피 Struct 들에는 상속이 없습니다. 하지만 왜죠?

만약 답을 모르시겠다면, 아래의 코드를 잠시 읽어보세요. 다시, 양식에 대해서는 양해를 구하겠습니다. 가능한한 간결하게 작성하려고 애를 썼습니다.

class HumanClass {
 var name: String
 init(name: String) {
 self.name = name } }
var classyHuman = HumanClass(name: "Bob")
classyHuman.name // "Bob"
var newClassyHuman = classyHuman // Created a "copied" object
newClassyHuman.name = "Bobby"
classyHuman.name // "Bobby"

newClassyHuman의 name 속성을 "Bobby"로 변경했을 때, 원본 객체(classyHuman) 의 name 속성 또한 "Bobby"로 변했습니다.

이제 Struct로 살펴봅시다.

struct HumanStruct {
 var name: String }
var humanStruct = HumanStruct(name: "Bob" )
var newHumanStruct = humanStruct // Copy and paste
newHumanStruct.name = "Bobby"
humanStruct.name // "Bob"

차이점을 아시겠나요? 복사된 객체의 name 속성에 대한 변경은 원래의 humanStruct 객체에 영향을 미치지 않습니다.

Class 들에서는, 값의 복사본을 만들 때, 두 값들은 메모리 상의 같은 객체를 참조하고 있습니다. 값들 중 하나에 대한 변경은 다른 것도 변경시킬 겁니다(참조 타입 - Reference Type).
하지만, Struct 들에서는, 개별 객체를 생성해서 값을 복사해서 붙여넣습니다(값 타입 - Value Type).

아직 모르시겠다면, 이전 단락을 다시 읽어 보세요. 그래도 모르시겠다면, 제가 만든 비디오를 보세요.

Struct vs Class 수업

잘가 OOP

제가 왜 Protocol Oriented Programming 과 상관없어 보이는 이런 것들에 대해서 이야기 하는지 의문스러우실 수도 있습니다. 하지만, OOP를 넘어서 POP를 사용하는 것의 확실한 이점을 이야기 하기 전에, 참조 타입(Reference Type)과 값 타입(Value Type) 사이의 차이점을 이해하셔야 합니다.

확실히 OOP를 사용하는 것의 장점이 있습니다만, 단점도 마찬가지로 있습니다.

1.어떤 클래스를 상속받을 때, 필요없는 속성(property)들과 메소드들까지 상속받아야 합니다. 객체가 필요이상으로 커집니다.

2.많은 super class를 만들 때, 각각의 클래스를 돌아다니며 버그를 고치고 수정하기가 매우 어렵습니다.

3.객체들이 메모리 상에 같은 위치를 참조하고 있기 때문에, 그것의 속성을 복사하고 작은 변경을 만든다면, 나머지들에도 영향을 미칠 수 있습니다.(참조로 인한 가변성)

말이 났으니 말인데, UIKit framework 가 OOP로 어떻게 쓰여져 있는지 봅시다.

2015 WWDC 끔찍한 Structure

처음으로 애플에서 소프트웨어 엔지니어로 일하게 되었다면, 이 코드를 가지고 일할 수 있을 까요? 표면적으로 우리 개발자들이 그것을 사용하는데 어려움을 겪는다는 것을 이야기 하는 겁니다.

OOP는 스파게티 코드를 작성하기 위한 단지 모듈화된 방법이라고 누군가 말했었습니다. 만약, OOP에 대한 나쁜 점을 더 발견하고 싶다면, 과장된 말1, 과장된 말2, 과장된 말 3, 과장된 말 4가 있습니다.

환영합니다. POP

여러분이 추측하는 것이 맞을 겁니다. 클래스와는 다르게, Protocol Oriented Programming 의 근본은 값 타입(Value Type)입니다. 더이상 참조(referencing)는 없습니다. 위에서 본 피라미드 구조와는 다르게, POP는 평평하고(flat) 감싸지지 않은(non-nested) 코드를 권장합니다.

여러분에게 겁을 조금 주기위해서, 애플의 정의를 가져오겠습니다.

"Protocol은 메소드들와 속성(property)들의 "설계도(blueprint)"를 정의합니다... 그런 다음 그 Protocol은 클래스(class), 구조체(structure) 혹은 열거체(enumeration)에 적용될 수 있습니다."
--Apple

여러분이 기억해야 할 한가지는 "설계도(bluprint)"라는 단어 입니다.

Protocol 은 농구 코치와 같습니다. 그는 선수들에게 무엇을 해야 할지 이야기 하지만 실제로 덩크할 줄 모릅니다.

진지하게 POP를 합시다.

우선, human에 대한 설계도(blueprint)를 만듭시다.

protocol Human {
 var name: String { get set }
 var race: String { get set }
 func sayHi() }

여러분이 보시다시피, protocol에는 실제로 "덩크하는 것"이 없습니다. protocol은 단지 어떤 것이 존재하는지만 이야기합니다. { get set } 에 대해서는 지금은 걱정하지 마세요. 이건 단순히 그 property에 다른 어떤 것을 설정(set)할 수 있고 또한 접근할(get) 수 있다는 것을 나타냅니다. 계산되는 property를 사용하지 않는다면, 아직은 걱정하지 마세요.

protocol 을 적용한 Korean struct를 만들어 봅시다.

struct Korean: Human {
 var name: String = "Bob Lee"
 var race: String = "Asian"
 func sayHi() { print("Hi, I'm \(name)") }
}

Human protocol이 구조체(struct)에 적용될 때, 구조체(struct)는 Human protocol에 속하는 모든 속성(property)들과 메소드들을 구현함으로써 그 Human protocol을 준수해야(conform) 합니다. 그렇지 않다면, Xcode가 소리칠 것이고, 왼쪽에 오류를 표시할 겁니다.

아시다시피, 설계도(blueprint)를 만족하는 한 이런 모든 property들을 커스터마이즈할 수 있습니다. 심지어 벽을 쌓을 수도 있습니다.

물론 American에 대해서도 마찬가지 입니다.

struct American: Human {
 var name: String = "Joe Smith"
 var race: String = "White"
 func sayHi() { print("Hi, I'm \(name)") }
}

꽤 멋지죠? 무서운 "init" 이나 "override" 같은 키워드를 사용하지 않는 자유가 얼마나 큰지를 보세요. 이해가 가기 시작하시나요?

Protocol 소개 수업

Protocol 상속

Human protocol 의 설계도(blueprint)를 상속하는 superhuman protocol 만들려면 어떻게 해야 할까요?

protocol SuperHuman: Human {
 var canFly: Bool { get set }
 func punch()
}

이제, SuperHuman이 적용된 struct나 class를 만든다면, 마찬가지로 Human protocol의 요구사항을 만족해야 합니다.

// 💪 Over 9000
struct SuperSaiyan: SuperHuman {
 var name: String = "Goku"
 var race: String = "Asian"
 var canFly: Bool = true
 func sayHi() { print("Hi, I'm \(name)") }
 func punch() { print("Puuooookkk") } }

참고할 것이 없는 분들은, 동영상을 보세요.

물론, 하나 이상의 클래스를 상속하는 것(다중 상속) 처럼 많은 protocol을 준수할(conform) 수 있습니다.

// Example
struct Example: ProtocolOne, ProtocolTwo { }

Protocol 상속 수업

Protocol 확장

Protocol 확장은 프로토콜을 사용하는데 있어서 가장 강력한 특징입니다. 많이 이야기 할 필요가 없습니다.

// Super Animal speaks English
protocol SuperAnimal {
 func speakEnglish() }

SuperAnimal 에 확장을 추가하세요.

extension SuperAnimal {
 func speakEnglish() { print("I speak English, pretty cool, huh?")}}

SuperAnimal이 적용된 class를 만들어 봅시다.

class Donkey: SuperAnimal { }
var ramon = Donkey()
ramon.speakEnglish() //  "I speak English, pretty cool, huh?"

확장(extension)을 사용한다면, 기본(default) 함수들과 속성(property)들을 class, struct 그리고 enum 에 추가할 수 있습니다. 멋지지 않나요? 저는 이것을 진짜 중요한 것으로 여깁니다.

만약 참고할 사항이 없으시다면, 이것을 보세요.

Protocol 확장 수업

타입으로서의 Protocol(마지막)

형변환(type casting) 없이 struct 객체와 class 객체를 둘다 모두 포함하는 배열을 만들려면 어떻게 해야 할까요?

네 맞습니다.

예를 들어, 저는 암컷을 차지하기 위해 싸우는 캥거루들을 사용할 겁니다. 저를 못 믿으시겠다면, 이 캥거루 싸움을 보세요.

protocol Fightable {
 func legKick() }
struct StructKangaroo: Fightable {
 func legKick() { print("Puuook") } }
class ClassKangaroo: Fightable {
 func legKick() {print("Pakkkk") } }

이제 캥거루 객체들을 만듭시다.

let structKang = StructKangaroo()
let classKang = ClassKangaroo()

이제 그 캥거루들을 배열로 합칠 수 있습니다.

var kangaroos: [Fightable] = [structKang, classKang]

헐. 정말로? 이것 보세요.

for kang in kangaroos { kang.legKick() }
// "Puuook"
// "Pakkkk"

아름 답지 않나요? 이걸 OOP에서는 어떻게 할 수 있을까요? 이제 위에 나온 커버 이미지가 이해가 되시나요? POP는 진짜 좋습니다.

타입으로서 Protocol 수업

파트 2

이제 POP를 진짜 앱에 적용합시다! 여기를 클릭하세요.

최후 발언

이 튜터리얼이 유용하셨고 제가 유용한 일을 했다고 생각하신다면, 저를 위해서 ❤️ 를 주세요. 그리고 커뮤니티에 공유해주세요. 저는 더 많은 iOS 개발자들이 POP를 구현해야 한다고 선언합니다! 저는 그렇게 하려고 노력중이고, 그것이 제가 이 글을 쓰는 이유입니다. 하지만 더 큰 효과를 위해 여러분의 도움이 필요합니다.

외침

여기 저기 이슈를 충분히 지적해주시기 위해 노력하고 관심을 기울여주신 분들께 특별히 감사드립니다. Kilian Költzsch, Erik Krietsch, Özgür Celebi, Sanchika Singh Rana, Frederick C. Lee, moh tabi, october hammer, Anthony Kersuzan, Kenneth Trueman, Wilson Balderrama, Rowin, Quang Dinh Luong, Oren Alalouf, Peter Witham, Victor Tong.

새로 나올 것

이번 주 토요일에 Switt3 에서 Protocol을 한 Delgate 디자인 패턴에 대해서 글을 쓸 겁니다. 몇몇 분들이 저에게 그것에 대해서 글을 써줄 것을 요청하셨습니다. 그래서 그분들의 의견에 따르기로 했습니다. 빠른 갱신을 원하시거나 다른 주제를 요청하기 원하신다면, 제가 책임지고 있는 Bob the Developer 페이스북 페이지를 follow할 수 있습니다. 곧 다시봐요! 저로 부터 더 많은 것들을 얻고 싶으시다면, 개인 메일링 리스트에 가입하실 수 있습니다.

자료들

자료 페이지

감사합니다.