객체지향프로그래밍(29) - 이론적 배경(2) - 객체지향의 SOLID 원칙

객체 지향의 SOLID 원칙에 대해 이해.

Featured image

🔚 짧게 하는 복습

✅ 1. 4대 특성 중 캡슐화와 그 장단점을 안다.

✅ 2. 4대 특성 중 추상화와 그 장단점을 안다.

✅ 3. 4대 특성 중 상속과 그 장단점을 안다.

✅ 4. 4대 특성 중 다형성과 그 장단점을 안다.

혹시 기억이 안 난다면, 다시 돌아가자


저번 시간에 이어서 이번 시간의 내용도 가벼운 마음으로 읽어보도록 하자.

이번 시간에 다룰 내용은 객체지향의 5대 원칙으로 불리기도 하는 SOLID 원칙이다.


SOLID 원칙이란?

SOLID 원칙은 소프트웨어 설계의 기본 원리로서, 좋은 소프트웨어 설계를 위해 반드시 준수해야 하는 원칙들로, OOD에서 고려해야 할 필수 사항이다.


단일 책임 원칙 (Single Responsibility Principle, SRP)

첫 번째는 단일 책임 원칙이다.

이름 그대로 하나의 클래스는 하나의 책임만 가져야 한다는 뜻이다.

당연한 말 같지만, 아래와 같은 말로도 동시에 번역이 될 수 있다.

클래스가 변경되어야 하는 이유는 오직 하나여야 한다.

역시 이를 통해, 원하는 것은 클래스의 응집성을 높이고 유지보수을 향상하는 것이다.


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

두 번째는 개방-폐쇄의 원칙이다.

이는 소프트웨어 엔티티(클래스, 함수 등)확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다라는 뜻이다.

변경에는 닫혀 있어야 한다는 말이 오해를 일으킬 수 있는데, 한 번 만들고 나서 수정해서는 안 된다는 말이 아니다.

기능 수정이 아니라 기능 확장 시에 기존의 코드를 수정하지 않고도 새로운 기능을 추가할 수 있도록 설계되어야 한다는 뜻이다.

이를 통해 코드의 재사용성을 높이고 변경에 대한 위험을 최소화한다.

역시나 유지보수의 장점이 존재한다.


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

세 번째는 리스코프 치환 원칙이다.

여기서 말하는 것은 하위 타입은 상위 타입에서 대체 가능해야 한다는 것이다.

즉, 상속 관계에서 하위 클래스는 상위 클래스의 기능을 변경하지 않고 확장할 수 있어야 한다.

상속을 이용한 캐스팅일 수도 있고, 합성이나 집합을 의미할 수도 있다.

이를 통해 다형성을 지원하고 프로그램의 일관성을 유지한다.


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

네 번째는 인터페이스 분리의 원칙이다.

클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안 된다는 것이다.

우리 강의에서는 클라이언트인터페이스를 직접적으로 다루지 않았기에, 간단하게 설명하면 클라이언트는 다른 클래스나 서비스를 사용하는 주체이고, 인터페이스클래스나 모듈이 제공하는 기능을 정의한 것이다.

예를 들어 자동차를 운전하는 속성의 인터페이스라면, 클라이언트는 자동차를 타는 고객,

자동차를 작동시키는 속성의 인터페이스라면, 클라이언트는 자동차 그 자체 정도로 소개할 수 있다.

즉, 자신이 필요한 기능만 모인 인터페이스가 필요하고, 클라이언트는 그 인터페이스만 사용해야 한다는 말이다.

이를 통해 인터페이스의 응집성을 높이고 결합도를 낮춘다.

또, 의도치 않은 기능을 할 위험을 줄이기에 변경 혹은 버그의 취약점에서 벗어날 수 있다.


의존 역전 원칙 (Dependency Inversion Principle, DIP):

마지막은 의존 역전의 원칙이다.

이는 고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 한다는 것인데, 모듈부터 알아보자.

모듈각각의 기능을 수행하는 코드 블록이나 파일로 구성될 수 있다.

예를 들자면 주로 함수, 클래스, 라이브러리 등이 모두 모듈이다.

예를 들어, 자동차를 운전하는 속성의 모듈운전자나 운전 기능(고수준 모듈)에 의존한다.

이렇게 말해도 모호한 것이 사실이다. 예를 들어 보겠다.

고수준 모듈은 시스템의 주요 기능을 담당하는 모듈로, 일반적으로 사용자 또는 다른 모듈과의 상호작용을 처리한다.

예를 들어, 자동차 시스템에서는 운전자가 자동차를 운전하는 기능이 고수준 모듈에 해당한다고 하자.

이 모듈은 자동차 시동을 걸고, 가속, 제동, 방향 조작 등의 운전 기능을 제공한다.

저수준 모듈고수준 모듈의 구체적인 기능을 실제로 구현하는 모듈이다.

이 모듈은 고수준 모듈이 요구하는 기능을 구현하고 제공한다.

자동차의 경우, 엔진, 변속기, 제동장치 등이 저수준 모듈에 해당한다.

이 모듈들은 자동차의 실제 동작을 제어하고 구현한다.

의존 역전 원칙을 적용하면 고수준 모듈이 저수준 모듈에 의존하는 것이 아니라, 추상화된 인터페이스에 의존하게 된다.

예를 들어, 운전자는 자동차를 운전하기 위해 운전 인터페이스를 사용합니다. (당연한 말이다.)

이 운전 인터페이스는 특정 자동차 모델이나 제조사에 의존하지 않고, 추상화된 운전 기능을 제공한다.

따라서 고수준 모듈은 운전 인터페이스에만 의존하게 되며, 구체적인 자동차 모델이나 제조사에 의존하지 않습니다.

이를 통해 운전자나 운전 속성을 변경하더라도 코드의 변경을 최소화한다.

즉, 새로운 자동차 모델이나 운전 기능을 추가하거나 변경할 때, 기존 코드의 수정이 필요 없이 운전 인터페이스를 구현하는 새로운 저수준 모듈을 제공함으로써 시스템을 확장하거나 유지보수할 수 있다.


SOLID 원칙의 공통적 장단점

결국은 SOLID 원칙의 공통점으로도 실제 세계의 반영유지보수에 의의가 있다.

최대한 그 실제 세계의 모습을 추상화해서 간단하게 나타내고 그것을 최대한 하나의 기능만 하는 인터페이스로 관리한다.(단독 책임의 원칙, 인터페이스 분리의 원칙)

세부 구현 모듈은 추상화된 인터페이스에 의존하여 구현되어야 하고, 하위 타입은 상위 타입을 대체할 수 있어야 한다.(리스코프 치환의 원칙, 의존 역전의 원칙)

이렇게 관리하는 이유는 유지보수의 용이, 쉽게 말하면 손쉬운 확장을 위해서이다.

즉 개방에는 열려 있되, 변경에는 닫혀 있게 코드를 짜는 것이다.(개방-폐쇄 원칙)


📖 오늘의 핵심(다 알기 전까지는 넘어가지 말자❗)

✅ 1. SOLID 원칙 중 단독 책임의 원칙과 그 특징을 안다.

✅ 2. SOLID 원칙 중 개방-폐쇄 원칙과 그 특징을 안다.

✅ 3. SOLID 원칙 중 리스코프 치환의 원칙과 그 특징을 안다.

✅ 4. SOLID 원칙 중 인터페이스 분리의 원칙과 그 특징을 안다.

✅ 5. SOLID 원칙 중 의존 역전의 원칙과 그 특징을 안다.