본문 바로가기
컴공생의 Knowledge/Expertise

[OOP] 객체지향 5원칙 - SOLID란?

by UIC 2022. 12. 27.
728x90

오늘은 객체지향 프로그래밍을 하기 전에 꼭 알았으면 하는 개념인 SOLID 원칙에 대해 알아볼 예정입니다.

 

 

SOLID 원칙이란?

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): 의존관계 역전 원칙

 

이 5가지 원칙의 앞 알파벳을 따서 SOLID 원칙으로 불리게 되었습니다.

이 원칙들은 소프트웨어 개발 시 프로그래머가 소스 코드를 읽기 쉽고 확장하기 쉽게 하기 위한 소프트웨어 소스 코드 리펙토링 적용 지침이라 할 수 있습니다.

이렇게 5가지 개념을 통해 객체 지향 프로그래밍을 설명하는 SOLID 원칙을 하나하나 톺아보겠습니다.

 

 

 

 

1. SRP(Single Responsibility Principle): 단일 책임 원칙

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

 

SRP(단일 책임 원칙)는 어떤 클래스나 모듈은 변경하려는 단 하나의 이유만을 가져야한다고 정의된 원칙입니다.

즉, 어떤 클래스는 하나의 성격 및 책임만을 가져야한다는 의미입니다. 이 내용을 말로 풀기는 어려우니 간단한 예로 알아보겠습니다.

 

 

한 남자가 있습니다.

이 남자는 부모님에게는 아들로, 여자친구에게는 남자친구로, 회사에서는 직원으로써의 역할을 갖고 있습니다.

한 남자를 클래스로 구현할 때, 하나의 클래스로 아들, 남자친구, 직원의 속성을 모두 갖는 클래스를 구현할 수 있습니다.

또한, 아들 클래스, 남자친구 클래스, 직원 클래스로 각각 구현 후 상속을 통해 한 남자를 클래스를 구현할 수 있습니다.

 

 

이 때 각 역할을 구분하여 클래스로 구현하는 방법이 단일 책임 원칙을 지킨 구현 방법이라고 할 수 있습니다.

 

 

 

 

2. OCP(Open - Closed Principle): 개방 - 폐쇄 원칙

소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.


OCP(개방 - 폐쇄 원칙)는 모든 소프트웨어 엔티티는 확장에 대해서는 열려있어야 하지만, 변경에 대해서는 닫혀있어야 한다고 정의된 원칙입니다.

즉, 자신의 확장에 대해서는 열려있지만, 주변의 변화에 대해서는 닫혀 있어야 한다는 어려운 말로 표현되어져 있지만, 실제 개념은 예로 간단하게 설명해보겠습니다.

 

 

한 사람이 출퇴근용 경차와 데이트용 스포츠카를 갖고 있습니다. 

이 두 차를 클래스로 구현해보려고 합니다. 이 두 자동차는 자동차라는 특징을 갖고 있기에 속성과 동작은 아래와 같이 유사합니다.

 

 

자동차
  경차 스포츠카
속성 바퀴, 문, 배기량, 최대 속도, 제로백 ... 바퀴, 문, 배기량, 최대 속도, 제로백 ...
동작 문열기, 창문열기, 에어컨 틀기, 시동 걸기, 브레이크/악셀 밟기 ... 문열기, 창문열기, 에어컨 틀기, 시동 걸기, 브레이크/악셀 밟기 ...

 

 

경차와 스포츠카는 위의 속성과 동작을 모두 갖고 있기에, 차 주인이 어떤 차인지와 관계없이 공통된 속성과 동작으로 차를 관리하고자 합니다. 이 때, 생성할 수 있는 자동차라는 공통된 속성 및 동작을 갖고 있는 인터페이스(or 상위 클래스)로 추출하여 차 주인이 자동차 관리를 함에 있어서 어떤 차인지에 영향을 받지 않게 됩니다.

 

 

여기서 경차와 스포츠카의 공통된 속성과 동작을 하나의 인터페이스(or 상위 클래스)로 추출하는 방법이 확장에는 열려있으며, 변경에는 닫혀있는 OCP를 지킨 구현 방법이라 할 수 있습니다.

 

 

 

 

3. LSP(Liskov Substitution Principle): 리스코프 치환 원칙

프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.

 

LSP(리스코프 치환 원칙)는 A 객체가 B 객체의 상위 계층이라면, B 객체는 어떤 변경 없이도 A 객체로 치환할 수 있어야한다고 정의된 원칙입니다.

즉, 하위 객체로 정의된 엔티티(변수, 클래스 등)라면 상위 객체로 치환이 가능하다는 의미입니다. 예를 들어 간단하게 설명해보겠습니다.

 

 

LSP을 만족하는 계층은 아래의 예와 같이 하위 객체를 상위 객체가 포함하고 있어야합니다. 

 

동물 포유류 고래
돼지
조류 참새
비둘기

 

 

다시 말하면, 하위 클래스의 인스턴스는 상위 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다고 정의되어져 있습니다.

 

 

 

 

4. ISP(Interface Segregation Principle): 인터페이스 분리 원칙

특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.

 

ISP(인터페이스 분리 원칙)는 SRP(단일 책임 원칙)과 유사합니다. SRP는 단일 클래스는 하나의 책임을 가져야한다고 정의되어진 원칙과 유사하게 ISP는 인터페이스는 각 역할에 맞게 분리되어져야 한다고 정의된 원칙입니다.

즉, SRP는 하나의 책임을 갖는 클래스로 구분되어져야하고, ISP는 각 역할에 맞는 인터페이스로 분리되어져야하기에 유사한 상황에서의 다른 해결책으로 볼 수 있습니다.

(이 상황에서 특별한 경우가 아니라면 SRP(단일 책임 원칙)을 적용하는 것이 더 좋은 해결책이라고 볼 수 있습니다.)

 

 

ISP는 아래 두 가지 정의로 더 세분화할 수 있습니다.

  • 상위 클래스는 풍성할수록 좋다.
  • 인터페이스 내에 메소드는 최소한 일수록 좋다.

위 세분화된 내용은 풍성할수록 하위 클래스에게 기능 확장 및 코드 중복을 줄여주는 장점과 인터페이스는 최소한의 기능만을 하위 클래스에게 구현을 강제하는 역할을 하는 것으로 설명되어집니다.

 

 

 

 

5. DIP(Dependency Inversion Principle): 의존관계 역전 원칙

추상화에 의존해야지, 구체화에 의존하면 안된다

 

DIP(의존관계 역전 원칙)는 "고차원 모듈은 저차원 모듈에 의존하면 안된다"와 "추상화된 것은 구체적인 것에 의존하면 안된다"라는 정의로 설명되어지는 원칙입니다.

즉, 어떤 특정한 하위 속성에 하나의 클래스가 의존되어지는 경우, 상위 개념이 하위 개념에 의존되어 고정된 클래스로 밖에 활용할 수 없는 문제를 해결하는 원칙이며, 간단한 예로 설명해보겠습니다.

 

 

요즘 사람이 사용하는 물건 중 땔래야 땔수없는 것이 핸드폰입니다. 어떤 사람이 아이폰만 사용한다고 해도 아이폰의 버전이 천차만별이고 한 사람은 아이폰 14프로만 사용해야하는 의존성을 지니게된다면 이 사람은 2022년부터 존재할 수 있으며, 아이폰의 최신 버전을 사용할 수 없는 이상한 사람이 되어버리는 오류가 발생하게 됩니다.

 

 

즉, 사람이 가질 수 있는 속성 중 핸드폰은 사람의 하위 속성이기에 현재 어떤 속성을 가질 수는 있지만 해당 속성에 의존해서는 안되는 추상화 원칙을 설명하고 있습니다.

 

 

 

 

결론

오늘은 SOLID 원칙이라는 객체지향 프로그래밍의 5원칙을 공부해보았습니다.

비록 어려운 개념일 수도 있지만, 객체지향 프로그래밍의 기본 5원칙인 SOLID 원칙을 이해하고 예제를 통해 습득한 내용으로 기능 구현에 적용할 수 있을 것 같다는 생각이 들었습니다.

 

이 글을 통해 앞으로 객체지향 프로그래밍을 수행할 때 위 원칙들을 지키는 설계 및 구현을 하면 어떨까요?

 

 

 

 

참고문헌

https://ko.wikipedia.org/wiki/SOLID_(%EA%B0%9D%EC%B2%B4_%EC%A7%80%ED%96%A5_%EC%84%A4%EA%B3%84) 

https://devlog-wjdrbs96.tistory.com/380

728x90

댓글