들어가기에 앞서
Delegate 패턴은 Swift 언어와 iOS 앱 개발에서 매우 중요한 디자인 패턴 중 하나이다. 이 패턴은 객체 사이의 효율적인 통신과 역할 분담을 위해 사용되며 객체 간의 결합도를 낮추고 코드의 재사용성과 유지보수성을 높이는데 매우 효과적이다. 이번 포스팅에서 Swift에서 Delegate 패턴의 개념과 구현 방법, 그리고 실제 예시를 다루어보겠다.
delegate : 대리자
delegate의 사전적 의미는 '대리자' 라는 뜻이다. 하나의 객체가 다른 객체의 대리자 역할을 수행하여 특정 이벤트가 발생했을 때 해당 이벤트를 처리하는 디자인 패턴이다. 객체는 자신이 처리하기 어려운 기능이나 작업을 대리자에게 위임함으로써 자신의 역할을 단순화하고 중요한 책임에만 집중할 수 있다. 이로써 객체들 간의 결합도가 낮아지고 유연한 코드를 작성할 수 있다.
Delegate 패턴에서는 특정 이벤트를 처리하기 위한 메서드들을 프로토콜로 정의한다.
protocol TVRemoteDelegate: AnyObject {
func didChangeChannel(to channel: Int)
func didAdjustVolume(to volume: Int)
}
위 코드에서 TVRemoteDelegate 프로토콜은 TVRemote 클래스에서 발생하는 이벤트를 처리하기 위해 정의된다. TVRemote 클래스는 TVRemoteDelegate 프로토콜을 사용하여 이벤트를 TV 클래스에게 알린다.
객체가 대리자 역할을 수행할 수 있도록 대리자 객체를 저장할 프로퍼티를 선언한다.
class TVRemote {
weak var delegate: TVRemoteDelegate?
func pressButtonA() {
delegate?.didChangeChannel(to: 5)
}
func pressButtonB() {
delegate?.didAdjustVolume(to: 15)
}
}
TVRemote 클래스는 TVRemoteDelegate를 프로퍼티로 가지고 있으며, 버튼을 누를 때마다 해당 이벤트를 TV 클래스에게 알리도록 구현된다.
객체에서 특정 이벤트가 발생했을 때, 대리자에게 알리는 메서드를 호출한다.
class TV: TVRemoteDelegate {
var channel: Int = 1
var volume: Int = 10
let remoteControl: TVRemote
init() {
remoteControl = TVRemote()
remoteControl.delegate = self
}
func didChangeChannel(to channel: Int) {
self.channel = channel
print("TV: 채널 \(channel)로 변경되었습니다.")
}
func didAdjustVolume(to volume: Int) {
self.volume = volume
print("TV: 볼륨 조절 - 현재 볼륨: \(volume)")
}
}
TV 클래스는 TVRemoteDelegate 프로토콜의 메서드를 구현하여 TV 리모컨에서 발생하는 채널 변경과 볼륨 조절 이벤트를 처리한다. TV 클래스는 TVRemote 객체를 생성하고 TVRemote 객체의 delegate를 TV 클래스 자신으로 설정하여 이벤트를 받을 수 있도록 한다.
대리자 객체는 프로토콜에 정의된 메서드들을 구현하여 실제 이벤트 처리를 수행한다.
let myTV = TV()
myTV.remoteControl.pressButtonA() // "TV: 채널 5로 변경되었습니다." 출력
myTV.remoteControl.pressButtonB() // "TV: 볼륨 조절 - 현재 볼륨: 15" 출력
main.swift에서는 TV 클래스의 인스턴스를 생성하고, TV 리모컨에서 버튼을 누르면 TV 클래스가 해당 이벤트를 처리한다.
마무리하며
개발을 하며 많이 사용하게 될 Delegate 패턴이다. 이해가 쉽지 않겠지만 직접 구현해보며 체득하길 바란다.
언제나 기초는 튼튼히! 사고는 유연하게