Spring & SpringBoot

좋은 객체지향 설계의 5원칙(SOLID)과 스프링

땅콩콩 2023. 1. 25. 15:04

*인프런 김영한님 강의 [스프링 핵심원리 기본편]을 수강하며 작성한 글입니다.

 

SOLID란?

클린코드로 유명한 로버트 마틴이 좋은 객체지향 설계의 5가지 원칙을 정리한 것.

  • SRP = 단일 책임 원칙 (single responsibility principle)
  • OCP = 개방-폐쇄 원칙 (open/closed principle)
  • LSP = 리스코프 치환 원칙 (liscov substitution principle)
  • ISP = 인터페이스 분리 원칙 (interface segregation principle)
  • DIP = 의존관계 역전 원칙 (dependency inversion principle)

 

SRP, 단일 책임 원칙 (single responsibility principle)

어떤 변경이 있을 때 파급효과가 적으면 단일 책임 원칙을 잘 따른 것이다.
ex) ui변경, 객체의 생성과 사용을 분리.
OCP, 개방-폐쇄 원칙 (open/closed principle) 

확장에는 열려 있으나, 변경에는 닫혀 있어야 한다.
ex) 인터페이스 (역할과 구현의 분리)
그러나 구현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.
즉, 다형성을 사용했지만 OCP원칙을 지킬수 없는 문제점이 생긴다.
이를 해결하기 위해 객체를 생성하고 연관관계를 맺어주는 별도의 조립, 이를 위한 설정자가 필요하다.
여기서 이 별도의 조립을 스프링 컨테이너가 해준다.
LSP, 리스코프 치환 원칙 (liscov substitution principle)

인터페이스를 구현할 때, 프로그램의 정확성을 깨뜨리지 않고 구현체를 만드는 것.
ex) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능, 뒤로 가게 구현하면 LSP 위반! 느리더라도 앞으로 가야 한다.
ISP, 인터페이스 분리 원칙 (interface segregation principle)

특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 낫다.
인터페이스를 여러개로 분리해서 사용하면 인터페이스가 더 명확해지고, 대체 가능성도 높아진다.
ex) 자동차 인터페이스를 운전 인터페이스/ 정비 인터페이스로 분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않는다.
DIP, 의존관계 역전 원칙 (dependency inversion principle)

구현 클래스(구체화)에 의존하지 말고, 인터페이스(추상화)에 의존하라는 뜻.
즉, 클라이언트 코드가 구현 클래스를 바라보지 말고 인터페이스만 바라보게 하라는 것이다.

 

다형성만으로의 한계점

객체지향의 핵심은 다형성이지만, 다형성만으로는 구현 객체를 변셩할 때 클라이언트 코드도 함께 변경되는 등의 사유로 OCP, DIP를 지킬 수 없다.

 

스프링으로 한계점을 극복
  • 스프링은 DI(dependency injection), DI 컨테이너 제공을 통해 OCP, DIP를 가능하게 지원.
  • 클라이언트 코드의 변경 없이 기능 확장이 가능해짐
  • 쉽게 부품을 교체하듯이 개발할 수 있게 됨.

 

정리

모든 설계에 역할과 구현을 분리하자. 애플리케이션 설계도 공연 설계처럼 배역만 만들어두고, 배우는 언제든지 유연하게 변경할 수 있도록 만드는 것이 좋은 객체 지향 설계다. 이상적으로는 모든 설계에 인터페이스를 부여하자.

하지만, 인터페이스를 도입하면 추상화라는 비용 발생...

따라서 기능을 확장할 가능성이 없다면, 구체 클래스를 직접 사용하고,향후 꼭 필요할 때 리팩터링해서 인터페이스를 도입하는 것도 방법이다.