[JAVA] SOLID 원칙

유지보수와 확장이 쉬운 소프트웨어를 만들기 위한 5가지 설계 원칙인 SOLID 원칙에 대해 알아보자.


SOLID 원칙

  • 객체지향 프로그래밍(OOP)에서 SOLID 원칙이란, 유지보수와 확장이 쉬운 소프트웨어를 만들기 위한 5가지 설계 원칙
  • 각각의 원칙의 첫글자를 따서 만든 약자.
  • solid 원칙

1. SRP (Single Responsibility Principle)

🔴 단일 책임 원칙

  • 정의
    • 하나의 클래스는 단 하나의 책임(기능)만 가져야 한다.
    • 즉, 클래스가 변경될 이유는 오직 하나여야 한다/
  • 의미
    • 클래스가 너무 많은 역할을 담당하게 되면, 유지보수나 확장 시 하나의 변경 사항이 다른 기능까지 의도치 않게 영향을 줄 수 있음
    • 하나의 클래스가 단 하나의 목적만 수행하도록 하면, 코드 관리가 쉬워지고 명확해짐
  • 예시
    • ❌ 나쁜 예시 : 회원 관리 클래스가 로그인, 회원정보 관리, 이메일 발송까지 전부 담당
    • ✅ 좋은 예시 : 로그인 클래스, 회원정보 관리 클래스, 이메일 발송 클래스를 각각 따로 분리

2. OCP (Open/Closed Principle)

🟠 개방-폐쇄 원칙

  • 정의
    • 소프트웨어의 구성 요소(클래스, 모듈, 함수 등)는 확장에는 열려있고, 변경에는 닫혀있어야 한다.
  • 의미
    • 새로운 기능을 추가할 때 기존 코드를 수정하지 않고도 기능을 확장할 수 있어야 함.
  • 예시
    • ❌ 나쁜 예시 : 새로운 결제 방식을 추가할 때마다 기존의 결제 클래스를 직접 수정
    • ✅ 좋은 예시 : 결제 방식 인터페이스를 정의하고, 이를 구현한 클래스(신용카드 결제, 페이팔 결제 등)를 추가함으로써 기존 코드 수정 없이 확장 가능

3. LSP (Liskov Substitution Principle)

🟡 리스코프 치환 원칙

  • 정의
    • 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 함.
    • 부모 클래스가 사용되는 곳에 자식 클래스를 넣었을 때도 프로그램이 정확히 동작해야 함
  • 의미
    • 상속 관계를 올바르게 설계해 자식 클래스가 부모 클래스의 본질적인 특성을 바꾸지 않아야 한다.
    • 자식 클래스는 부모 클래스가 가진 모든 속성과 메서드를 위반 없이 사용할 수 있어야함
  • 예시
    • ❌ 나쁜 예시 : ‘정사각형’ 클래스를 ‘직사각형’의 자식 클래스로 만들었지만, 가로세로를 독립적으로 조정할 수 없어서 예상한 동작이 깨지는 경우
    • ✅ 좋은 예시 : ‘도형’이라는 부모 클래스를 상속하여 ‘직사각형’, ‘정사각형’, ‘삼각형’ 등으로 각자 독립적으로 확장하여 서로 간섭 없이 동작

4. ISP (Interface Segregation Principle)

🟢 인터페이스 분리 원칙

  • 정의
    • 클라이언트는 자신이 사용하지 않은 메서드에 의존하지 않아야 함.
    • 하나의 일반적인 인터페이스보다 여러 개의 구체적이고 세분화된 인터페이스를 사용하는 것이 좋음
  • 의미
    • 하나의 크고 범용적인 인터페이스보다, 용도에 따라 작고 명확하게 구분된 인터페이스를 제공하는 것이 좋음
    • 클라이언트가 필요로 하는 최소한의 메서드만 포함한 인터페이스를 만들어야함
  • 예시
    • ❌ 나쁜 예시 : 하나의 인터페이스에 “프린트, 팩스, 복사, 스캔” 기능을 모두 넣어서 일부만 사용하는 프린터 기기같이 모든 메서드를 구현해야하는 경우
    • ✅ 좋은 예시 : “프린트 인터페이스”, “팩스 인터페이스”, “복사 인터페이스”, “스캔 인터페이스”로 나눠서 필요한 기능만 구현하도록 제공

5. DIP (Dependency Inversion Principle)

🔵 의존성 역전 원칙

  • 정의
    • 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안되며 둘 다 추상화에 의존해야함
    • 또한, 추상화(인터페이스나 추상 클래스)는 세부 사항에 의존해서는 안되고, 세부 사항이 추상화에 의존해야함
  • 의미
    • 클래스가 특정 구현(구체적 클래스)이 아닌, 추상화된 인터페이스에 의존하도록 설계해야 함.
    • 이는 의존 관계룰 유연하게 만들어 유지보수 및 확장이 편리해지게 횜
  • 예시

    • ❌ 나쁜 예시 : 데이터베이스 클래스가 특정 DB(에: MySQL)에 직접 의존하는 코드 설계
    • ✅ 좋은 예시 : 데이터베이스 인터페이스를 정의하고, 이를 구현하는 다양한 DB클래스(MySQL, PostgreSQL 등)를 만들어 상위 모듈이 인터페이스에만 의존하도록 설계

    SOLID 원칙을 지켰을 때의 장점

    • 유지보수 용이성
    • 코드 확장 용이성
    • 가독성 및 코드 품질 향상
    • 테스트 용이성