컴퓨터 프로그래밍에서 SOLID란 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙이다. 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다. SOLID 원칙들은 소프트웨어 작업에서 프로그래머가 소스 코드가 읽기 쉽고 확장하기 쉽게 될 때까지 소프트웨어 소스 코드를 리팩터링하여 스파게티 코드, 에일리언 코드 또는 레거시코드가 되지 않도록 하기 위한 지침이다. 이렇게 설계된 소프트웨어는 재사용이 많아지고, 수정이 최소화되기 때문에 결국 유지 보수가 용이해진다. 물론 처음에 SOILD 원칙에 따라 소스코드를 작성하였어도 지속적으로 추가, 수정 등을 진행하며 리팩터링을 수행하여야 한다.
SOILD는 아래 5가지의 원칙의 첫 글자를 따서 명명되었다.
Single Responsiblity Principle (단일 책임 원칙)
SRP는 소프트웨어의 설계 부품(클래스, 함수 등)은 단 하나의 책임만을 가져야 한다는 원칙이다. 여기서 책임이란, '기능' 정도의 의미로 해석하면 된다. 설계를 잘한 프로그램은 기본적으로 새로운 요구사항과 프로그램 변경에 영향을 받는 부분이 적다. 다시 말해, 응집도는 높고 결합도는 낮은 프로그램을 뜻한다. 만약 한 클래스가 수행할 수 있는 기능, 즉 책임이 많아진다. 책임이 많아지면 클래스 내부의 함수끼리 강한 결합을 발생할 가능성이 높아진다. 이는 유지보수에 비용이 증가하게 되므로 따라서 책임을 분리시킬 필요가 있다. 즉, 클래스의 역할과 책임을 너무 많이 주지 마라는 뜻이다.
Open-Closed Principle (개방-폐쇄 원칙)
OCP는 기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다. OCP에 만족하는 설계를 할 때 변경되는 것이 무엇인지에 초점을 맞춘다. 자주 변경되는 내용은 수정하기 쉽게 설계하고, 변경되지 않아야 하는 것은 수정되는 내용에 영향을 받지 않게 하는 것이 포인트다. 이를 위해 자주 사용되는 문법이 인터페이스(Interface)이다. 자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 한다는 뜻이다.
Liskov Substitution Principle (리스코프 치환 원칙)
LSP는 자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다. 부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야 한다는 원칙이며, 이는 객체 지향 프로그래밍에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스턴스를 사용해도 문제가 없어야 한다는 것을 의미한다.
예시는 아래와 같다.
- 잘못된 상속 관계 : 아버지와 아들 // 아들은 아버지의 한 종류이다
- 올바른 상속 관계 : 포유류와 고래 // 고래는 포유류의 한 종류이다
Interface Segregation Principle (인터페이스 분리 원칙)
ISP는 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다는 것이다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다. 이는 다시 말해서, 자신이 사용하지 않는 기능(인터페이스)에는 영향을 받지 말아야 한다는 의미이다. 코드 작성 시 기능별로 인터페이스를 정의하고 상황에 맞는 메소드만 정의하면 된다.
예를 들어 우리는 스마트폰으로 전화, 웹서핑, 사진 촬영 등 다양한 기능을 사용할 수 있다. 그런데 전화를 할 때에는 웹서핑, 사진 촬영 등 다른 기능은 사용하지 않는다. 따라서 전화 기능과 웹서핑 기능 사진 촬영 기능은 각각 독립된 인터페이스로 구현하여, 서로에게 영향을 받지 않도록 설계해야 한다. 이렇게 설계된 소프트웨어는 인터페이스 분리 원칙을 통해 시스템의 내부 의존성을 약화시켜 리팩터링, 수정, 재배포를 쉽게 할 수 있다.
Dependency Inversion Principle (의존 역전 원칙)
DIP를 만족한다는 것은 의존관계를 맺을 때, 구체적인 클래스보다 인터페이스나 추상 클래스와 관계를 맺는다는 것을 의미한다. DIP를 만족하면 '의존성 주입'이라는 기술로 변화에 유연한 설계를 할 수 있다. 구체적으로 추상 클래스 또는 상위 클래스는 구체적인 구현 클래스 또는 하위 클래스에게 의존적이면 안된다. 구체적인 클래스는 코딩에 있어서 가장 전면적으로 노출되고 사용되기 때문에 변화에 민감하다. 만약 DIP에 의해서 설계하지 않는다면, 구체화된 클래스가 수정될 때마다 상위 클래스나 추상 클래스가 변화해야 하는데 또 그 상위 또 그 상위 계속 연관되어 있는 클래스들이 수정되어야 한다. 따라서 하위 클래스나 구체 클래스에게 의존하면 안 된다. 즉, 그대로 자신보다 변하기 쉬운 것에 의존하지 말라는 뜻이다.
참고 자료
https://dev-momo.tistory.com/entry/SOLID-원칙 [Programming Note]
https://limkydev.tistory.com/77