본문 바로가기

지식/Java

[Spring] 객체지향 설계와 스프링 (SOLID)

- 스프링과 객체지향의 관계

1. 스프링은 자바 언어 기반의 프레임워크입니다. 자바 언어의 가장 큰 특징은 "객체 지향 언어"입니다.

2. 스프링은 객체 지향 언어가 가진 강력한 특징을 잘 살려내는 프레임워크입니다.

3. 스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크입니다.

 

그렇다면.....

- 좋은 객체지향 프로그래밍이란?

객체 지향의 가장 큰 특징은 "다형성" 입니다.

다형성을 구현하기 위해 추상화, 캡슐화, 상속 등 다양한 개념들이 함께 합니다.

 

- 다형성(Polymorphism) :

유연하고 변경이 용이하게 합니다. 

레고 블럭을 조립하듯이, 컴퓨터의 키보드, 마우스를 갈아 끼우듯이 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법입니다.

즉, 역할과 구현으로 세상을 구분하는 방법이라고 생각합니다.

 

ex)

역할 : 자동차

구현 : K5, 아반떼, 니로, 테슬라 등등..

 

 

- 자바에서의 역할과 구현

역할 = 인터페이스 (물론 상속도 가능하지만 인터페이스 권장)

구현 = 인터페이스를 구현한 클래스, 구현 객체

 

이렇게 비유할 수 있습니다.

 

역할과 구현을 구현하는데 있어 핵심은

1. 구현보다 역할을 먼저 만들어야 합니다.

그래야지 한 역할에 집중되지 않고 유연하고 구현이 아닌 역할에 의존할 수 있습니다. (의존관계 역전 원칙)

 

2. 객체의 협력이라는 관계부터 생각해야 합니다.

객체지향 세상에 혼자 있는 객체는 없습니다.

즉, 수많은 객체들은 서로 협력 관계를 가지고 이를 고려하여 구현해야 합니다.

객체를 상태를 보고 행동을 구현하는 것이 아닌 행동을 보고 상태를 구현하여야 합니다.
(자세한 내용은 객체지향의 사실과 오해 책 독서에 설명이 있습니다.)

 

 

- 좋은 객체 지향 설계의 5가지 원칙 (SOLID)

클린코드로 유명한 Robejt C. Martin은 5가지 Software design principles을 정의하였고 앞글자를 따서 SOLID라고 부릅니다.

1. SRP : 단일 책임 원칙

2. OCP : 개방-폐쇄 원칙

3. LSP : 리스코프 치환 원칙

4. ISP : 인터페이스 분리 원칙

5. DIP : 의존관계 역전 원칙

 

1. 단일 책임 원칙 : 한 클래스는 하나의 책임만 가져야한다.

하지만, 하나의 책임이 모호합니다. 클 수도 작을 수도 있습니다. 문맥과 상황에 따라 다릅니다.

중요한 기준은 요구사항의 변경이 있을 때 파급효과가 적으면 단일 책임 원칙을 잘 따랐다고 생각할 수 있습니다.

(ex : UI 변경, 객체의 생성과 사용을 분리)

 

2. 개방-폐쇄 원칙 : 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야한다.

다형성과 연관된 원칙입니다.

위에서 언급하였던 역할과 구현을 잘 분리할 필요성을 알려줍니다.

기존 동작을 변경하지 않고 클래스의 동작을 확장을 목표로 합니다.

 

3. 리스코프 치환 원칙 : 프로그램의 객체는 프로그램의 정확성을 깨트리지 않으면서 하위 인스턴스로 바꿀 수 있어야한다.

다형성을 지원하기 위한 원칙으로 인터페이스를 구현한 구현체를 믿고 사용하려면 이 원칙을 지켜야합니다.

이 원칙은 단순히 컴파일 성공과 관련된 이야기가 아니라,

예를 들어 자동차라는 인터페이스의 엑셀이라는 메소드를 만들고 앞으로 가는 기능이라고 하였는데 이 기능을 뒤로 가는 기능으로 만든 구현체가 있다면 그것은 리스코프 치환 원칙을 위배했다고 할 수 있습니다.

 

4. 인터페이스 분리 원칙 : 사용하지 않는 메소드에 의존해서는 안된다.

큰 범위의 범용 인터페이스보다 특정 클라이언트를 위한 인터페이스를 만드는 것이 낫습니다.

예를 들어 자동차 인터페이스에 K3엑셀 메소드, 아반떼엑셀 메소드 이렇게 따로 메소드가 구현되어 있다면 인터페이스 분리하는 것이 낫습니다.

이렇게 분리하지 않으면 K3엑셀 메소드는 아반떼 객체가 쓰지도 않는데 변경될 경우 재컴파일하여 배포해야되는 문제와 유지보수의 문제도 가져옵니다.

그리고 인터페이스의 크기가 작아져서 갈아끼우기가 쉽고 인터페이스가 하는 일이 명확해져 유지보수에 도움을 줍니다.

 

5. 의존관계 역전 원칙 : 추상화에 의존해야지, 구체화에 의존하면 안된다.

의존선 주입(DI)과 연관된 원칙입니다.

쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻으로도 해석 가능합니다.

즉, 역할에 의존해야지 구현에 의존하면 안됩니다. 자동차 인터페이스가 아닌 K3 구현체에 의존한다면 후에 아반떼 객체, 전기차 객체 등을 추가할 때 변경이 어려워집니다.

 

 

- 결론 : 스프링과 좋은 객체지향 설계의 관계

좋은 객체지향의 원칙을 보면서 순수하게 자바의 기술로는 위의 원칙들을 지키면서 개발하기 너무나 많은 경우들이 생깁니다.

스프링은 의존관계 주입(DI,의존성 주입)과 DI컨테이너를 제공하여 다형성을 지킬 수 있도록 줍니다.