객체지향 설계의 5원칙 SOLID
Intro
면접때 보면 자격요건 혹은 우대사항에서 제일많이 본 말이 있다.
객체지향과 SOLID 라는 단어이다.
이번에는 객체지향의 5가지 설계원칙이라고 불리는 SOLID에 대해서 알아보자
What is SOLID?
SRP(Single Responsibility Principle) : 단일 책임 원칙
OCP(Open Closed Principle) : 개방 폐쇄 원칙
LSP(Liskov Subsitution Principle) : 리스코프 치환 원칙
ISP(Interface Segregation Principle) : 인터페이스 분리 원칙
DIP(Dependency Inversion Principle) : 의존 역전 원칙
SOLID 설계 원칙은 객체지향의 4가지 특징(추상화, 상속, 다형성, 캡슐화)와 더불어, 객체 지향 프로그래밍의 단골 면접 질문 중 하나이다.
또한 디자인 패턴들이 SOLID 설계 원칙에 입각해서 만들어 진 것이기 때문에 표준화 작업에서 부터 아키텍처 설계에 이르기까지 다양하게 적용되는 SOLID 원칙에 대해 확실하게 알아두는게 좋다
본래 좋은 소프트웨어란 변화에 대응을 잘 하는 것을 말한다.
예를 들어 갑자기 고객사에 기획에 없는 추가적인 요청을 하면 비록 욕 한사바리는 할지라도 결국 구현을 해야하는데 이러한 변화에 큰 애로사항없이 잘 대응하기 위해선 소프트웨어 설계 근간이 좋아햐 한다.
좋은설계란 시스템에 새로운 요구사항이나 변경사항이 있을 때 영향을 받는 범위가 적은 구조를 말한다.
그래서 시스템에 예상하지 못한 변경사항이 발생하더라도, 유연하게 대처하고 이후에 확장성이 있는 시스템 구조를 만들 수 있다.
SOLID 객체 지향 원칙을 적용하면 코드를 확장하고 유지보수하기가 더 쉬워지며 불필요한 복잡성을 제거해 리팩토링에 소요되는 시간을 줄임으로써 프로젝트 개발의 생산성을 높일 수 있다.
예를들어
SRP(Single Responsibility Principle) 단일 책임 원칙
- 모든 클래스는 각각 하나의 책임만 가져야 한다
책임 이란?
SRP 에서 이야기하는 책임이란, 기능 정도로 생각하면 된다. 만약 한 클래스가 수행할 수 있는 기능 이 여러 개라면, 클래스 내부의 함수끼리 강한 결합을 발생할 가능성이 높아진다.
응집도는 높고 결합도는 낮은 프로그램을 설계하는 것이 비로소 객체지향 설계의 핵심인데, 이것이 위반되는 것이다.
새로운 요구사항이나 프로그램 변경에 의해 클래스 내부의 동작들이 연쇄적으로 변경되어야 할 수도 있다. 이는 유지보수가 비효율적이므로, 책임을 잘게 쪼개어 분리시킬 필요가 있다.
예를 들어 어떤 클래스 내부에 A 라는 메서드가 있고 이 A 메서드는 A 메서드의 결과를 기반으로 B 메서드를 호출하며 B메서드는 B메서드의 결과를 기반으로 C 메서드를 호출하도록 구현되어 있다고 가정해보자.
이때 만약 A 메서드 동작이 일부 수정된다고 가정해보자 그럼 어떻게 될까?
B와 C 메서드 전부를 바꿔야하는 연쇄적인 상황이 발생할 수 있다.
유지보수가 매우 비효울적인 것이다. 따라서 SRP의 원칙을 생각하면서 코드를 짤 필요가 있다!
OCP(Open Closed Principle) 개방 폐쇄 원칙
- 확장에는 열려있어야 하고, 변경에는 닫혀 있어야 함
- 기능 추가 요청이 생기면 클래스를 확장해 기존 코드를 변경하지 않고 기능을 수정하거나 추가할 수 있도록 설계해야함
확장에 열려있다
새로운 변경 사항이 발생했을 때 유연하게 코드를 추가함으로 큰 힘을 들이지 않고 앱의 기능을 확장할 수 있음
변경에 닫혀있다
새로운 변경 사항이 발상했을 때 객체의 직접적인 수정을 제한함
즉 OCP 은 추상화를 사용한 관계 구축을 권하는 것을 의미한다.
LSP(Liskov Subsitution Principle) 리스코프 치환 원칙
- LSP 원칙은 서브 타입은 언제가 부모 타입으로 교체할 수 있어야 하는 원칙으로 다형성 원리를 이용하기 위한 원칙개념으로 생각하면 된다.
- 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면 업캐스팅 된 상태에서 부모의 메서드를 사용해도 동작이 의도대로 흘러가야 하는 것을 의미한다.
ISP(Interface Segregation Principle) 인터페이스 분리 원칙
- ISP 원칙은 인터페이스를 각각 사용에 맞게끔 잘 분리해야 된다는 설계 원칙
- SRP(단일책임원칙)에서 클래스의 단일 책임을 강조했다면, ISP(인터페이스 분리 원칙)에서는 인터페이스의 단일 책임을 강조한다고 보면된다.
- ISP 원칙은 인터페이스를 사용하는 클라이언트를 기준으로 분리함으로써 클아이언트의 목적과 용도에 적합한 인터페이스 만을 제공하는 것이 목표이다.
- 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 한다.
DIP(Dependency Inversion Principle) : 의존 역전 원칙
- DIP 원칙은 어떤 Class 참조해서 사용해야하는 상황이 생긴다면 그 Class를 직접 참조하는 것이 아니라 그 대상의 상위 요소로 참조하라는 원칙
- 구체적인 클래스에 의존하지 말고 인터페이스나 추상클래스와 의존해서 관계를 맺어라
결론
SRP와 ISP는 객체가 커지는 것을 방지해준다. 객체가 단일 책임을 갖도록 하고 클라이언트마다 특화된 인터페이스를 구현하게 함으로써 한 기능의 변경이 다른 곳 까지 미치는 영향을 최소화 하고, 기능을 추가 및 변경에 용이해 주도록 만들어준다
LSP 와 DIP 는 OCP 를 서포트 한다.
OCP는 자주 변화되는 부분을 추상화 하고 다형성을 이용함으로 써 기능 확장에는 용이하되 기존 코드의 변화에는 보수적이도록 만들어준다. 변화되는 부분을 추상화 할 수 있도록 도와주는 것이 DIP 이고, 다형성 구현을 도와주는 원칙이 LSP 인 것이다.
참고
https://velog.io/@haero_kim/SOLID-%EC%9B%90%EC%B9%99-%EC%96%B4%EB%A0%B5%EC%A7%80-%EC%95%8A%EB%8B%A4