스프링은 객체지향 설계를 통해 어떤 장점을 가지고 있으며, 왜 객체지향을 선택하게 되었는가
스프링의 탄생까지
- EJB 표준의 유행 - 강력한 분산 지원, 선언적 트랜잭션, Entity bean(ORM) 지원 등... 이론적으로는 고성능
- EJB 표준의 문제점:
- 고비용,
- 높은 복잡성,
- 높은 난이도,
- 코드 가독성 감소
- 낮은 속도
- EJB에 과하게 의존적인 코드 형성
- 개빈 킹, 로드존슨의 등장
- 개빈킹의 하이버네이트
- EJB 엔티티 빈 기술 대체
- 표준 인터페이스인 JPA(Java Persistence API) 등장에 기여. 가장 널리 쓰이는 구현체.
- 로드존슨의 스프링
- EJB 컨테이너 대체
스프링의 역사
2002년, 로드 존슨 - EJB의 문제점을 지적하면서 EJB 없이도 고품질의 확장 가능한 어플리케이션의 개발이 가능함을 제시. 30,000라인 이상의 기반기술을 예제 코드로 선보였다.
이 예제코드를 보고 유겐 휠러, 얀 카로프가 오픈소스 프로젝트를 제안하였으며 스프링(EJB winter 다음)으로 명명.
릴리즈 타임라인
- 스프링 프레임워크 1.0 (xml)
- 스프링 프레임워크 2.0 (xml편의기능)
- 스프링 프레임워크 3.0 (자바 코드로 설정)
- 4.0 - java 8
- spring boot 1.0
- 5.0, boot 2.0리엑티브 프로그래밍 지원
스프링 소개
1. 스프링 생태계
필수
- 스프링 프레임워크 - core
- 스프링부트 - 편리하게 사용하도록 돕는 tool
선택
- 스프링 데이터,
- 스프링 세션,
- 스프링 시큐리티,
- 스프링 rest docs - 문서화와 테스트,
- 스프링 배치 - 데이터 batch처리,
- 스프링 클라우드
- ...
2. 스프링 프레임워크
핵심기술
- 스프링DI 컨테이너, AOP, event, etc.
웹 기술, 데이터 접근 기술, 기술통합, 테스트, 언어(코틀린, groovy)
3. 스프링 부트
- 스프링을 편리하게(단독 사용 불가). 최근에는 기본으로 사용.
- 단독 실행가능한 스프링 어플리케이션 쉽게 생성
- tomcat 등 웹서버 내장. 별도 웹서버 필요x
- 손쉬운 빌드 구성을 위한 starter 종속성 제공 (종속성 관리 용이)
- 스프링과 3rd party 라이브러리 자동 구성
- 메트릭, 상태확인, 외부 구성같은 프로덕션 준비기능 제공
- 관례에 의한 간결한 설정
4. 'Spring' 정의
- 스프링 DI 컨테이너 기술
- 스프링 프레임워크
- 스프링 생태계
스프링의 핵심
- 이 기술을 왜 만들었을까?
- 이 기술의 핵심 concept(개념)은?
- 스프링은 자바 언어 기반의 프레임 워크다.
- 자바는 객체지향 언어다.
- 스프링은 객체지향의 강력한 특징을 활용하는 프레임 워크다.
결론: 스프링 핵심은 좋은 객체 지향 어플리케이션을 개발 할 수 있게 하는 프레임워크다.
1. 객체지향 프로그래밍
- 프로그램을 객체들의 모임으로 파악
- 각 객체는 메시지를 주고받고 데이터를 처리할 수 있다
- 프로그램을 유연하고 변경을 쉽게 만든다
-> 다형성
예시)
운전자와 차량 모델 A,B가 있을 때 A모델에서 B모델로 바꾸어도 운전이 가능하다.
- 즉 운전자(역할)는 차량(역할)이라는 인터페이스에 의존적이다.
2. 역할과 구현의 분리
클라이언트에 영향을 주지않고 새로운 기능을 추가 가능
- 세상이 단순, 유연해지며 변경이 편리해진다.
- 클라이언트는 역할(인터페이스)만 알면 된다.
- 구현 대상의 내부구조를 알 필요가 없다.
- 내부구조가 변경되어도 영향 받지 않는다.
2-1. 객체의 협력?
- 혼자 있는 객체는 없다.
- 클라이언트는 요청, 서버는 응답하는 객체.
- 수많은 객체 클라이언트와 객체 서버들이 관계를 가진다.
2-2. 자바 언어의 다형성
- 구현체에서 오버라이딩 된 메서드의 실행
- 다형성으로 인터페이스를 구현한 객체를 실행시점에 변경 가능
다형성의 본질은 객체간의 협력 개념을 이해함으로서 접근가능하다.
- 다형성은 클라이언트를 변경하지 않고 서버 객체를 변경 가능하다는 것이다.
- 확장 가능한 설계, 클라이언트에 영향을 주지 않는 변경 가능
2-3. 한계
인터페이스(역할) 자체가 변하면 클라이언트와 서버 모두 크게 변경이 필요해지므로 안정적인 인터페이스 설계가 중요해진다.
3. 스프링과 객체 지향
- 스프링은 자바가 제공하는 객체지향적 특징 중 다형성을 극대화해 이용할 수 있게 도와준다.
- 제어의 역전, 의존관계 주입은 다형성을 활용해서 역할과 구현을 편리하게 다룰 수 있도록 지원한다.
3-1. 좋은 객체지향 5원칙: SOLID
로버트 마틴이 정리
- SRP: 단일 책임 원칙 - 하나의 클래스는 하나의 책임만 가져야한다.
- 하나의 책임이란 클수도, 작을 수도, 문맥과 상황에 따라 다를 수 도 있다.
- 기준 = 변경. 변경이 있을 때 파급 효과가 적다면 이 원칙이 지켜진것. 경험적 체득.
- 예시: UI 변경, 객체의 생성과 사용을 분리
- OCP: 개방-폐쇄 원칙 (가장 중요) - 확장에는 열려있고 변경에는 닫혀있어야 함.
- 다형성의 활용: 인터페이스를 구현한 새로운 클래스 -> 새로운 기능의 구현(변경 없는 확장)
- 한계: 구현객체를 변경하려면, 클라이언트 코드 변경 필요
public class MemberService {
private MemberRepository memberRepository = new JdbcMemberRepository();
}
- 돌파: 객체를 생성하고 연관관계를 맺어주는 별도의 조립, 설정자 == IoC컨테이너
- LSP: 리스코프 치환 원칙 - 프로그램 객체는 정확성을 깨트리지 않으면서 하위타입의 인스턴스로 바꿀 수 있어야 한다.
- 하위 클래스는 상위 인터페이스의 규약을 모두 지켜야함
- 컴파일 오류를 넘어서는 수준의 약속으로, 구현체를 신뢰할 수 있는 기반.
- 위반 예시: 자동차 인터페이스:"엑셀==가속기능", 구현체:"엑셀을 감속기능으로 구현"
- 위반 예시: 아빠 클래스를 상속받은 딸 클래스(계층도)
- 올바른 예시: 포유류 클래스를 상속받은 고래 클래스(분류도)
- ISP: 인터페이스 분리 원칙 - 특정 클라이언트를 위한 인터페이스 여러개가 범용 인터페이스 하나보다 좋다.
- 자동차 인터페이스: 운전 인터페이스, 정비 인터페이스 분리
- 사용자 클라이언트: 운전자 클라이언트, 정비사 클라이언트로 분리
- 명확한 인터페이스, 대체 가능성 증가
- DIP: 의존과계 역전 원칙 (가장 중요) - 구체화가 아닌 추상화에 의존하는 방법론
실제로는 구현클래스에도 의존함.
3-2. 결론
- 객체 지향의 핵심은 다형성이나
- 다형성만으로는 클라이언트 코드의 변경을 막을 수 없다.
- 다형성 만으로는 OCP, DIP를 만족 할 수 없다.
정리:
- 모든 설계에 역할과 구현 분리
- 모든 설계에 인터페이스 부여
- 그러나 추상화 비용 발생: 기능을 확장할 가능성이 없다면 구체 클래스를 직접 사용하기도 함.