백엔드 개발자

[SOLID] 객체 지향 5가지 원칙 본문

스프링

[SOLID] 객체 지향 5가지 원칙

임잠탱 2022. 10. 26. 02:28

SOLID 란 ?

SRP - Single Responsibility principle (단일 책임 원칙)

OCP - Open/closed principle (개방-폐쇄 원칙)

LSP - Liskov substitution principle (리스코프 치환 원칙)

ISP - Interface segregation principle (인터페이스 분리 원칙)

DIP - Dependency inversion principle (의존관계 역전 원칙)

 

SRP 단일 책임 원칙

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

 

한 클래스 안에 여러가지의 기능이 있으면 유지보수나 변경이 어려워진다.

나중에 이 클래스가 하는 기능이 어떤 것인지 모를 수도 있게된다.

 이게 뭐하는 클래스지??

 

또 기능을 너무 세세하게 나눠놓는 것도 클래스가 너무 많아져 비효율적이다.

적절한 기준으로 책임을 나누는 것이 중요하다.

 

OCP 개방-폐쇄 원칙

- 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.(다형성)

 

예를 들어 자동차가 있다.

 

Car car = new BungBung()

Car 를 붕붕이로 선언하여 코드를 작성하였다.

그런데 오토바이로 바꾸고 싶어졌다.

그럼 기존 코드를 변경할 필요없이 Car 인터페이스로 오토바이를 구현하여 선언해주면 된다.

 

이것은 확장에 열려있고 변경에는 닫혀있는 코드가 된다.

 

LSP 리스코프 치환 원칙

- 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다.

저희는 이걸 00라고 부르기로 했어요.. 그게 사회적 약속이에요..

달리기는 달리는 기능을 구현해야 하고, 멈추다는 멈추는 기능을 구현해야 한다. 

이게 무슨말일까???

 

 

자동차 인터페이스가 있다.

 

 

public interface Car(){
      public void run(){};
}

이 인터페이스는 run 이라는 메소드를 가지고 있고, 인터페이스를 구현한 구현체는 run 을 구현해야 한다.

 

그런데 run 을 시동을 끄는 것으로 구현하면 인터페이스 규약을 깨는것이다.

컴파일에는 문제가 없지만 우리가 기대하는 기능을 하지 않아 정확성을 깨뜨리기 때문이다.

그러므로 사회적 약속을 잘 지키도록 하자.^^

 

ISP 인터페이스 분리 원칙

- 범용 인터페이스 하나보다 여러개의 인터페이스 여러개가 낫다.

 

자동차 인터페이스 -> 운전 인터페이스 , 정비 인터페이스 로 분리.

인터페이스 기능이 명확해지기 때문에 유지보수가 편리하다.

 

변경이 필요한 인터페이스의 구현체만 변경하면 된다.

 

-> 운전 인터페이스의 변경이 필요하면 운전 인터페이스의 구현체만 변경을 하면 되므로 정비 인터페이스 구현체에 영향을 주지 않음.

<<인터페이스를 구현한 구현체들>>

운전 인터페이스 -> 운전자 클라이언트
정비 인터페이스 -> 정비사 클라이언트 
( 정비사 클라이언트 변경 X)

 

DIP 의존관계 역전 원칙

- 구현 클래스에 의존하는 것이 아닌 인터페이스에 의존해야 한다.

 

예를 들어 오늘의 음료를 판매하는 카페가 있다.

오늘의 음료 는 매일 바뀌게 되는데 다른 음료로 변하는것 --> 확장 하는 것이 가능해야 한다.

 

그렇지만 그럴때마다 코드를 수정하는 변경이 일어나면 안된다.

 

예를 들어 오늘의 음료는 아메리카노이다.

오늘의 음료는 추상화이고 아메리카노는 구체화된 객체이다.

 

아메리카노는 오늘의 음료입니다.
오늘의 음료인 아메리카노를 주문하시면 10퍼센트의 할인을 적용해 드립니다.

 

만약 코드에 구현 클래스인 아메리카노를 직접 참조를 하였다.

그러면 내일은 또 바뀐 바닐라라떼로 변경해 주기 위해 코드를 변경해 주어야 한다.

 

DIP 원칙은 구체화된 객체를 직접 참조하지 않고 추상화를 참조해야 한다.

오늘의 음료 -> return (아메리카노 class);

오늘의 음료 는 오늘의 음료입니다.
오늘의 음료인 오늘의 음료 를 주문하시면 10퍼센트의 할인을 적용해 드립니다.

 

아메리카노를 직접 참조하지 않고 오늘의 음료를 참조하면 다음날에 오늘의 음료가 바뀌어도 

오늘의 음료 코드만 변경해주면 클라이언트의 코드를 변경하지 않아도 된다.

 

 

그런데 잠깐..

위에 OCP는 DIP를 위반한다.

 

 

Car car = new BungBung()

 

이렇게 구체화된 클래스를 직접 참조하기 때문에 클라이언트 코드의 변경이 일어나게 된다.

결국 OCP의 다형성만으로 해결할 수 없기 때문에

 

그래서 의존성 주입을 해주어야 한다.

객체를 직접 참조하지 않고 생성자 주입을 통해 인터페이스를 주입해주고 인터페이스가 구체화된 객체를 반환해 주게 된다.

그럼 OCP 와 DIP를 모두 지키게 된다!!

 

글로 정리 하는 것 너무 어렵다...

 

 

 

 

 

-출처 인프런 김영한님의 [스프링 기본편] 강의

Comments