이 강의에서 얻을 수 있는 것.
- 스프링 기본 기능 학습
- 스프링 본질 깊은 이해
- 객체 지향 설계를 고민하는 개발자로 성장 가능
대상
- 스프링의 핵심 원리를 제대로 이해하고 사용하고 싶은 개발자 (바로 나예요)
옛날에는 EJB (Enterprise Java Bean) 가 대세였고..
거의 종합 선물 세트 였다고 한다..!!
EJB 는 진짜 어렵고 복잡하고 느렸다고 한다..
엄청 분산되어있고.. 인터페이스 설계 다 만들고.. 의존적이고 더러워지고 느리고 등등.. 그랬다고 합니다..
JPA의 탄생을 간략하게 듣고..
2002년 로드 존슨 책이 나오고 EJB 문제점을 언급하고 지금의 스프링 핵심 개념과 기반 코드가 들어가있다고 한다.
스프링은 J2EE(EJB)
겨울을 넘어 새로운 시작이라는 뜻으로 지웠다고 한다. 봄이 왔다는 뜻에서... !!!
스프링 부트는
- 스프링을 편리하게 사용할 수 있도록 지원하며 기본으로 사용되고 있다.
- 단독으로 스프링 애플리케이션을 쉽게 생성하고, Tomcat 같은 웹 서버를 내장하거나 별도 웹 서버를 설치하지 않아도 된다.
- 스프링과 외부 라이브러리 자동 구성해준다. 등
- 오해일 수 있는 것, 스프링 부트는 꼭 스프링 프레임워크를 사용해서 도와주는 것이며 단독으로 사용하는 것이 아니다.
스프링이란 단어는 문맥에 따라 다르게 사용된다고 한다.
- 스프링 DI 컨테이너 기술,
- 스프링 프레임워크,
- 스프링 부트, 스프링 프레임워크 등을 모두 포함한 스프링 생태계
이 기술의 핵심 컨셉은?
스프링의 진짜 핵심은
- 자바가 갖고 있는 객체 지향 언어를 활용해
- 좋은 객체 지향 어플리케이션을 개발할 수 있게 도와주는 프레임워크다.
그렇다면 좋은 객체 지향 프로그래밍이란 뭘까?
설명하기 전에 먼저
객체 지향 프로그래밍이란
- "객체"들로 나누어서 만들며, 객체들 간의 상호작용으로 프로그램을 개발하는 방식
다형성
실세계와 객체 지향을 적용하는 것은 어려운 일이다.
그래도 이해를 위해 실세계와 비교를 해보면
- 여러 자동차를 바꿔탈 수 있어도 운전자의 역할이 바뀌지 않는 것!
- 뮤지컬 배우에서 각자의 역할은 있지만 어떤 사람인지 바뀌어도 상관이 없다! (대본만 있으면 소화할 수 있으니까)
- 이러한 것들이 다형성이라 볼 수 있다.
- 운전자 - 자동차
- 공연 무대
- 키보드, 마우스, 표준 인터페이스들
- 정렬 알고리즘
- 할인 정책 로직 등...
역할과 구현으로 구분하면 세상이 단순해지고, 유연해지며 변경도 편리해진다.
클라이언트는 대상의 역할(인터페이스)만 알면 된다.
클라이언트는 구현 대상의 내부 구조를 몰라도 된다.
클라이언트는 구현 대상의 내부 구조가 변경되어도 대상 자체를 변경해도, 영향을 받지 않는다
혼자 있는 객체는 없다.
- 클라이언트 : 요청
- 서버 : 응답
···
클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있는 것이 다형성의 본질이다.
인터페이스를 안정적으로 설계하는 것이 정말 중요하다.
스프링과 객체 지향
- 스프링은 다형성을 극대화해서 이용할 수 있게 도와준다.
- 스프링에서 이야기하는 제어의 역전(IoC), 의존관계 주입(DI)은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원해준다.
- 또 중요한 것 하나!
- + 좋은 객체 지향 설계의 5가지 원칙 (SOLID)
좋은 객체 지향 설계의 5가지 원칙 (SOLID)
- 클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리
- 단일 책임 원칙 (Single Responsibility Principle, SRP)
- 클래스는 하나의 주요 책임만을 가지며, 그 변경 사유 또한 하나여야 한다.
이렇게 하면 클래스의 역할이 명확해지고 코드 수정 시 다른 기능에 영향을 주지 않아 유지보수가 용이해진다. - 하나의 책임이란 것은 조금 모호하다. (클 수 있고, 작을 수 있으며 문맥과 상황에 따라 다르다.)
- 중요한 기준은 변경이며, 변경이 있을 때 파급 효과가 적다면 단일 책임 원칙을 잘 따른 것이다.
- 클래스는 하나의 주요 책임만을 가지며, 그 변경 사유 또한 하나여야 한다.
- 개방/폐쇄 원칙 (Open/Closed Principle, OCP)
- 기존의 코드를 수정하지 않고도 기능을 확장할 수 있어야 한다. (확장에는 열려 있으나 변경에는 닫혀 있어야 한다.)
- 새로운 기능은 기존 코드를 건드리지 않고도 추가할 수 있어야 하며, 코드의 유연성과 확장성을 높인다.
- 다형성을 잘 활용하면 개방/폐쇄 원칙을 잘 따르는 것이지만 문제점이 있긴 하다. (코드 보면서 이해 됨!)
객체를 생성하고, 연관 관계를 맺어주는 별도의 조립, 설정자가 필요하다. (이러한 것들 때문에 DI가 필요하고 등..그렇다..나중에 더 이해하면서 듣기로..)
- 리스코프 치환 원칙 (Liskov Substitution Principle, LSP)
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위 한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다
- 단순히 컴파일에 성공하는 것을 넘어서는 이야기이다.
- 상속 관계에서 일관성을 유지하고 예상치 못한 동작을 방지할 수 있다.
- 인터페이스 분리 원칙 (Interface Segregation Principle, ISP)
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다
- 자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스 분리
- 인터페이스가 명확해지고, 대체 가능성이 높아진다.
- 의존성 역전 원칙 (Dependency Inversion Principle, DIP)
- 프로그래머는 "추상화에 의존해야 하며, 구체화에 의존하면 안 된다."
- 쉽게 이야기 한다면 구현 클래스 말고 인터페이스에만 의존하라는 뜻이다.
- 앞에서 이야기한 역할(Role)에 의존하게 해야 한다는 것과 같다.
(의존 한다는 것은? 내가 저 코드에 대해 안 다는 것!)
객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다! 구현체에 의존하게 되면 변경이 아주 어려워진다. - 고수준 모듈은 저수준 모듈에 의존하면 안 되며, 양쪽 모두 추상화에 의존해야 한다.
이를 통해 코드의 유연성을 높이고 의존성을 더 효과적으로 관리할 수 있다.
객체 지향의 핵심은 다형성이다.
하지만 다형성 만으로 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.
다형성 만으로는 OCP, DIP를 지킬 수 없기 때문에..
무언가 더 필요하다!
스프링은 다형성 + OCP, DIP를 가능하게 지원한다!
- DI(Dependency Injection): 의존관계, 의존성 주입
-
DI 컨테이너 제공
DI 개념은 말로 설명해도 이해하기가 어렵다. 코드로 짜보면서 필요성을 알게 된다!
다음은 코드를 실습해보면서 학습!
정리
- 모든 설계에 역할과 구현을 분리해야 한다.
- 어플리케이션 설계도 공연을 설계 하듯이 배역만 만들어 두고, 배우는 언제든지 유연하게 변경할 수 있도록 만드는 것
→ 이것이 좋은 객체 지향 설계이다.
- 이상적으로 모든 설계에 인터페이스를 부여해야 한다.
하지만
인터페이스를 도입하면 추상화라는 비용이 발생한다.
기능을 확장할 가능성이 없다면 구체 클레스를 직접 사용하고 나중에 리팩토링을 해서 인터페이스를 도입하는 방법도 있다.
모든 상황에는 장단점이 존재하고
장점이 단점을 넘어설 때, 선택을 해야 한다!
이러한 고민이 항상 필요하고 설계를 하는 것이 중요하다... !!!
'개인 > [java] 스프링 핵심 원리 학습' 카테고리의 다른 글
| AppConfig 리팩터링 (0) | 2023.09.09 |
|---|---|
| 관심사의 분리 (0) | 2023.08.28 |
| 새로운 할인 정책 추가 (객체 지향 원리 적용, 문제점···) (0) | 2023.08.28 |
| 주문과 할인 도메인 설계 (0) | 2023.08.21 |
| 프로젝트 생성, 회원 도메인 설계 (0) | 2023.08.20 |
댓글