서기...(는 아니고) 스프링이 등장하기 전 EJB 라는 자바 기술이 존재했다.
엔터프라이즈 자바빈즈(Enterprise JavaBeans; EJB)
기업환경의 시스템을 구현하기 위한 서버측 컴포넌트 모델이다. 즉, EJB는 애플리케이션의 업무 로직을 가지고 있는 서버 애플리케이션이다. EJB 사양은 Java EE의 자바 API 중 하나로, 주로 웹 시스템에서 JSP는 화면 로직을 처리하고, EJB는 업무 로직을 처리하는 역할을 한다.
출처 : 위키백과
분산 기술을 제공하고 엔티티빈이라는 기술이 존재했지만 비용이 비쌌다. EJB는 너무 복잡하고 어렵고 게다가 속도도 느렸다. 😱 그렇기에 개발자들만 갈려나갔다고 한다 ...
이렇게 EJB의 문제성에 대해 이야기가 나오는 와중에 다른 기술들을 개발해내기 시작했다. 그중에 하나가 바로 로드 존슨이 만들어낸 스프링 이다 !!
객체 지향 프로그래밍 :
여러 개의 독립된 단위, 객체들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
객체 지향의 특징
그 중에서도 다형성이 객체 지향의 진또배기이다.
클라이언트에 영향을 주지 않고 새로운 것 개발 가능하도록 한다. 클라이언트는 새롭게 배우지 않아도 된다는 것이 핵심이다. 그니까 클라이언트는 클라이언트 역할만 그대로 하면 되고 우리는 클라이언트를 바꿀 필요가 없다.
예를 들어 우리는 자동차를 만들때 전체적인 틀은 그대로이고 그 안의 성능만 조금 바꾸어서 기아 차를 만들던지 현대차를 만들던지 전기차를 만들던지 한다. 운전자는 현대차, 기아차, 전기차 마다 운전 방식이 달라지는 것이 아닌 그냥 타는 차의 종류만 바뀌는 것이다. 즉 클라이언트에게 영향을 주지않고 더 다양한 성능을 구현할 수 있다는 것이다.
그러니 우리는 역할과 구현을 분리해야한다. 역할과 구현으로 구분하면 세상이 단순해지고 변경도 편리해진다. ( 역할 = 인터페이스 / 구현 = 클래스, 구현객체 )
자바 언어의 다형성을 활용해 객체를 설계할 때 역할과 구현을 명확히 분리해야한다. 객체 설계 시 인터페이스를 먼저 부여한 뒤, 그 역할을 수행하는 구현 객체를 만들어야 한다. 수 많은 객체인 클라이언트와 객체 서버는 서로 협력 관계를 가진다. 모든 객체들은 협력 관계를 가진다고 생갹해야한다. 자바의 오버라이딩이 다형성의 대표적인 예시이다. 오버라이딩으로 인해 더 다양한 기능을 구현할 수 있기 때문이다.
다형성의 본질
즉 우리는 인터페이스를 안정적으로 잘 설계하는 것이 중요하다고 말할 수 있다.
스프링은 우리가 다형성을 극대화할 수 있도록 도와준다.

출처 : https://wiki.yowu.dev/en/dev/Java/about-solid-principles-oop
SOLID :
로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리한 것이다.
SRP, OCP, LSP, ISP, DIP 가 있다.
한 클래스는 하나의 책임만 가져야한다.
코드를 변경할 때에 파급 효과가 작다면 단일 책임 원칙을 잘 따른 것이다.
ex) UI 변경, 객체 생성과 사용을 분리
소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀 있어야 한다.
인터페이스 구현한 클래스를 새로 만들어 새로운 기능 구현했다고 가정할 때, 기존 코드를 수정한 것은 없다. 새 기능 추가를 위해 클래스만 하나 새로 만든 것이다. 즉 우리는 기능을 확장한 것이지 변경한 것이 아니다.
MemberRepository m = new MemoryMemberRepository(); //기존코드
MemberRepository m = new JdbcMemberRepository(); //변경코드
예를 들어 MemberRepository 라는 인터페이스가 있고 이를 구현한 MemoryMemberRepository()와 JdbcMemberRepository() 클래스가 있다고 해보자, 우리는 구현 객체를 변경하기 위해서는 우리가 클라이언트 코드를 변경해야한다. 하지만 OCP의 원칙이 무엇이었는가. 변경에는 닫혀있다고 했다. 이렇게되면 우리는 OCP 원칙을 어기게 된다. 이를 위해선 객체를 따로 생성하고, 관계를 맺어주는 별도의 조치가 필요하다.
프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다. 즉, 하위 클래스는 인터페이스 규약을 다 지켜야한다는 것이다.
인터페이스를 통틀어 범용적인 것으로 설계하는 것이 아닌 분리해서 인터페이스를 설계하는 것이 효율적이다. 이렇게되면 인터페이스가 명확해지고, 대체 가능성이 높아진다.
예를 들어, 자동차 인터페이스 안에 운전 인터페잇, 정비 인터페이스로 분리되어 존재한다고 하면 정비 인터페이스 자체가 변해도 운전 인터페이스에는 영향을 끼치지 않는다.
구현 클래스에 의존하지 말고, 인터페이스에 의존해야 한다. 즉, 구체적인 것에 의존해야하는 것이 아닌 추상화에 의존해야한다는 것이다. 이렇게 해야 유연하게 구현체를 변경할 수 있다.
하지만 위에 등장했던 코드는 인터페이스에도 의존하지만 구현 클래스에도 의존한다. 이는 OCP 뿐만아니라 DIP도 위반하게 된다.
즉, 다형성만으로는 OCP와 DIP를 지키기 어렵다. 그래서 우리는 스프링이 필요하다.
그래서 대체 스프링이 뭔데요 ?
스프링 :
로드 존슨이 만들었다.
스프링은 자바 언어 기반 프레임워크 (객체 지향)
객체 지향 언어가 가진 장점을 살려내는 프레임워크이다.
스프링은 좋은 객체 지향 어플리케이션을 만들 수 있도록 도와주는 프레임워크이다.
다형성만으로는 지켜지지 않는 OCP와 DIP를 지키기 위해 지원해주는 프레임워크이다.
spring은 이름 그대로 '봄'을 의미한다. EJB라는 추운 겨울이 가고 스프링으로 인해 봄을 맞이했으면 좋겠다고해서 스프링으로 지었다고 한다..

스프링은 지금 화면에 보여지는 것 말고도 더 많은 것들을 제공한다. 우리는 스프링 부트를 통해 스프링 프레임워크를 사용한다.
핵심 기술 : 스프링 DI 컨테이너, AOP, 이벤트 등
웹 기술 : 스프링 MVC, 스프링 WebFlux
데이터 접근 기술 : 트랜잭션, JDBC, ORM 지원, XML 지원
기술 통합 : 캐시, 이메일, 원격 접근, 스케줄링
테스트 : 스프링 기반 테스트 지원
언어 : 코틀린, 그루비
스프링을 편리하게 사용할 수 있도록 지원해준다.
Tomcat 같은 웹 서버를 내장해서 별도 웹 서버를 설치하지 않아도 된다.
starter 종속성 제공한다. (라이브러리 하나만 땡겨도 나머지는 starter가 땡겨줌 )
프로덕션 준비 기능 제공해준다.
우리는 모든 설계에 역할과 구현을 분리하고 모든 설계에 인터페이스를 부여하는게 이상적이다.
하지만 인터페이스를 도입하면 추상화라는 비용이 발생한다고 한다. 기능을 확장할 가능성이 없다면, 구체 클래스를 직접 사용하고, 향후 꼭 필요할 때 리팩터링하여 인터페이스를 도입하는 것도 방법이라고하니 참고해두자!