객체지향 프로그래밍(OOP)에서 좋은 설계를 위해 지켜야 하는 대표적인 5가지 원칙을 SOLID라고 부릅니다.
Swift로 예시를 들어 이해하기 쉽게 정리했습니다.
// 잘못된 예시: User가 여러 책임을 가짐
class User {
func login() { }
func saveLog() { }
func sendNotification() { }
}
// 올바른 예시: 역할 분리
class UserAuth {
func login() { }
}
class UserLogger {
func saveLog() { }
}
class UserNotifier {
func sendNotification() { }
}
protocol Shape {
func area() -> Double
}
class Circle: Shape {
let radius: Double
init(radius: Double) { self.radius = radius }
func area() -> Double { return Double.pi * radius * radius }
}
class Rectangle: Shape {
let width: Double
let height: Double
init(width: Double, height: Double) {
self.width = width
self.height = height
}
func area() -> Double { return width * height }
}
새로운 도형을 추가해도 기존 코드를 수정할 필요가 없다.
class Bird {
func fly() { print("I can fly") }
}
class Penguin: Bird {
// LSP 위반: 펭귄은 날 수 없음
override func fly() { fatalError("펭귄은 날 수 없습니다.") }
}
→ Penguin은 Bird로 대체 불가능하므로 잘못된 설계.
부모 클래스에 공통 기능만 넣고, 자식은 적절히 확장해야 한다.
// 잘못된 예시
protocol Worker {
func work()
func eat()
func sleep()
}
// 로봇은 eat, sleep 불필요 → 불필요한 의존 발생
class Robot: Worker {
func work() { print("Working") }
func eat() { } // 필요 없음
func sleep() { } // 필요 없음
}
// 올바른 예시: 인터페이스 분리
protocol Workable { func work() }
protocol Eatable { func eat() }
protocol Sleepable { func sleep() }
class Human: Workable, Eatable, Sleepable {
func work() { }
func eat() { }
func sleep() { }
}
class RobotV2: Workable {
func work() { }
}
protocol InputDevice {
func input() -> String
}
class Keyboard: InputDevice {
func input() -> String { return "키보드 입력" }
}
class Mouse: InputDevice {
func input() -> String { return "마우스 입력" }
}
class Computer {
private let device: InputDevice
init(device: InputDevice) {
self.device = device
}
func start() {
print("입력 장치: \(device.input())")
}
}
// 사용 예시
let computer = Computer(device: Keyboard())
computer.start()
Swift에서도 SOLID 원칙을 따르면 코드가 읽기 쉽고, 유지보수 및 확장이 용이한 구조를 만들 수 있다.