티스토리 뷰
Swift로 배우는 전략 패턴 (Strategy Pattern) – Head First 디자인 패턴 기반 설명
『Head First Design Patterns』는 디자인 패턴을 쉽고 직관적으로 설명하는 명저입니다.
이번 글에서는 그중에서도 전략 패턴(Strategy Pattern)을 iOS 개발 환경에 맞게 Swift로 구현해보며 학습해보겠습니다.
🧠 전략 패턴이란?
전략 패턴(Strategy Pattern)은 알고리즘(또는 행위)을 객체로 캡슐화하여 상호 교환 가능하게 만드는 디자인 패턴입니다.
핵심 개념:
"행동을 클래스로 분리해서, 실행 중에 바꿀 수 있게 만든다."
✅ 전략 패턴 요약 정리
| 항목 | 내용 |
| ------ | ------ |
| 패턴명 | 전략(Strategy) 패턴 |
| 목적 | 알고리즘을 런타임에 자유롭게 교체 가능하게 만들기 |
| 특징 | 1개의 인터페이스 + 여러 전략 구현체 + Context 객체 |
| 장점 | OCP 만족, 중복 제거, 행동 교체 가능 |
| 자주 쓰이는 경우 | 로그인 방식, 정렬 기준, 렌더링 전략 등 |
📖 책 속 예시: 오리 시뮬레이터
Head First 디자인 패턴에서 소개된 전략 패턴의 대표 예시는 오리 시뮬레이터입니다.
Duck
객체는fly()
와quack()
같은 행동을 가짐- 행동은 상황에 따라 달라지므로, 서브클래싱보다 구성(Composition)을 통해 캡슐화
FlyBehavior
,QuackBehavior
라는 인터페이스로 행동을 외부에서 주입
🧪 iOS에서의 실제 예: 로그인 전략
iOS 앱에서 다음과 같은 로그인 기능을 제공한다고 가정해봅시다:
- Apple ID 로그인
- Google 계정 로그인
- 게스트 로그인
이 3가지 로그인 방식은 서로 방식이 다르지만, "로그인"이라는 기능은 같기 때문에 전략 패턴이 유용합니다.
1. LoginStrategy
프로토콜 정의
protocol LoginStrategy {
func login(completion: @escaping (Bool) -> Void)
}
2. 전략 클래스 구현
struct AppleLoginStrategy: LoginStrategy {
func login(completion: @escaping (Bool) -> Void) {
print("🍎 Apple ID로 로그인 시도")
// Apple 로그인 로직
completion(true)
}
}
struct GoogleLoginStrategy: LoginStrategy {
func login(completion: @escaping (Bool) -> Void) {
print("🔍 Google 계정으로 로그인 시도")
// Google 로그인 로직
completion(true)
}
}
struct GuestLoginStrategy: LoginStrategy {
func login(completion: @escaping (Bool) -> Void) {
print("👤 게스트 로그인")
completion(true)
}
}
3. Context 객체: LoginManager
final class LoginManager {
private var strategy: LoginStrategy
init(strategy: LoginStrategy) {
self.strategy = strategy
}
func setStrategy(_ strategy: LoginStrategy) {
self.strategy = strategy
}
func login(completion: @escaping (Bool) -> Void) {
strategy.login(completion: completion)
}
}
4. ViewController에서 사용
class LoginViewController: UIViewController {
let loginManager = LoginManager(strategy: GuestLoginStrategy())
@IBAction func appleLoginTapped() {
loginManager.setStrategy(AppleLoginStrategy())
loginManager.login { success in
print("로그인 성공 여부: \(success)")
}
}
@IBAction func googleLoginTapped() {
loginManager.setStrategy(GoogleLoginStrategy())
loginManager.login { success in
print("로그인 성공 여부: \(success)")
}
}
@IBAction func guestLoginTapped() {
loginManager.setStrategy(GuestLoginStrategy())
loginManager.login { success in
print("로그인 성공 여부: \(success)")
}
}
}
🧩 iOS에서 자주 쓰이는 전략 패턴 예시
| 상황 | 전략이 필요한 이유 |
| ------ | ------------------- |
| 이미지 필터 처리 | 다양한 필터 적용 방식(흑백, 세피아 등)을 런타임에 변경 가능 |
| 정렬 기준 선택 | 리스트 정렬 기준을 이름순 / 날짜순 등으로 교체 |
| 광고 A/B 전략 | 유저 그룹별 광고 표시 전략 분리 |
| 데이터 저장 방식 | UserDefaults, Keychain, File 방식 전략적으로 교체 |
💡 고급 팁: 클로저로도 전략을 표현할 수 있다
Swift에서는 꼭 클래스로만 전략을 구현하지 않아도 됩니다.
간단한 전략은 클로저로 대체할 수 있습니다.
typealias LoginClosure = (@escaping (Bool) -> Void) -> Void
let appleLogin: LoginClosure = { completion in
print("🍎 Apple로 로그인")
completion(true)
}
let guestLogin: LoginClosure = { completion in
print("👤 게스트로 로그인")
completion(true)
}
이런 방식은 간단한 상황에서는 더욱 가볍게 전략을 구성할 수 있어 유용합니다.
🎯 결론
전략 패턴은 다음과 같은 경우에 아주 효과적입니다:
- 동작을 바꿔야 하지만, 코드를 수정하고 싶지 않을 때
- 여러 조건에 따라 다른 처리를 해야 할 때
- 테스트 가능성과 코드 확장성을 확보하고 싶을 때
Swift와 iOS 프로젝트에서 전략 패턴을 적극적으로 활용해보세요!
한층 더 유연하고 유지보수하기 쉬운 앱을 만들 수 있습니다.
📚 참고
『Head First Design Patterns』, O’Reilly Media
Swift 공식 문서, Apple Developer Guide
- Total
- Today
- Yesterday
- 병든 나이트#BOJ#탐욕법#Python
- Distinct#Codility#Python
- django
- 파이썬알고리즘인터뷰#4장
- 쿼드트리#BOJ#분할정복#Python
- 종이자르기#분할정복#BOJ#Python
- 배열합치기#분할정복#BOJ#Python
- 토마토#백준알고리즘#Python
- Swift#Tuples#Range
- 텀 프로젝트#백준알고리즘#Python
- N으로 표현#DP#Programmers#Python
- filter#isalnum#lower
- 미로 탐색#백준알고리즘#Python
- 섬의개수#백준알고리즘#Python
- 리모컨#완전탐색#BOJ#Python
- 터틀비치#리콘#xbox#controller
- django#slicing
- 날짜 계산#BOJ#완전탐색#Python
- 공유기 설치#BOJ#이분탐색#Python
- Triangle#Sorting#Codility#Python
- 순열사이클#BOJ#Python
- 반복수열#백준알고리즘#Python
- NumberofDiscIntersections#Codility#Sort#Python
- Brackets#Stacks and Queues#Codility#Python
- PassingCars#Codility#Python
- 랜선자르기#이분탐색#BOJ#Python
- 나무자르기#BOJ#이분탐색#Python
- API#lazy#
- 백준 알고리즘#BackTracking
- 암호코드#dp#BOJ#Python
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |