[iOS] Delegate Pattern
Delegate 는 위임하다, 대리자 등의 뜻을 가진 단어입니다.
말 그대로 Delegate Pattern 은 대리자를 가지고 있는 객체가 대리자 객체에게 자신의 일을 위임하는 형태의 디자인 패턴입니다.
이는 하나의 객체가 모든 일을 처리하는 것이 아니라 다른 객체가 이를 일부분만 확장하여 처리하도록 위임하는 방식입니다.
말만 들어서는 잘 이해가 되지 않을수도 있으니 예시를 들어 설명해보겠습니다.
예시
영화를 만드는 Producer 라는 객체가 있다고 가정하겠습니다.
영화를 만들려면 누군가가 연기를 해야하는데, 대부분 감독들이 직접 연기를 하는 경우는 없죠. 그러니 다른 누군가에게 자신이 생각한 연기를 하도록 시킵니다.
이렇게 대신 연기를 하는 객체를 Actor 라고 하겠습니다.
Actor 객체는 연기를 하기 위해 act()
라는 메소드를 가지고 있습니다. 이를 통해 Producer 객체는 delegate
라는 프로퍼티에 Actor 객체를 할당시켜 act()
메소드를 호출할 수 있습니다.
이렇게 Producer 는 영화를 만들 수 있게 되었습니다.
위 코드에서 나온 방법을 추상화시켜보도록 하겠습니다.
저희는 act()
메소드를 가지고 있는 ProducerDelegate 프로토콜을 선언했습니다. 이는 Producer 의 대리자라면 연기를 할 수 있어야 한다는 뜻입니다.
Actor 객체는 해당 프로토콜을 채택하여 act()
메소드를 구현할 수 있고, Producer 객체의 delegate
프로퍼티는 ProducerDelegate 타입을 가지고 있어서 act()
메소드를 호출할 수 있게 됩니다.
다만 위의 코드와 다른점을 꼽자면, Producer 의 delegate 는 ProducerDelegate 를 준수하고 있는 Actor 객체이다 라고 지정해줘야 한다는 점이 있습니다.
이는 코드상에서 20번째 라인인 producer.delegate = Actor()
에서 확인할 수 있습니다.
이렇게 되면 ProducerDelegate 를 준수하는 여러 객체를 만들 수 있게 되고, 해당 객체들은 Producer 의 delegate, 즉 대리자 역할을 수행할 수 있게 됩니다.
실제로 모든 배우는 연기를 하지만, 연기 스타일이 각 배우마다 모두 다르듯이 ProducerDelegate 프로토콜을 준수하는 각 객체는 act()
메소드를 구현해야 하지만 그 방식은 다양해질 수 있습니다.
TableView & CollectionView
Delegate Pattern 의 가장 대표적인 예시는 UITableView 와 UICollectionView 입니다. 해당 포스트에서는 UITableView 를 예로 들어 설명해보겠습니다.
저희는 UITableView 를 이용할 때 ViewController 에게 UITableViewDataSource 라는 프로토콜을 준수하도록 하고, tableView.dataSource = self
라는 라인을 작성합니다.
이는 TableView 를 구현하기 위한 대리자의 역할을 ViewController 자신이 하겠다는 의미입니다.
TableView 는 리스트 형태로 데이터를 나타내고, 여러 셀을 가지고 있다는 특징이 있지만 TableView 마다 데이터의 개수나 셀에 담기는 정보 등이 다르게 구현될 수 있습니다.
이는 위에서 설명한 배우 예시와 비슷합니다.
위의 코드에서 Producer 와 Actor 를 UITableView 와 ViewController 로 대체해보겠습니다.
조금씩 감이 오시나요?
실제 UITableViewDelegate 프로토콜에 선언된 메소드와는 다르지만, 위와 같은 형식이라고 볼 수 있습니다.
ViewController 는 TableView 를 그리는 대리자라고 생각하시면 됩니다.
실제로 UITableView 와 UITableViewDataSource 를 이용하는 예시를 보여드리겠습니다.
위와 같이 TableView 의 DataSource 를 담당하는 것은 ViewController 이기 때문에 tableView.dataSource = self
라는 코드를 작성했습니다.
아래에는 ViewController 를 확장하여 UITableViewDataSource 프로토콜을 채택했고, 내부에는 필수 구현 메소드들을 작성해줬습니다.
작성된 메소드들은 각각 TableView 의 각 Section 에 나타낼 행의 개수와 TableView 에 나타낼 Cell 을 구현합니다.
이는 TableView 마다, 혹은 표현하고자 하는 데이터마다 다르게 구현될 것입니다.
Delegate Pattern 을 사용하는 이유
Delegate Pattern 을 이용하면 위임하는 객체들은 대리자에게 해당 기능을 구현하도록 시킬 뿐 그 작업을 어떻게 처리해야 하는지는 알려주지 않습니다.
어떠한 기능을 구현해야 한다고 했을때, 큰 틀과 목적만 알려줄 뿐 항상 같은 결과를 나타내지는 않는다는 것입니다.
그래서 각 대리자 객체는 구현하도록 전달받은 기능을 상황에 맞게 구현하면 됩니다.
그렇기 때문에 공통된 기능이라도 한 부분에서 에러가 발생했을 때 다른 부분까지 영향을 끼치지 못합니다.
또한 코드의 확장성이 높아지고 유지보수가 쉬워진다는 장점을 가지고 있습니다.
마무리
오늘은 Delegate 패턴에 대해 알아봤습니다.
Delegate Pattern 은 특히나 처음 학습할 때 이해하기 정말 어려운 개념인 것 같습니다.
저도 3~4 번은 반복해서 학습하여 겨우 조금 이해한것 같습니다.
위의 예시를 천천히 살펴보며 이해하고, 해당 방식이 어떻게 동작하는 것인지 차근차근 생각해 보신다면 금방 이해하실 수 있을겁니다.
'iOS 개발 > iOS' 카테고리의 다른 글
[iOS] 이미지 캐시 모듈 구현하기 (feat. Kingfisher) (0) | 2022.12.28 |
---|---|
[iOS] 메모리 구조 (0) | 2022.07.12 |
[iOS] UINavigationController (0) | 2022.06.30 |
[iOS] 앱 생명주기 (App LifeCycle) (0) | 2022.06.24 |
[iOS] Frame & Bounds (0) | 2022.06.17 |