> For the complete documentation index, see [llms.txt](https://real-dev.gitbook.io/real-library/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://real-dev.gitbook.io/real-library/java_oop_for_spring_framework/undefined/5-.-5-solid.md).

# 5장. 객체 지향 설계 5원칙 - SOLID

* 로버트 마틴이 설계 기본 원칙으로 제안한 5가지를 마이클 페더스가 두문자어로 소개한 것
  * SRP (Single Responsibility Principal)
  * OCP (Open - Closed Principal)
  * LSP (Liskov Subsitution Principal)
  * ISP (Interface Segregation Principal)
  * DIP (Dependency Inversion Principal)
* 따지건데 응집도를 높이고 결합도를 줄이는 고전 원칙을 객체지향 프로그래밍 방식으로 녹여내어 재정의한 원칙들
* SOLID는 제품이나 서비스가 아니기에 애매하다. 동일한 모듈을 보고도 누군가가 SOLID 원칙을 잘 지켰다고 하는 것을 누군가는 아니라고 하기도 한다. 그만큼 모호하고 어려운 개념이다.
* 하지만 SOLID 원칙을 준수하면서 만들어진 제품이 그렇지 않은 제품보다 유지보수성, 테스트 용이성, 가독성이 월등한 것은 자명하게 밝혀져있다.

### SRP

* 하나의 클래스에 너무 많은 역할과 책임이 부여되면 변경이 힘들고 여파도 크다. 작게 쪼개라
* 하나의 속성이 여러 의미를 갖는 경우도 단일 책임 원칙을 위반하는 사례라고 볼 수 있다.

### OCP

*“소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려있어야 하지만 변경에 대해서는 닫혀 있어야 한다.” - 로버트.C.마틴*

의역 → “자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 한다.”

* JDBC가 좋은 사례가 된다. 이 경우 드라이버만 갈아끼우면 Mysql, Oracle, Mssql 등 얼마든지 연결이 가능하다. (쿼리 문법이 다른건 차치하자)
* 자바 프로그램도 비슷한 결을 갖는다. 사용자의 운영체제에 상관없이 JVM에서 구동되는 프로그램으로 구성한 결과 운영체제의 변화에 닫혀있고, 프로그램 자체의 확장엔 열려 있다.
* 개방 폐쇄 원칙을 따르지 않는다고 하더라도 개발은 가능하다. 하지만 객체 지향의 가장 큰 장점인 유연성, 재사용성, 유지보수성을 얻을 수 없다.

### LSP

*“서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다.” - 로버트.C.마틴*

* 객체 지향에서 상속은 `하위 클래스 is a kind of 상위 클래스, 구현체 is able to interface` 관계를 만족해야한다. 그리고 이 경우 이미 리스코프 치환 원칙을 잘 지키고 있다 볼 수 있다.
* `Penguin pororo = new Penguin() Animal pororo = new Penguin() Animal pororo = new Animal()` 모두 가능해야 한다.

  잘못된 상속 사례

### ISP - 인터페이스 분리 원칙

*“클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.” - 로버트.C.마틴*

* 단일 책임 원칙은 하나의 클래스에 여러 책임을 물리는 대신 단일한 역할을 갖는 여러 개의 클래스로 분리한다면, 인터페이스 분리 원칙은 하나의 클래스에 여러 인터페이스를 물려 상황에 맞게 사용하는 방식이다.
* 즉, SRP와 ISP는 하나의 문제에 대한 서로 다른 해결법인 셈.
* 다만 저자는 SRP를 더 우선시 할 것을 권한다. 나도 그렇게 생각하고
* 인터페이스 최소주의 원칙은 인터페이스를 통해 메서드를 외부에 제공할 때는 최소한의 메서드만 제공하라는 것이다.

  공통 사항은 되도록 상위 클래스에서 정의되고, 인터페이스는 각각의 뾰족한 기능만 요구한다.
* 각 인터페이스는 상황에 맞는 기능만 명세하고 공개해야한다. 과도하게 열린 인터페이스는 혼란만 가중시킨다.

### DIP

*“고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다.” “추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.” “자주 변경되는 구현 클래스에 의존하지 마라” - 로버트.C.마틴*

* 잘 바뀌지 않는 인터페이스를 의존하는 구조로 변경했을 때의 장점은 그림 5-17에서 잘 드러난다.

### Summary

* SOLID는 객체 지향 프로그래밍에서 어떻게 해야 좀 유지보수하기 수월한 코드를 짤 수 있는지 고민의 결과로 나온 원칙들이다. 없어도 구현은 가능하지만 있을 때 더 좋다는 점을 기억하자.
* SoC(Seperation Of Concerns)는 관심사의 분리를 의미한다. 응집도는 높이고, 결합도는 낮출 수 있도록 고민해보자.
* 스프링 또한 SoC를 통해 SOLID를 극한까지 활용하고 있다.
* SOLID 원칙을 적용하면 파일의 개수는 더 많아지는 경향이 있다. 하지만 많아진 파일은 논리를 더 잘 분할하고, 더 잘 표현할 수 있게 만든다.
