본문 바로가기

OOP

[OOP] SOLID원칙 정리

728x90

개요

Java 진영에서 새로운 지식을 습득할 때 OOP의 특징과 SOLID 원칙이 항상 핵심이 된다.

따라서 이에 대해 확실한 이해가 있어야 본질적으로 깊게 해당 지식을 이해할 수 있다고 생각한다.

 

이번 기록의 목적은 SOLID 원칙에 대한 자세한 기록의 목적도 있지만

앞으로의 기록에서 SOLID 원칙을 계속해서 복기하고, 습득한 개념의 본질적인 핵심이 무엇인지 고민해 보기 위함이 가장 크다.

SOLID란?

프로그래밍에서 SOLID란 로버트 마틴이 명명한 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 말한다.

유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 필수적으로 지켜야 할 원칙들이다.

원칙 개념
단일 책임 원칙(Single Responsibility Principle) 한 클래스는 하나의 책임만 가져야 한다.
개방-폐쇄 원칙(Open/Closed Principle) 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
리스코프 치환 원칙(Liskov Substitution Principle) 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입 인스턴스로 바꿀 수 있어야 한다.
인터페이스 분리 원칙(Interface Segregation Principle) 특정 클라이언트를 위한 인터페이스가 여러 개가 범용 인터페이스 하나보다 낫다.
의존관계 역전 원칙(Dependency Inversion Principle) 구체화가 아닌 추상화에 의존해야 한다.

 

단일 책임 원칙(SRP)

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

 

여기서 하나의 책임이라는 것이란 무엇을 말할까?

로버트 마틴은 책임을 변경하려는 이유로 정의했다. 해당 클래스의 변경을 야기하는 이유는 하나만 있어야 한다는 것이다.

 

각 클래스를 하나의 관심사에 집중하도록 유지하면

각 클래스의 목적이 분명해지고, 확장이나 유지보수도 훨씬 쉬워진다.

개방/폐쇄 원칙(OCP)

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

 

만약 하나의 객체를 수정했을 때 그 객체에 의존하는 모든 객체들을 수정해야 하는 구조라면, 수정하기가 힘들다.

기능을 확장하거나 수정해야 할 때 제대로 동작하는 다른 객체들을 변경하지 않아도 되도록 해야 한다.

 

OCP에서 변경은 어떤 변경을 말하고, 확장은 어떤 확장을 말할까?

변경은 추상화된 역할의 변경이고, 확장은 구현의 확장을 말한다.

추상화된 역할이 변경이 닫혀 있어야 해당 객체에 의존하는 다른 객체들에 영향을 주지 않을 것이고,

역할 구현의 확장이 열려 있어야 해당 역할에 대한 추가 기능 구현이나 수정이 이뤄질 수 있을 것이기 때문이다.

리스코프 치환 원칙(LSP)

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

 

객체의 치환성 개념을 정의하는 원칙이다.

만약 자료형 S가 자료형 T의 하위형이라면, 자료형 T의 객체는 자료형 S의 객체로 교환할 수 있어야 한다.

이때 프로그램의 정확성을 깨뜨리지 않아야 하기 때문에 기능적으로도 치환이 가능해야 한다.

인터페이스 분리 원칙(ISP)

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

 

자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다. 

따라서 하나의 인터페이스가 너무 많은 기능을 요구하는 일이 없도록 해야 한다.

 

이를 위해 큰 덩어리의 인터페이스를 작은 단위들로 분리시킴으로써 꼭 필요한 메서드만 구현할 수 있도록 해야 한다.

그래야 객체 간 의존성을 느슨하게 하고, 확장이나 유지보수에 용이해진다.

의존관계 역전 원칙(DIP)

구체화가 아닌 추상화에 의존해야 한다.

 

고수준 모듈은 저수준 모듈에 의존해선 안된다. 대신 추상화된 역할(정책)에 의존해야 한다.

가령 운전자와 자동차가 있다고 해보자. 자동차는 KIA CAR, HYUNDAI CAR가 있다.

만약 운전자가 자동차라는 추상화된 역할이 아닌 특정 KIA CAR에 의존하고 있다면, KIA CAR가 아닌 다른 CAR로는 운전할 수 없다는 것을 의미한다. 다른 CAR를 운전할 때마다 코드를 변경해줘야 한다. 이뿐만이 아니라 KIA CAR 코드를 변경하게 되면, 운전자의 코드도 변경해야 할 수도 있다.

 

위처럼 고수준 모듈이 저수준 모듈에 강하게 의존하게 되면

저수준 모듈의 수정이 고수준 모듈의 수정에 영향을 주게 되고, 저수준 모듈임에도 교체가 어려워진다.

 

때문에 저수준 모듈의 역할을 추상화해 저수준 모듈이 추상화된 역할에 의존하게 함으로써 의존관계를 역전시켜야 한다는 것이 DIP다.

이렇게 되면 고수준 모듈은 역할에 의존하기 때문에 저수준 모듈 구현에 영향을 받지 않게 되고, 저수준 모듈을 쉽게 교체할 수 있다.

위 예시로 생각해보면 운전자는 CAR라는 역할에 의존하게 된다. 결과적으로 더이상 KIA CAR의 변경에 영향을 받지도 않고, HYUNDAI CAR 등 다른 CAR로 쉽게 교체할 수 있게 된다.

마무리

앞으로 더 공부하면서 잘못 생각했던 부분이나 추가할 만한 부분에 대한 수정이 있을 예정입니다.

제가 이해한대로 기록한 글이기 때문에 틀린 내용이 있을 수 있습니다. 이에 대한 지적이나 피드백은 환영입니다 :)

참고

 

SOLID (객체 지향 설계) - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 컴퓨터 프로그래밍에서 SOLID란 로버트 마틴[1][2]이 2000년대 초반[3]에 명명한 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙을 마이클 페더스가 두문자어

ko.wikipedia.org

 

728x90

'OOP' 카테고리의 다른 글

[OOP] 디미터의 법칙  (0) 2023.11.01