**OCP(Open-Closed Principle, 개방-폐쇄 원칙)**은 SOLID 원칙 중 하나로,
**“확장에는 열려 있고, 변경에는 닫혀 있어야 한다.”**라는 개념을 의미함.
즉, 새로운 기능을 추가할 때 기존 코드를 수정하지 않고 확장할 수 있어야 함.
이 원칙을 잘 지키면 코드의 유지보수성과 확장성이 증가하고, 버그 발생 가능성이 줄어듦.
📌 1. OCP 원칙이란?
✅ OCP(Open-Closed Principle)의 정의
“소프트웨어 요소(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하지만, 변경에는 닫혀 있어야 한다.”
• 확장(Open) → 새로운 기능 추가 가능해야 함.
• 변경(Closed) → 기존 코드 수정 없이 기능을 추가해야 함.
✅ 왜 OCP가 중요할까?
• 기존 코드를 수정하면 새로운 버그가 발생할 가능성이 있음 🚨
• 여러 사람이 함께 개발하는 경우, 변경이 많아지면 충돌 가능성이 커짐 ⚡
• 유지보수가 어렵고, 코드 수정이 많아질수록 테스트 비용 증가 🏗️
• OCP를 지키면 유지보수와 확장이 쉬운 코드를 작성할 수 있음 ✅
📌 2. OCP를 지키지 않은 코드 (문제점)
아래 코드를 보면 기능을 추가할 때 기존 코드 수정이 필요하므로 OCP를 위반함.
class PaymentProcessor {
public void processPayment(String paymentType) {
if (paymentType.equals("creditCard")) {
System.out.println("Processing credit card payment...");
} else if (paymentType.equals("paypal")) {
System.out.println("Processing PayPal payment...");
} else {
throw new IllegalArgumentException("Unsupported payment type");
}
}
}
❌ 문제점
• 새로운 결제 수단(bitcoin)을 추가하려면 processPayment() 메서드를 수정해야 함.
• OCP 원칙을 위반하여 코드 수정이 계속 발생 → 버그 발생 가능성 증가 🚨
• 클래스가 닫혀 있지 않음 → 유지보수가 어려움 😭
📌 3. OCP를 지키는 코드 (해결 방법)
OCP를 준수하려면 “새로운 기능을 추가할 때 기존 코드를 수정하지 않도록” 설계해야 함.
이를 위해 **인터페이스(Interface)나 추상 클래스(Abstract Class)**를 활용하면 됨.
// 1. 결제 수단 인터페이스 정의
interface Payment {
void pay();
}
// 2. 각 결제 수단을 별도 클래스로 분리
class CreditCardPayment implements Payment {
public void pay() {
System.out.println("Processing credit card payment...");
}
}
class PayPalPayment implements Payment {
public void pay() {
System.out.println("Processing PayPal payment...");
}
}
// 3. 확장 가능한 결제 처리 클래스
class PaymentProcessor {
public void processPayment(Payment payment) {
payment.pay();
}
}
// 4. 새로운 결제 수단 추가 (OCP 원칙 준수)
class BitcoinPayment implements Payment {
public void pay() {
System.out.println("Processing Bitcoin payment...");
}
}
// 5. 실행 코드
public class Main {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor();
processor.processPayment(new CreditCardPayment()); // 기존 코드 수정 없음
processor.processPayment(new PayPalPayment());
processor.processPayment(new BitcoinPayment()); // 새로운 결제 수단 추가 가능!
}
}
✅ OCP 원칙을 적용한 코드의 특징
1. **새로운 기능(결제 방식 추가)**이 필요하면 새로운 클래스를 만들면 됨 (기존 코드 수정 X)
2. OCP 원칙을 준수하여 코드 확장 가능성이 높아짐
3. 코드 수정 없이 새로운 기능을 추가 가능 → 유지보수성이 뛰어남
4. 인터페이스를 활용하여 유연한 설계 가능
📌 4. OCP 원칙을 적용하는 방법
✅ (1) 인터페이스와 추상 클래스 활용
• 기능 확장이 필요하면 새로운 클래스를 만들어 추가하는 방식
• 위의 Payment 예제처럼 인터페이스를 정의하고, 구현 클래스를 확장하면 됨.
✅ (2) 전략 패턴(Strategy Pattern) 적용
• 실행 중에 원하는 기능을 동적으로 변경할 수 있도록 설계하는 패턴
• OCP 원칙을 준수하면서 유연하게 기능 추가 가능
class PaymentProcessor {
private Payment payment;
public PaymentProcessor(Payment payment) {
this.payment = payment;
}
public void process() {
payment.pay();
}
}
public class Main {
public static void main(String[] args) {
PaymentProcessor processor = new PaymentProcessor(new CreditCardPayment());
processor.process(); // 신용카드 결제
processor = new PaymentProcessor(new BitcoinPayment());
processor.process(); // 비트코인 결제
}
}
✅ (3) 의존성 주입(DI, Dependency Injection)
• Spring 프레임워크에서 OCP 원칙을 실천하는 대표적인 방법
• 인터페이스를 주입하여 변경 없이 새로운 기능 추가 가능
@Service
class PaymentService {
private final Payment payment;
@Autowired
public PaymentService(Payment payment) {
this.payment = payment;
}
public void processPayment() {
payment.pay();
}
}
• 새로운 결제 수단이 추가되더라도 기존 PaymentService 코드를 수정할 필요 없음
📌 5. OCP 원칙을 따르지 않으면 생기는 문제점
OCP를 준수하지 않으면? | 발생 문제 |
기능 추가 시 기존 코드 수정이 필요함 | 기존 코드 수정 중 버그 발생 가능 🚨 |
클래스가 너무 커지고 복잡해짐 | 코드 유지보수 어려움 😭 |
새로운 기능 추가 시 테스트 필요 | 코드 수정 없이 기능 추가 가능해야 함 |
🚀 결론
• OCP 원칙을 따르면 기존 코드를 수정하지 않고도 새로운 기능을 쉽게 추가 가능함.
• 인터페이스, 추상 클래스, 전략 패턴, DI(의존성 주입) 등을 활용하면 OCP를 쉽게 적용할 수 있음.
• 유지보수성과 확장성이 뛰어난 코드 작성 가능 → 버그 발생 가능성 줄이고 개발 속도 증가 🚀
출처 : ChatGPT
'CS' 카테고리의 다른 글
SSE (Server-Sent Events) (0) | 2025.02.19 |
---|---|
락(Lock)과 동시성 (0) | 2025.02.18 |
다형성 (1) | 2025.02.16 |
DFS, BFS (0) | 2025.02.14 |
git branch 별 차이 (dev, origin dev, origin/dev) (0) | 2025.02.11 |