EJB 문제점을 지적 -> 스프링 프레임 워크를 개발하여 스프링이 등장함
스프링 부트 = 스프링 프레임워크를 편리하게 사용하기 위함
스프링 프레임워크가 핵심
스프링 세션, 데이터, 배치, 클라우드 등 여러가지가 있음
단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게 생성
tomcat 같은 웹 서버를 내장 -> 별도 웹서버 설치 필요 없음
스프링과 외부 라이브러리 자동 구성
스프링은 자바 기반 프레임워크
스프링 = 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크
스프링은 객체 지향의 다형성을 극대화하여 이용할 수 있게 도와준다
객체 지향 = 프로그램을 객체의 모임으로 두고, 각 객체는 협력하여 데이터를 처리함
객체지향은 레고 블럭 조립하듯 유연한 변경이 가능하다
역할(인터페이스)과 구현(구현 객체)으로 세상을 구분
구현한 객체 인스턴스를 실행 시점에 유연하게 변경
확장이 가능하므로 인터페이스를 안정적으로 설계하는게 중요하다
아래 예시에서 자동차가 바뀌어도 운전자에게 영향을 주지 않음
운전자를 클라이언트로 생각했을 때, 자동차가 기능이라고 가정하면
기능을 무한히 확장해도 클라이언트에게 영향을 주지 않는다

아래 예시처럼 MemberRepository라는 인터페이스를 구현한 인스턴스를
실행 시점에 변경할 수 있다

로버트 마틴 (클린코드)이 정리한 좋은 객체 지향 설계의 5가지 원칙
한 클래스는 하나의 책임만 가져야한다
책임의 크기는 문맥에 따라 다른데, 이를 적절히 고려하는게 중요하다
하나의 책임 기준 == 변경
변경이 발생할 때 파급이 적으면 SRP를 잘 따른 것
5가지 원칙 중 가장 중요한 원칙
확장에는 열려있으나 변경에는 닫혀있어야한다
새 구현 객체를 만드는 것 = 확장, 이는 기존 코드의 변경이 아님
OCP가 지켜지지 않은 예시
MemberService (인터페이스)와 두 구현 객체 (MemoryMember, JdbcMember)에서 구현 객체를 변경하려면 클라이언트 코드를 변경해야함 => OCP 원칙 지켜지지 않음
해결 방법 = 객체 생성 및 연관 관계를 맺어주는 조립, 설정자가 필요

하위 클래스는 인터페이스 규약을 전부 지켜야함
예시) 자동차 엑셀 인터페이스가 있을 때 이를 구현하는 객체는 뒤로가는 기능일 수 없다. 무조건 앞으로 가는 기능으로 구현
범용되는 인터페이스보다 기능을 잘 쪼개서 타겟이 있는 인터페이스 여러 개를 만드는 것이 낫다
인터페이스가 명확해지고, 대체 가능성이 높아진다
추상화에 의존해야지, 구체화에 의존하면 안된다.
즉 프로그래머는 인터페이스에 의존해야한다 (역할에 의존)
구현 클래스가 어떻든 신경쓰지말고, 인터페이스(역할)를 명확하게 알고 설계해야한다.
구현체에 의존하게 되면, 유연한 변경을 하기 어렵다
위 OCP 예시를 보면 memberService(인터페이스)가 MemoryMemberRepository(구현 객체)에 의존하고 있음 => DI 위반
다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경해야하는 문제점이 있다. 즉 OCP, DIP를 지킬 수 없음
→ 스프링을 통해 다형성 + OCP, DIP를 가능하게 함
스프링의 DI (Dependency Injection) 의존성 주입을 통해, 클라이언트 코드 변경 없이 기능 확장이 가능하다
단점)
실무에서는 모든 곳에 인터페이스를 도입하면, 개발자가 코드를 한 번 더 열어봐야하는 비용이 발생함. 기능 확장의 가능성이 없는 경우에는 구체 클래스를 직접 사용하고 필요한 경우에 리팩토링으로 인터페이스를 도입하는 방법도 있다.