Skip to content

Commit 85f2ab1

Browse files
authored
docs: Protocol과 Delegate (#72) (#74)
1 parent c326a74 commit 85f2ab1

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
## 1. **프로토콜 (Protocol)**
2+
| `프로토콜`**클래스, 구조체, 열거형이 따라야 하는 "규칙"**을 정의하는 타입
3+
어떤 타입이 특정 프로토콜을 채택하면 그 프로토콜이 정의한 메서드나 프로퍼티를 반드시 구현해야 함
4+
```swift
5+
protocol Drivable {
6+
func startEngine()
7+
func drive()
8+
}
9+
```
10+
이 프로토콜을 채택하면 아래처럼 메서드를 구현해야 함!
11+
```swift
12+
struct Car: Drivable {
13+
func startEngine() {
14+
print("Engine started")
15+
}
16+
17+
func drive() {
18+
print("Car is driving")
19+
}
20+
}
21+
```
22+
23+
### 왜 필요할까?
24+
- **일관된 인터페이스 보장**: 여러 타입이 동일한 동작을 할 수 있도록 강제함
25+
- **의존성 역전 (DIP)**: 구체적인 타입이 아닌 "기능"에 의존하게 함
26+
- **다형성**: 다양한 객체를 같은 방식으로 처리할 수 있음
27+
28+
## 2. **델리게이트 패턴 (Delegate Pattern)**
29+
> 델리게이트(Delegate) 패턴은 **어떤 객체가 해야 할 일을 다른 객체에게 위임(delegate)** 하는 디자인 패턴
30+
보통 프로토콜을 기반으로 구성되며, 어떤 객체가 프로토콜을 통해 "일을 대신할 대상"을 등록하고, 그 대상이 프로토콜을 채택해 필요한 기능을 구현함
31+
32+
왜 필요할까?
33+
- **역방향 데이터 전달**: 자식 → 부모 뷰로 이벤트 전달
34+
- **책임 분리**: 하나의 객체에 너무 많은 역할을 몰아주지 않음
35+
- **유연성**: 동작을 외부에서 커스터마이즈 가능
36+
37+
### 델리게이트 패턴 구성 요약
38+
39+
|프로토콜 정의|`MyViewDelegate`|어떤 메서드를 구현해야 할지 명시|
40+
|---|---|---|
41+
|델리게이트 변수|`weak var delegate: MyViewDelegate?`|대리자(역할 수행자) 연결|
42+
|호출|`delegate?.somethingDidHappen()`|대리자에게 이벤트 전달|
43+
|프로토콜 채택 및 구현|보통 ViewController|이벤트에 반응하는 코드 작성|
44+
45+
### 예시) 버튼이 눌렸을 때 ViewController에게 알리는 커스텀 뷰
46+
```swift
47+
// 1. 프로토콜 정의
48+
protocol CustomButtonDelegate: AnyObject {
49+
func buttonWasTapped()
50+
}
51+
52+
// 2. 커스텀 뷰 정의
53+
class CustomButtonView: UIView {
54+
weak var delegate: CustomButtonDelegate?
55+
56+
func buttonTapped() {
57+
// 3. 델리게이트에게 알림
58+
delegate?.buttonWasTapped()
59+
}
60+
}
61+
```
62+
```swift
63+
// 4. ViewController에서 델리게이트 채택
64+
class ViewController: UIViewController, CustomButtonDelegate {
65+
func buttonWasTapped() {
66+
print("Button was tapped in the custom view!")
67+
}
68+
69+
func setup() {
70+
let customView = CustomButtonView()
71+
customView.delegate = self
72+
}
73+
}
74+
```
75+
76+
## ** 정리
77+
||프로토콜|델리게이트 패턴|
78+
|---|---|---|
79+
|개념|기능의 "약속"|"위임"을 통해 일을 분리함|
80+
|목적|인터페이스 통일|이벤트 전달 & 역할 분산|
81+
|연관성|프로토콜 기반으로 동작|항상 프로토콜과 함께 사용|
82+
|주요 용도|기능 설계|자식 → 부모 이벤트 전달 등|
83+
84+
85+
## Q) 언제 쓰면 좋을까?
86+
- View ↔ ViewController 간 통신 (ex. 버튼 누름, 스크롤 이벤트 등)
87+
- TableView, CollectionView처럼 iOS 시스템이 제공하는 델리게이트 패턴 활용 시
88+
- 복잡한 동작을 모듈로 분리하고 싶을 때
89+
90+
# !! 근데 SwiftUI에서는 delegate가 사라짐 !!
91+
> SwiftUI의 설계 철학과 아키텍처가 기존 UIKit과 크게 다름 UIKit은 **객체지향(OOP)** 기반으로 동작함
92+
```swift
93+
class MyViewController: UIViewController, UITableViewDelegate {
94+
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
95+
// 셀 선택됨
96+
}
97+
}
98+
```
99+
100+
- delegate = UIKit 컴포넌트의 이벤트를 외부 객체로 전달하기 위한 방법!!
101+
- UIKit은 명령형(imperative) UI 모델로 구성돼 있어서, 이벤트가 발생할 때마다 개발자가 수동으로 상태를 업데이트해줘야함
102+
103+
→ 다양한 이벤트 처리를 위해 delegate 패턴이 필수…였는데요
104+
## SwiftUI에서는 왜 delegate가 사라졌을까?
105+
> SwiftUI는 UIKit과 달리 선언형(declarative) UI 모델을 사용한다
106+
```swift
107+
List(items) { item in
108+
Text(item.name)
109+
.onTapGesture {
110+
// 이 아이템이 탭됐을 때 처리
111+
}
112+
}
113+
```
114+
SwiftUI는 **뷰의 상태(state)**와 UI를 선언적으로 연결해 놓음
115+
116+
### 1. **상태 기반 데이터 흐름 (State-Driven UI)**
117+
SwiftUI는 `@State`, `@Binding`, `@ObservedObject`, `@Environment` 등 다양한 상태 속성 래퍼를 사용해서 데이터의 변경이 곧 UI의 변경으로 직결되는 구조
118+
```swift
119+
@State private var isOn = false
120+
121+
Toggle("Switch", isOn: $isOn)
122+
```
123+
- `delegate` 없이도 `@State`가 바뀌면 UI가 자동으로 다시 렌더링됨
124+
- 반응형 프로그래밍 → 별도로 이벤트 처리 객체(delegate)를 둘 필요가 없음!
125+
126+
### 2. **View는 구조체 Struct → 소유관계가 사라짐**
127+
UIKit은 클래스 기반이기 때문에 `delegate`처럼 다른 객체를 참조해서 처리해야 했고,
128+
SwiftUI의 뷰는 대부분 `struct`라서 참조보다 데이터 전달과 바인딩에 집중함
129+
```swift
130+
struct CustomView: View {
131+
var onComplete: () -> Void // delegate 대신 클로저를 받음
132+
}
133+
```
134+
- delegate 프로퍼티를 가질 수 없음 (구조체는 참조를 보관하지 않음)
135+
- 대신 클로저로 필요한 로직을 주입 (event handler로 대체)
136+
137+
### 3. **단방향 데이터 흐름**
138+
SwiftUI는 모든 데이터가 위에서 아래로 흐르도록 설계되어 있음
139+
```swift
140+
ParentView
141+
└── ChildView(data: ..., onTap: { ... })
142+
143+
```
144+
- 뷰는 데이터를 직접 수정하지 않고, 상위 뷰의 바인딩이나 클로저를 통해 동작만 위임
145+
- delegate 같은 양방향 흐름은 SwiftUI에서 지양함
146+
147+
## Q) 그럼 delegate는 완전히 사라졌을까?
148+
아니요!!!!!!! UIKit을 사용할 때는 여전히 필요함!!!
149+
`UIViewRepresentable` 같은 SwiftUI <-> UIKit 브리징 컴포넌트에서는 여전히 delegate를 사용함
150+
151+
ex)
152+
```swift
153+
class Coordinator: NSObject, UITextFieldDelegate {
154+
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
155+
...
156+
}
157+
}
158+
```
159+
160+
## ** 결론
161+
> SwiftUI는 상태 중심 + 선언형 UI + 함수형
162+
> UIKit에서 쓰던 delegate 패턴은 필요 없어졌고, 대신 클로저, 바인딩, ObservableObject 같은 기능이 대신하고 있음

0 commit comments

Comments
 (0)