본문 바로가기

Spring

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

 객체지향 설계와 스프링에 대해 정리하겠다.

 

 스프링의 핵심 가치는 좋은 객체지향(SOLID)이다.

 

스프링이란? 

 

 스프링이란 단어는 

1. DI 컨테이너 기술

2. 스프링 프레임워크

3. 스프링 부트, 스프링 프레임 워크를 다 포함한 스프링 프레임워크 생태계

등 문맥에 따라 다르게 사용된다.

 

 스프링을 왜 만들었을까?

 

 스프링의 핵심 개념(핵심 컨셉)은

1. 자바 언어 기반의 프레임 워크

2. 자바의 핵심 - 객체 지향 언어

3. 객체 지향 언어의 강력한 특징을 살려내는 프레임 워크

이다. 

 

 Spring 이전에는 EJB라는 것을 이용해 개발을 했는데 EJB를 사용하면 EJB에 너무 의존적이고 코드가 더러워져

객체지향과는 멀어진 개발을 하게 됐기 때문에 스프링이 만들어졌다.

 

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

 

 좋은 객체지향 프로그래밍이란 객체가 메세지를 주고 받으며 협력하고 유연하며 변경이 용이한 상태를 의미한다.

연극에 대본과 무대가 정해져 있고 필요한 배우만 변경해서 투입시키면 되는 상태를 예로 들 수 있다.

 

 위에서 언급한 유연하며 변경이 용이한 상태를 다형성이라고 할 수 있다.

 

 세상을 역할(인터페이스)구현(객체)으로 구분짓는 것이 좋은 객체지향 프로그래밍으로 가는 길이다.

 

역할과 구현을 분리

 

 역할과 구현으로 구분하면 우리가 사는 복잡한 세상이 단순, 유연, 변경에 용이해진다.

우리에게 요청을 보내는 클라이언트는 원하는 대상의 역할(인터페이스)만 알면 된다. 그 안에 어떤 내용이 들어있는지는  내부 구조가 어떤지는 알 필요가 없다. 자동차로 예를 들면 현대차든 기아차든 어떤 회사의 어떤 차종이 오는 지는 상관 없고 그저 '운전을 한다'라는 역할만 알고 있다면 상관이 없는 것이다. 

 

 역할 = 인터페이스

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

 

 구현보다 인터페이스가 더 먼저다. 즉, 역할이 먼저다.

 

역할과 구현의 한계

 

 역할(인터페이스)이 변한다면 다 변화가 필요하다. 예를 들어 연극의 대본이 바뀐다면? 혹은 자동차가 비행기로 바뀐다면? 과 같이 역할 자체가 변하는 경우에 대응하기 어렵다. 때문에 인터페이스를 안정적으로 잘 설계하는 것이 매우 중요하다.

 

스프링과 객체지향

 

 다형성이 가장 중요한 개념이다. 스프링은 다형성을 극대화해서 이용할 수 있게 도와준다. 여러 특징들이 있는데 그 특징들로 역할과 구현으로 나눠 개발하는데 도움을 준다.

 

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

 

 1. SRP(single responsibility principle) : 단일 책임 원칙

한 클래스는  하나의 책임만 가져야 한다는 원칙

 

 2. OCP(open/closed principle) : 개방-폐쇄 원칙

확장에는 열려있으나 변경에는 닫혀 있어야 한다는 원칙

다형성을 활용하면 된다.

 

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

자동차로 예를 들면 자동차라는 인터페이스의 구현체가 있어야 하고, 그 구현체 중엔 엑셀이라는 기능이 있을텐데 엑셀은 무조건 앞으로 가게 하는 규칙이 있어야 한다는 개념이라고 생각하면 된다. (엑셀은 뒤로 가는 기능이 되어서는 안된다.)

 

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

자동차에는 운전, 정비 등 다양한 역할이 필요하다. 자동차 안에 필요한 이 역할을 운전 인터페이스, 정비 인터페이스와 같이 두 개의 인터페이스로 분리하는 것이다. 추후에 변경이 용이해진다.

 

 5. DIP 의존관계 역전 원칙 

프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다.

MemberService와 MemberRepository의 의존관계

MemberService가 MemberRepository를 바라봐야지 그 아래 구현체인 MemoryMemberRepository나 DBMemberRepository를 바라봐선 안된다는 뜻이다. 역할과 구현을 철저히 분리하는 것이다. 역할에 의존해야지 구현에 의존하면 안된다. (의존한다는 것은 그 구현 코드를 안다는 뜻이다.)

 

정리

 

  • 객체지향의 핵심은 다형성
  • 하지만 다형성만으로는 OCP, DIP를 지킬 수 없음. 뭔가가 더 필요
  • 스프링은 다형성 + OCP, DIP가 가능하게 해줌 (DI와 DI 컨테이너로)
  • 모든 설계에 역할과 구현을 분리해야 함 (대본을 만들고 배우는 언제든 교체 가능하도록)
  • 이상적인 것은 모든 설계에 인터페이스를 부여하는 것이나 실무적으로 너무 많은 추상화 비용은 부담임
  • 기능을 확장할 가능성이 없다고 판단되면 구체 클래스를 직접 사용하고 이후 필요할 때 리팩터링 하는 것도 방법임
  • 이걸 잘 하는 것이 좋은 개발자다..