💡 객체 지향 설계란?
- 유지 보수, 확장, 재사용이 쉬운 소프트웨어를 만들기 위한 설계 철학
- 그중에서도 SOLID 원칙은 객체 지향 설계의 5가지 핵심 원칙을 제시
- 깨지기 쉬운 코드를 유연한 구조로 바꿈
🧱 SOLID 원칙이란?
1️⃣ SRP(Single Responsibility Principle) - 단일 책임 원칙
📌 하나의 클래스는 오직 하나의 책임만 가져야 함
🗒️ 예시 코드
// ❌ 단일 책임 위반
public class User {
public void login() { /* 로그인 */ }
public void saveUser() { /* DB 저장 */ }
}
// ✅ 단일 책임 분리
public class User { /* 사용자 정보 */ }
public class AuthService { public void login(User user) { ... } }
public class UserRepository { public void saveUser(User user) { ... } }
2️⃣ OCP(Open-Closed Principle) - 개방-폐쇄 원칙
📌 확장에는 열려 있고, 수정에는 닫혀 있어야 함
🗒️ 예시 코드
// ❌ 도형이 추가되면 기존 코드 수정 필요
public class AreaCalculator {
public double calculate(Shape shape) {
if (shape.type.equals("circle")) { ... }
}
}
// ✅ 다형성 + 인터페이스 활용
public interface Shape { double calculateArea(); }
public class Circle implements Shape { ... }
public class AreaCalculator {
public double calculate(Shape shape) {
return shape.calculateArea(); // 수정 없이 확장 가능
}
}
💬 왜 중요할까?
3️⃣ LSP(Liskov Substitution Principle) - 리스코프 치환 원칙
📌 부모 타입을 사용하는 곳에 자식 타입을 넣어도 문제가 없어야 함
❌ LSP 위반
class Car { void accelerate() { 휘발유로 가속 } }
class ElectricCar extends Car {
@Override
void accelerate() { throw new Exception(); } // 문제 발생
}
✅ LSP 준수
interface Acceleratable { void accelerate(); }
class Car implements Acceleratable { ... }
class ElectricCar implements Acceleratable { ... }
💬 핵심은?
기능을 바꾸고 싶다면 역할(인터페이스)을 분리해서 다형성 구조를 유지해야 함
4️⃣ ISP(Interface Segregation Principle) - 인터페이스 분리 원칙
📌 큰 인터페이스 하나보다는, 클라이언트에 맞는 여러 개의 인터페이스가 나음
❌ ISP 위반
public interface Animal {
void fly(); void run(); void swim();
}
public class Dog implements Animal {
public void fly() { } // 필요 없음
}
✅ ISP 준수
interface Runnable { void run(); }
interface Swimmable { void swim(); }
class Dog implements Runnable, Swimmable { ... }
💬 결과적으로?
인터페이스가 작고 명확할수록 유지 보수 수월 및 의존성 감소
5️⃣ DIP(Dependency Inversion Principle) - 의존관계 역전 원칙
📌 상위 모듈(비즈니스 로직)은 하위 모듈(구현)에 의존하지 않고, 추상화에 의존해야 함
❌ DIP 위반
class NotificationService {
private EmailNotifier emailNotifier = new EmailNotifier(); // 강한 결합
}
✅ DIP 준수
interface Notifier { void send(String message); }
class EmailNotifier implements Notifier { ... }
class SMSNotifier implements Notifier { ... }
class NotificationService {
private final Notifier notifier;
public NotificationService(Notifier notifier) {
this.notifier = notifier;
}
}
💬 왜 DI가 필요한가?
NotificationService는 코드 수정 없이 그대로 사용 가능🌱 Spring과 객체 지향
- Spring은 다형성만으로는 해결하지 못했던
객체 지향 설계 원칙 중 OCP, DIP를 IOC, DI를 통해 가능하도록 만들어 줌
💼 Spring의 역할
Spring Container가 생성해서 주입해 줌🧩 개발자가 해야 할 일