Letswift pop in swift cover

Swift에서 프로토콜 중심 프로그래밍(POP)하기

Let’Swift는 Swift 개발자들이 만나고, 배우고, 즐기는 컨퍼런스로 총 13개의 세션으로 이뤄졌습니다. Swift 개발자들이 모여 iOS의 넥스트 스텝을 이야기한 행사였습니다. 빠르게 발전하는 언어 Swift에 대한 뜨거운 열의를 엿볼 수 있었던 Let’Swift 행사 동영상을 공유합니다

Swift로 프로토콜 중심 프로그래밍을 하는 것에 관심이 있으신가요? 그렇다면 프로토콜 중심 프로그래밍에 대해 알아보고 장단점과 실제로 프로젝트에 어떻게 적용해야 할지도 궁금하실 겁니다. Protocol Oriented Programming in Swift라는 주제로 조성규님이 발표한 세션 동영상을 통해 궁금증을 해소하세요.


Protocol Oriented Programming in Obective-C

  • in Obective-C
    • 단지 기능의 청사진의 역할을 수행
    • 주로 Delegate, DataSource 등으로 이용
    • 기본 구현 (Default Implementation) 불가 (ex. 카테고리 적용 불가)
  • in Swift
    • Objective-C의 프로토콜 기능은 기본
    • 기본 구현(Default Implementation) 가능
      • Protocol + Extension = Protocol extension
      • 특정 타입이 할 일 지정 + 구현을 한 방에!
  • Protocol extension

    • Protocol default implimentation: 프로토콜을 따르겠다고 선언만 하면 어디서든 해당 프로토콜의 기능을 사용할 수 있음


  • Protocol을 만들게 된 배경 idea
    • 상속의 한계: 서로 다른 클래스에서 상속받은 클래스는 동일한 기능을 구현하기 위해 중복코드 발생 -> Protocol default implimentation으로 해결
    • 카테고리의 한계: 프로퍼티 추가 불가, 오직 클래스에만 적용 가능, 기존 메서드를 (자신도 모르게) 오버라이드 가능 -> Protocol default implimentation으로 해결
    • 참조타입의 한계: 동적 할당과 참조 카운팅에 많은 자원 소모 -> Value Type으로 해결


프로토콜 중심 프로그래밍과 밸류 타입을 (소셜미디어) 프로젝트에 적용하기

기획 1) 타임라인을 나타낼 수 있는 테이블 뷰 컨트롤러 구성하기

이런 개발 뉴스를 더 만나보세요

  • TimelineTableViewCell

기획 2) 사진첩처럼 볼 수 있는 모드 추가

  • model에 프로토콜 중심 프로그래밍과 밸류 타입 적용하기


  • 프로토콜 명시하기 (싱글턴 객체가 밸류 타입 프로퍼티를 가지고 이를 공유함)
class TimelineTableViewController: UITableViewController,
    ContainContents { //... }
class TimelineCollectionViewController: UITableViewController,
    ContainContents { //... }

protocol ContainContents {
    var contents: [Content] { get }
}

class TimelineContentObject {
    static let shared = TimelineContentObject() var contents: [Content] = [Content]()
}

extension ContainContents {
    var contents: [Content] {
        return TimelineContentObject.shared.contents
    }
}
  • view에 프로토콜 중심 프로그래밍과 밸류 타입 적용하기
    • 프로토콜 명시하기
    • 같은 기능과 역할을 수행하도록 기능 블럭을 가져와서 사용할 수 있음
protocol MediaContainer: class {
    var content: Content? { get set }
    var media: UIImageView { get }
    var note: UILabel { get set }

    func contentChanged()
}

extension MediaContainer {
    func contentChanged() {
        // Update view...
    }
}

class TimelineTableViewCell: UITableViewCell,
    MediaContainer {
    var media: UIImageView
    var note: UILabel
    var content: Content? {
        didSet {
            contentChanged()
        }
    }
}

class TimelineCollectionViewCell: UICollectionViewCell,
    MediaContainer {
    var media: UIImageView
    var note: UILabel
    var content: Content? {
        didSet {
            contentChanged()
        }
    }
}

class DetailViewController: UIViewController,
    MediaContainer {
    var media: UIImageView
    var note: UILabel
    var content: Content? {
        didSet {
            contentChanged()
        }
    }
}
  • Controller에 프로토콜 중심 프로그래밍과 밸류 타입 적용하기
    • tableViewController와 collectionViewController의 공통 기능인 다음화면 보여주기 기능을 뽑아 프로토콜로 만들기
protocol CanShowDetailView {
    func showDetailView(withContent content: Content)
    var navigationController: UINavigationController? { get }
}

extension CanShowDetailView {
    func showDetailView(withContent content: Content) {
        // Show detail view...
    }
}

class TimelineTableViewController: UITableViewController,
    ContainContents, CanShowDetailView {
    // ...
}

class TimelineCollectionViewController: UITableViewController,
    ContainContents, CanShowDetailView {
    // ...
}

기획 3) 영상을 볼 수 있는 모드 추가

  • Refactoring하기
    • 셀의 imageView 부분을 image와 video 모두 표현 가능하도록 변경
    • var media에 들어가는 타입을 기존 UIImageView에서 프로토콜로 변경
protocol ContentPresentable: class, Layout {
    var frame: CGRect { get set }
    var canPresentContent: Bool { get }
}

extension ContentPresentable {
    var canPresentContent: Bool {
        return true
    }
}

extension UIImageView: ContentPresentable { }
extension AVPlayerLayer: ContentPresentable { }
  • container 프로토콜 변경
    • extension에 computed property 추가

Swift에서 프로토콜 중심 프로그래밍하기의 장점

  • 범용적인 사용
    • 클래스, 구조체, 열거형 등등 모든 타입에 적용 가능
    • 제네릭과 결합하면 더욱 파급적인 효과 (Type safe & Flexible code): 하나의 타입으로 지정 가능
  • 상속의 한계 극복
    • 특정 상속 체계에 종속되지 않음
    • 프레임워크에 종속적이지 않게 재활용 가능
  • 적은 시스템 비용
    • Reference type cost > Value type cost
  • 용이한 테스트
    • GUI 코드 없이도 수월한 테스트

Swift에서 프로토콜 중심 프로그래밍하기의 한계

  • Objective-C 프로토콜에 Swift Extension을 붙여도 Protocol default implimentation이 구현되지 않음
  • 자주 사용되는 Delegate, DataSource 등 프레임워크 프로토콜에 기본 구현 불가

결론

  • Value Type을 사용하여 성능상의 이득을 취하자
  • Protocol + Extension + Generic은 환상의 조합이다
  • 이제 상속을 통한 수직 확장이 아닌 Protocol과 Extension을 통한 수평 확장과 기능추가를 고민해 볼 때

참고 자료


발표 슬라이드는 아래를 참고해주세요.

다음: iOS 프로그래밍 아키텍처와 패러다임 #3: 실무에서 활용하는 프로토콜 중심 프로그래밍

General link arrow white

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.

Realm Team

Realm의 미션은 더 나은 앱을 빠르게 개발할 수 있도록 돕는 것입니다. 이를 위해 저희는 개발자들이 실시간 협업, 가상 현실, 라이브 데이터 동기화, 오프라인 경험, 메시징 등 정교하고 강력한 기능을 쉽게 개발할 수 있도록 하는 개발 도구와 플랫폼을 제공하고 있습니다.

저희는 모바일 인터넷이 수많은 사용자와 보다 많은 디바이스가 속한 개방형 네트워크와 이들 간의 실시간 상호 작용으로 진화할 것이라고 믿으며, 개발자가 이같은 방향으로 발전할 수 있도록 돕기 위해 저희 제품들을 개발하고 있습니다.

4 design patterns for a RESTless mobile integration »

close