카테고리 없음

2024 동계 모각코 6회차 활동 기록

발빠진 쥐 2025. 2. 11. 17:00

"SOLID 원칙 – 객체지향 설계의 핵심 가이드"

"코드가 작을 때는 괜찮지만, 프로젝트가 커지면 무너지는 이유는 무엇일까?"
이 블로그에서는 객체지향 설계의 5대 원칙인 SOLID 원칙을 깊이 다룹니다.
유지보수성, 확장성, 재사용성을 높이기 위해 필수적인 원칙과 실제 적용 방법을 예시와 함께 설명합니다.


📌 SOLID 원칙이란 무엇인가?

SOLID 원칙5가지 객체지향 설계 원칙의 앞글자를 따서 만든 약어입니다.
이 원칙들은 소프트웨어를 더 유연하고 확장 가능하며 유지보수하기 쉽게 만듭니다.


🛠️ SOLID 원칙의 구성 요소

1️⃣ S (SRP) – 단일 책임 원칙 (Single Responsibility Principle)
2️⃣ O (OCP) – 개방-폐쇄 원칙 (Open/Closed Principle)
3️⃣ L (LSP) – 리스코프 치환 원칙 (Liskov Substitution Principle)
4️⃣ I (ISP) – 인터페이스 분리 원칙 (Interface Segregation Principle)
5️⃣ D (DIP) – 의존 역전 원칙 (Dependency Inversion Principle)


📌 1. S – 단일 책임 원칙 (SRP)

"하나의 클래스는 하나의 책임만 가져야 한다."

**단일 책임 원칙(SRP)**은 클래스가 오직 하나의 책임만 수행해야 하며, 하나의 이유로만 변경되어야 한다는 원칙입니다.
책임을 여러 개 가지는 클래스는 변경이 많아지고 유지보수하기 어려워집니다.


🛠️ SRP 위반 코드 예시

java
복사편집
public class ReportManager { public void generateReport() { // 보고서 생성 로직 } public void sendReportByEmail() { // 이메일 전송 로직 } public void saveReportToDatabase() { // 데이터베이스 저장 로직 } }

문제점:

  • ReportManager 클래스가 보고서 생성, 이메일 전송, 데이터베이스 저장이라는 여러 책임을 가집니다.
  • 만약 이메일 전송 방식이 바뀐다면 모든 코드를 수정해야 할 수 있습니다.

SRP 준수 코드

java
복사편집
public class ReportGenerator { public void generateReport() { // 보고서 생성 로직 } } public class EmailSender { public void sendReportByEmail() { // 이메일 전송 로직 } } public class DatabaseSaver { public void saveReportToDatabase() { // 데이터베이스 저장 로직 } }

개선점:

  • 각 클래스가 하나의 책임만 수행하므로 변경에 따른 영향이 최소화됩니다.
  • 유지보수와 테스트가 훨씬 쉬워집니다.

📌 2. O – 개방-폐쇄 원칙 (OCP)

"확장에는 열려 있고, 수정에는 닫혀 있어야 한다."

**OCP(Open/Closed Principle)**는 기존 코드를 수정하지 않고도 기능을 확장할 수 있어야 한다는 원칙입니다.
이 원칙을 지키면 기존 코드의 안정성을 유지하면서도 새로운 기능을 추가하기 쉬워집니다.


🛠️ OCP 위반 코드 예시

java
복사편집
public class PaymentProcessor { public void processPayment(String paymentType) { if (paymentType.equals("CreditCard")) { // 신용카드 결제 처리 } else if (paymentType.equals("PayPal")) { // PayPal 결제 처리 } } }

문제점:

  • 새로운 결제 수단이 추가될 때마다 processPayment 메서드를 수정해야 합니다.
  • OCP를 위반했기 때문에 수정할수록 코드가 복잡해집니다.

OCP 준수 코드 (다형성 활용)

java
복사편집
public interface PaymentMethod { void processPayment(); } public class CreditCardPayment implements PaymentMethod { public void processPayment() { // 신용카드 결제 처리 } } public class PayPalPayment implements PaymentMethod { public void processPayment() { // PayPal 결제 처리 } } public class PaymentProcessor { public void processPayment(PaymentMethod paymentMethod) { paymentMethod.processPayment(); } }

개선점:

  • 새로운 결제 수단을 추가할 때 기존 코드는 수정할 필요가 없습니다.
  • OCP를 준수하며, 확장성이 훨씬 좋아집니다.

📌 3. L – 리스코프 치환 원칙 (LSP)

"하위 클래스는 언제나 상위 클래스를 대체할 수 있어야 한다."

**LSP(Liskov Substitution Principle)**는 하위 클래스가 상위 클래스의 기능을 깨뜨리지 않고 동작해야 한다는 원칙입니다.
즉, 하위 클래스가 상위 클래스의 역할을 대신할 수 있어야 합니다.


🛠️ LSP 위반 코드 예시

java
복사편집
public class Bird { public void fly() { System.out.println("새가 날아간다"); } } public class Ostrich extends Bird { @Override public void fly() { throw new UnsupportedOperationException("타조는 날 수 없습니다."); } }

문제점:

  • Ostrich 클래스는 Bird의 하위 클래스지만, fly() 메서드를 지원하지 않습니다.
  • LSP를 위반했기 때문에 상위 클래스와 하위 클래스가 호환되지 않습니다.

LSP 준수 코드

java
복사편집
public interface Bird { void sound(); } public interface FlyingBird extends Bird { void fly(); } public class Sparrow implements FlyingBird { public void fly() { System.out.println("참새가 날아간다"); } } public class Ostrich implements Bird { public void sound() { System.out.println("타조가 소리를 낸다"); } }

📌 4. I – 인터페이스 분리 원칙 (ISP)

"클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다."


📌 5. D – 의존 역전 원칙 (DIP)

"고수준 모듈은 저수준 모듈에 의존해서는 안 된다."


🎯 마무리

SOLID 원칙을 잘 이해하고 코드에 적용하면 유지보수와 확장성이 뛰어난 시스템을 만들 수 있다.
한 번에 완벽히 적용하기 어렵지만, 작은 습관부터 시작해보자 😊