[Java] 객체 지향 설계 5원칙 SOLID

조혜은·2025년 4월 17일

Java

목록 보기
4/10

객체 지향 설계 5원칙 SOLID

객체 지향의 4대 특성이 객체 지향 프로그램을 작성할 수 있는 도구라면, 이를 올바르게 사용하는 법이 객체 지향 설계 5원칙이다.

  • SRP(Single Responsibility Principle): 단일 책임 원칙
  • OCP(Open Closed Principle): 개방 폐쇄 원칙
  • LSP(Liskov Substitution Principle): 리스코프 치환 원칙
  • ISP(Interface Segregation Principle): 인터페이스 분리 원칙
  • DIP(Dependency Inversion Principle): 의존 역전 원칙

응집도는 높이고 결합도는 낮추라는 고전 원칙을 객체 지향의 관점에서 재성립한 것.

SRP 단일 책임 원칙

" 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다 "

클래스를 역할과 책임에 따라 분리해 각각 하나의 역할과 책임만 갖게 하기.
ex) 남자 클래스 -> 남자친구, 아들, 직장상사 클래스로 분리.
하나의 속성이 여러 의미를 갖는 경우에도 단일 책임 원칙을 어긋나는 것.
테이블을 설계할 때도 단일 책임 원칙을 지키는 것이 좋다.
SRP를 지키지 못할 경우 if문을 쓰게 된다.
ex) 사람 클래스, 속성으로 성별 -> 메서드에서 if 성별 == 남자, ~하기 이런식으로 하는 것은 좋지 않다.
사람 클래스 -> class 남자 extends 사람 / class 여자 extends 사람 이런식으로 해야함.
4대 특성 중 추상화와 연관이 있음.

OCP 개방 폐쇄 원칙

" 소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있고, 변경에 대해서는 닫혀 있어야 한다. "
-> 자신의 확장에는 열려있고, 주변의 변화에 대해서는 닫혀 있어야 한다.

중간에 클래스나 인터페이스를 둬서 영향이 안 가도록 하는 것이 좋다.
운전자 -> 마티즈 (X)
운전자 -> 자동차 -> 마티즈 (O)
데이터 베이스 프로그래밍을 지원하는 라이브러리와 프레임워크에서도 개방 폐쇄 원칙을 볼 수 있다. ex) JDBC: JDBC 인터페이스를 통해 어떤 데이터베이스를 사용하던 수정할 부분이 적거나 없음.
스프링 프레임워크 또한 좋은 예.

LSP 리스코프 치환 원칙

" 서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다. "

기반 타입 = 상위 클래스. 서브 타입 = 하위 클래스

상속의 조건

  • 하위 클래스 is kind of 상위 클래스: 하위 분류는 상위 분류의 한 종류다.
  • 구현 클래스 is able to 인터페이스: 구현 분류는 인터페이스할 수 있어야 한다.

위 두 문장을 만족하면 리스코프 치환 원칙을 잘 지키고 있는 것.
아버지 - 딸 이런 계층 구조는 LSP를 위배하고 있는 것.

LSP는 상속과 연관이 있다.

ISP 인터페이스 분리 원칙

" 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다. "

SRP에선 남자 클래스를 여러 클래스로 분할 했었다.
ISP에선 클래스를 분할하지 않고 여러 인터페이스로 각 상황마다 제한을 두는 것이다.
같은 문제에 대한 2가지 해결책인 느낌.
근데 보통 단일 책임 원칙을 적용하는 것이 좋다고 한다.
인터페이스 최소주의 원칙: 인터페이스를 통해 메서드를 외부에 제공할 때는 최소한의 메서드만 제공하라는 것. 상위 클래스는 풍성할수록 좋고 인터페이스는 작을수록 좋다.

DIP 의존 역전 원칙

" 고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다. "
" 추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다. "
" 자주 변경되는 구체 클래스에 의존하지 마라 "

ex)
자동차 -> 스노우 타이어
자동차가 스노우 타이어에 의존적인 관계이다. 하지만 스노우 타이어는 계절에 영향을 받아 바뀐다. 그러면 자동차도 이 영향에 노출되므로 바꿔야 한다.
자동차 -> 타이어(인터페이스) <--스노우 타이어
이렇게 바꾸면 자동차는 타이어 인터페이스에만 존재함으로써 영향을 받지 않는다.
스노우 타이어는 이전에는 그 무엇에도 의존하지 않는 클래스였는데 추상적인 것인 타이어 인터페이스에 의존하게 됐다. 의존의 방향이 역전된 것!
자동차는 자신보다 변하기 쉬운 스노우 타이어에 의존하던 관계를 중간에 추상화된 타이어 인터페이스를 추가함으로써 의존 관계를 역전시키고 있다.

자신보다 변하기 쉬운 것에 의존하고 있던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향을 받지 않게 하는 것.

" 자신보다 변하기 쉬운 것에 의존하지 마라 "

상위 클래스일수록, 인터페이스일수록, 추상 클래스일수록 변하지 않을 가능성이 높기에, 하위 클래스나 구체 클래스 말고 상위 클래스, 인터페이스, 추상 클래스에 의존하라는 것.

SOLID 요약

SoC(Separation of Concerns) 관심사의 분리
관심이 같은 것끼리는 하나의 객체 안으로 또는 친한 객체로 모으고, 관심이 다른 것은 가능한 한 따로 떨어져 서로 영향을 주지 않도록 분리하라는 것.
관심사가 다르고 변화의 시기가 다르면 분리해야 한다는 것.
SoC를 적용하면 자연스럽게 SRP, ISP, OCP에 도달한다.

SOLID

  • SRP: 단일 책임 원칙. 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.
  • OCP: 개방 폐쇄 원칙. 자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 한다.
  • LSP: 리스코프 치환 원칙. 서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다.
  • ISP: 인터페이스 분리 원칙. 클라이언트는 자신이 사용하지 않는 메서드레 의존 관계를 맺으면 안 된다.
  • DIP: 의존 역전 원칙. 자신보다 변하기 쉬운 것에 의존하지 마라.

현실에서도 우리보다 성숙하고 쉽게 변하지 않는, 단단한 사람에게 의존하게 된다고 비유한 부분이 와닿았다.
이 책에서는 객체 지향을 현실 세계에 많이 비유한다. 그래서 더 이해도 잘 되는 것 같다.
객체 지향 세계는 현실 세계와 같고, 모델링을 통해 추상화됐다.

0개의 댓글