개발관련/용어

SOLID 원칙이란? (객체지향 5대원칙)

고통받는다 2023. 6. 29. 16:17

여러분이 객체지향 5대원칙에 대해 공부를 하다보면 듣게될 용어중 하나입니다.

 

SOLID.. 이름만 들었을때 뭔가 강해보이는 이름이다..

 

객체지향 5대원칙?

 

객체지향 5대원칙은 SRP(단일책임 원칙), OCP (개방 - 폐쇄 원칙), LSP (리스코프 치환 원칙) ,

DIP (의존 역전 원칙), ISP (인터페이스 분리 원칙) 을 일컫는 말입니다.

위 5가지의 앞자를 따서 SOLID 원칙이라고 부릅니다.

위 원칙을 적용하면 유지보수나 확장이 쉬운 소프트웨어를 만들수가 있습니다.​

Single Responsibility Principle (단일 책임 원칙)

 

  1. 하나의 클래스는 단 하나의 책임만을 가져야 합니다.
  2. 클래스를 변경하는 이유는 단 하나여야 합니다.
  3. 위 내용을 지키지 않을시, 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향을 미칠수 있습니다.

말이 좀 어려운가요?

쉽게말하자면 한클래스에는 그 클래스와 연관된 기능만 넣으라는 겁니다.

(Ex. 자바로 치면 Main 클래스에, Android로 치면 해당 Activity에 모든 코드를 다 작성하지 말라는겁니다. )​

Open-Closed Principle (개방-폐쇄 원칙)

 

  1. 확장에는 열려있어야 하며, 변경에는 닫혀있어야 합니다.
  2. 기존의 코드를 변경하지 않고 기능을 수정하거나 추가할수 있도록 설계해야 합니다.

이것도 쉽게 설명하자면... 여러분이 어느 기능을 만들었다고 칩시다

Ex.

컴퓨터 공학과 학생을 찾고 리스트를 보여주는 기능을 개발하라고 해서 정말 그것만 검색가능하게 어찌어찌 만들었다고 칩시다.

지금 당장은 전혀 문제가없고 원하는대로 잘 실행이 됩니다.

하지만 몇달후 갑자기 위에서 컴퓨터공학과 말고도 소프트웨어 학과 학생들도 검색이 되게 하라고 합니다.

OOP 원칙을 잘 지켰다면 그냥 데이터만 추가해서 기능이 돌아가게 할수 있으나...

OOP를 지키지 않고 막개발을 했다면... 이번에는 소프트웨어 학과 학생도 검색이 가능하게 코드를 뜯어서 고쳐야 할수 있습니다.

이렇게 개발을 했다는 시점에서 이미 OOP의 장점인 유연성, 재사용성, 유지보수성을 모두 버린것입니다.

사실상 객체지향 언어를 사용했지만 전혀 객체지향적이지 않게 개발했다는 뜻이 되는거죠...​

Liskov Substitution Principle (리스코프 치환 원칙)

 

  1. 하위 타입 객체는 상위 타입 객체에서 가능한 행위를 수행할 수 있어야합니다.
  2. 상속관계에서는 꼭 일반화 관계가 성립해야 합니다.
  3. 상속관계가 아닌 클래스들을 상속관계로 설정하면 해당 원칙이 위배됩니다.

EX.

가장 대표적인 예시가 여러분들이 자주 사용하는 ArrayList 입니다.

List의 모든 행위 (메서드) 들을 사용이 가능합니다.

Interface Segregation Principle (인터페이스 분리 원칙)

 

  1. 클라이언트는 자신이 사용하는 메서드에만 의존해야합니다.
  2. 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 않아야 합니다.
  3. 인터페이스는 해당 인터페이스를 사용하는 클라이언트를 기준으로 분리되어야 합니다.

Ex.

여러분이 A클래스를 위한 인터페이스를 만들었다고 칩시다.

그러다 B클래스에서 A클래스에서 만든 일부 인터페이스의 기능 10개중 1개만 사용해야할 일이 생겼다고 칩시다.

이때 새 인터페이스를 만들기 귀찮다고 B클래스에 A클래스를 위해 만든 인터페이스를 implement하고 나머지 9개의 메서드를 구현하지 않는다면 위 원칙에 위배되는 겁니다.

 

Dependency Inversion Principle (의존 역전 원칙)

 

  1. 의존 관계를 맺을때는 변하기 쉬운것 (구체적인것) 보다는 변하기 어려운것 (추상적인것)에 의존해야합니다.
  2. 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안됩니다.
  3. 저소준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 합니다.
  4. 저수준 모듈이 변경되어도 고수준 모듈이 변경이 필요없는 형태가 이상적입니다.

Ex.

A라는 클래스가 B라는 클래스에 의존할때 B는 구체적으로 구현된 클래스면 안된다는 소리입니다.

이유는 당연하게도 구체적으로 구현이 된 B클래스를 변경해야할 일이 생겼을때 그에 의존적인 A클래스 역시 변경해야 하기 때문입니다.

기능 확장을 위해 B클래스를 변경할때마다 A클래스 역시 같이 변경해야 하는건 일을 두번하는 것이죠... 매우 비효율적이라는 소리입니다.

​​

정리

 

SRP와 ISP는 객체의 규모가 커지는것을 방지해 줍니다.

객체가 단일책임을 가지게 하고, 각 클라이언트마다 인터페이스를 구현하게 함으로 한 기능의 변경이 일어나더라도 다른 곳까지 미치는 영향을 최소화 해줍니다.

이는 기능의 추가 및 변경에 유리하게 도와줍니다.

LSP와 DIP는 OCP를 서포트 합니다.

OCP는 변화되는 부분을 추상화 하고 다형성을 이용함으로 기능확장에는 용이하되 기존 코드의 변화는 거의 없도록 해줍니다.

여기서 변화되는 부분을 추상화 활수 있도록 도와주는게 DIP고 다형성 구현을 도와주는것이 LSP 입니다.