A/B 프로젝트의 홈 화면에 토픽 세부 액션과 댓글에 대한 바텀시트를 띄워주어야 한다. 이미 토픽 세부 액션 바텀시트를 띄워주는 기능은 구현한 상태였다.
collection view cell에서 액션을 받아 home view controller에게 전달해줘야 하므로, delegate 패턴을 사용했다.
이때 선언하고 채택해준 프로토콜은 TopicBottomSheetDelegate.
public protocol TopicBottomSheetDelegate: AnyObject {
func show()
}
새로운 기능인 댓글 바텀 시트 또한 collection view cell에서 액션을 받아 view controller에게 전달해줘야 한다. 이를 위해 ChatBottomSheetDelegate 프로토콜을 생성하고 마찬가지로 home view controller에게 전달해주도록 했다.
public protocol ChatBottomSheetDelegate: AnyObject {
func show()
}
문제의 발생은 이제부터다.
final class HomeViewController: BaseViewController, ChatBottomSheetDelegate, TopicBottomSheetDelegate {
}
ChatBottomSheetDelegate와 TopicBottomSheetDelegate 모두 show() 메서드를 가진다. collection view cell에서 책임을 넘겨줄 때, 어떤 프로토콜의 show() 메서드를 실행시킬지 선택이 불가능하고, 둘의 시그니처가 동일하다 보니 선언 자체도 한 번밖에 되지 않는다.
생각난 해결 방법은 2가지였다.
예시로 보자면 이런 느낌일 것이다.
public protocol ChatBottomSheetDelegate: AnyObject {
func showChatBottomSheet()
}
public protocol TopicBottomSheetDelegate: AnyObject {
func showTopicBottomSheet()
}
쉽게 문제를 해결할 수 있다는 장점을 있을 것이다.
하지만 다른 바텀시트 케이스가 무수히 생긴다고 가정했을 때, 이 방법이 좋은 방법일까? 나는 아니라고 생각한다.
프로토콜을 재사용할 수 없기 때문이다. (그리고 프로토콜 네이밍에서 댓글 바텀시트라는 것을 알려주는데, 메서드 네이밍에서도 댓글 바텀시트가 들어가는 것도 마음에 들지 않았다..^^)
public protocol BottomSheetDelegate: AnyObject {
func show(_ sender: DelegateSender)
}
2번 방식의 경우 프로토콜이 가지는 확장성이라는 특징을 살릴 수 있는 해결 방안이라고 생각했다.
2번 방식으로의 리팩토링 과정에 대해 조금 더 작성해보도록 하겠다.
내가 매개변수로 DelegateSender를 추가했을 때 기대한 부분은 바로 식별이 가능해지는 것이었다.
여러 바텀시트가 띄워질 수 있는 상황 속에서 책임을 전달받았을 때, 어떤 바텀시트를 최종적으로 띄울 것인지 정보를 제공하는 역할이다.
아래와 같이 identifier 프로퍼티를 추가하였다. (나중에 필요하다면 data 프로퍼티도 추가할 수 있지 않을까 싶다)
public protocol BottomSheetDelegate: AnyObject {
func show(_ sender: DelegateSender)
}
public struct DelegateSender {
public init(identifier: String) {
self.identifier = identifier
}
public let identifier: String
}
다음은 식별자를 어떻게 처리할 것인가.
리터럴 값을 다룰 때, 항상 중요하게 생각하는 것은 리터럴 값을 직접 선언해서 사용하려고 하지 말 것.
여러 파일에서 같은 식별자를 선언해줘야 할 때 직접 리터럴을 사용하면 귀찮아지고, 값을 변경하고자 할 때도 이 파일 저 파일 수정해야 해서 골치가 아파진다.
우선은 아래와 같이 namespace를 적절하게 활용하여 리터럴 값들을 선언해주었다.
public struct Literal {
public struct BottomSheet {
private static let base = "BottomSheet."
public static let topic = base + "topic"
public static let chat = base + "chat"
}
}
home view controller에서 show(:)라는 delegate method를 사용한 코드는 아래와 같다.
func show(_ sender: DelegateSender) {
switch sender.identifier {
case Literal.BottomSheet.topic:
coordinator?.startTopicBottomSheet()
case Literal.BottomSheet.chat:
coordinator?.startChatBottomSheet()
default:
return
}
}
토스트 메시지 싱글톤으로 관리하기 (1) | 2023.12.19 |
---|---|
enum을 configuration으로 사용할 때 발생하는 안티 패턴 제거해보기 (0) | 2023.12.14 |
Animation 활용해 TabBar 구현하기 (0) | 2023.04.27 |
JSON 파일 생성 및 파싱해 프로젝트에서 사용하기 (0) | 2023.04.27 |
Tag DesignSystem 리팩토링 과정 (0) | 2023.03.19 |