본문 바로가기

개발/Swift

[Swift] 프로토콜 지향 프로그래밍

반응형
 

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

Protocol Oriented Programming in Swift라는 주제로 조성규님이 발표해 주셨습니다. 요즘 뜨고있는 프로토콜 중심 프로그래밍에 대해 알아보고 장단점과 실제로 프로젝트에 어떻게 적용해야 할지 쉽게 설

academy.realm.io

Swift는 프로토콜 지향 프로그래밍 언어로 유연하고 확장성 있는 패러다임이 발전한 언어다.

 

많이 들어보았던 프로토콜 지향 프로그래밍 언어(POP)
Swift의 프로토콜은 Objective-C에서의 역할이었던 청사진에서 구현까지 가능해진 것을 알고 있다
그러나 왜 이러한 protocol을 만들게 되었을까?

 

  1. 상속의 한계
    서로 다른 클래스에서 상속받은 클래스는 동일한 기능을 구현하기 위해 중복 코드 발생
    -> protocol default implimentaion으로 해결
    더보기
    protocol default implimentaion이란? 

    = 프로토콜을 따르겠다고 선언만 하면 어디서든 프로토콜 기능을 사용할 수 있다
    = class a : protocolA
  2. 카테고리의 한계
    프로퍼티 추가 불가, 클래스에서만 확장 가능, 기존 메소드 오버라이딩
    -> protocol default implimentaiondmfh 해결
  3. 참조타입 한계 
    동적 할당과 참조 카운팅에 많은 자원 소모로 Value Type으로 해결

 

개인적으로 뽑은 최대 장점은 class와 struct 모두 사용 가능하다는 점이다
POP를 적용한 예시를 보자

 

Model에 POP와 Value type 적용하기

효과 : class Content에 대한 참조 카운팅이 사라진다

// before
class Content {
    var URLString : string
    var note : String
}

// after
struct Content {
    var URLString : String
    var note : String
}

 

프로토콜 명시하기 

싱글톤 객체가 밸류 타입 프로퍼티를 가지고 이를 공유한다 

더보기

싱글톤이란? 

어떤 클래스가 최초 한번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 방법이다

class TimeLineTableViewController : UITableViewController, ContainContents { ... }
class TimeLineCollectionViewController : UICollectionViewController, 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에 POP와 ValueType 적용하기

효과 : 기능 블럭을 적용하여 재사용성이 높다

protocol MediaContainer : class {
    var content: Content? { get set }
    var media : UIImageView { get }
    var note : UILabel { get set }
    
    func contentChanged()
}

extension MediaContainer {
    func conetntChanged() {
    	// ...
    }
}

class TimeLineTableViewCell : UITableViewCell, MediaContainer { ... }
class TimeLineCollectionViewCell : UICollectionViewCell, MediaConatiner { ... }
class DetailViewController : UIViewController, MediaContainer { ... }

 

컨트롤러에 POP와 ValueType적용하기

다음 화면 보여주기를 뽑아 프로토콜로 만들기 
Scene coordinator로 볼 수 있는듯..?

protocol CanShowDetailView {
    func showDetailView(withContent content: Content)
    var navigationController : UINavigationController? { get }
}

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

class TimeLineTableViewcontroller : UITableViewController, ContainContents, CanShowDetailView { ... }
class TimeLineCollectionViewController : UITableViewController, ContainContents, CanShowDetailView { ... }

 

기타 POP와 Value타입으로 만들기 

셀의 imageView를 image와 video 모두 표현 가능하도록 변경
var media에 들어가는 타입을 UIImageView -> Protocol로 변경

protocol ContentPresentable : class, Layout {
    var frame: CGRect { get set }
    var canPresentContent: Bool { get }
}

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

extension UIImageView: ContentPresentable { }
extension MusicPlayerLayer : ContentPresentable { }

protocol MediaContainer : class {
    var content: Content? { get set }
    var media: ContentPresentable { get }
    var note: UILabel { get set }
    
    var videoLayer: MusicPlayerLaber { get }
    var mediaImageView: UIImageView { get }
    
    func contentChanged()
}

extension MediaContainer { 
    func contentChanged() {
        // ...
    }
    var media: ContentPresentable {
        switch content!.type {
            case .image:
                return mediaImageView
            case .video:
                return videoLayer
        }
    }
}

struct Content {
    enum MediaType {
        case image, video
    }
    var type: Content.MediaType
    var URLString: String
    var note: String
}

 

처음 POP가 적용된 프로젝트를 보았을 때 느낀 점은 한 눈에 기능을 알아보기 어렵다는 점이었다 
하나의 클래스 혹은 컨트롤러에 여러 프로토콜이 붙어있기에 프로토콜을 탐색하며 알아볼 시간이 필요했다 (네이밍의 문제도 있다고 본다)
하지만 그럼에도 POP를 쓰고 싶은 이유는 때문이다 
테스트 코드도 잘 쓰고 싶고.. 
여튼 자유자재로 POP를 쓰는 날까지 화이팅

반응형

'개발 > Swift' 카테고리의 다른 글

[Swift] NSAttributedString  (0) 2021.02.25
[Swift] 문자열 색인  (0) 2021.02.25
[Swift] Protocol 알아보기  (0) 2021.02.25
[Swift] Typealias  (0) 2020.03.12
[Swift] Protocol  (0) 2020.03.08