스프링의 탄생 배경
스프링이 만들어지기 전 EJB (Enterprise Java Beans)라고 하는 표준 기술이 있었다. EJB는 기업환경의 시스템을 구현하기 위한 서버측 컴포넌트 모델이라고 한다. 이 EJB에는 여러 단점들이 있었는데, 먼저 가격이 아주 비쌌고, 복잡하고 어렵고 느렸다. 개발자들은 EJB에 의존적으로 개발해야 했고 많은 불편함이 있었다고 한다.
이에 로드 존슨이라는 개발자가 2002년에 책을 출간했다. 이 책에서는 EJB의 문제점을 지적하며 현재의 스프링의 핵심 개념과 기반이 되는 코드들이 소개되었다. 이 책은 출간되자마자 큰 인기를 끌었고 일부 개발자들은 이 책의 예제 코드를 프로젝트에 사용하기도 했다. 책이 유명세를 타자 유겐 휠러와 얀 카로프라고 하는 개발자가 로드 존슨에게 오픈소스 프로젝트를 제안했고, 이렇게 탄생하게 된 것이 지금의 스프링이라고 한다.
스프링이 무엇인가?
"스프링" 이라는 단어는 아래와 같이 다양한 맥락에서 사용된다.
- 스프링 DI 컨테이너 기술을 뜻하는 말
- 스프링 프레임워크를 뜻하는 말
- 스프링 프레임워크, 스프링 부트 등을 모두 포함한 스프링 생태계를 뜻하는 말
스프링 프로젝트는 스프링 프레임워크와 스프링 부트를 대표적인 프로젝트로 가지고 있고, 그 외에도 스프링 클라우드, 스프링 데이터, 스프링 배치 등 다양한 프로젝트를 가지고 있다.
스프링 프레임워크
.png)
스프링 프레임워크는 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크로, 동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공한다고 한다. 여기서 모르는 단어가 있는데 뜻을 알아보았다.
- 프레임워크
프레임워크는 소프트웨어 어플리케이션이나 솔루션의 개발을 수월하게 하기 위해 소프트웨어의 구체적 기능들에 해당하는 부분의 설계와 구현을 재사용 가능하도록 협업화된 형태로 제공하는 소프트웨어 환경을 말한다.
즉, 내가 이해하기로 프레임워크는 코드를 수월하게 작성하기 위해서 사용하는 작업 환경이다. 프레임워크 환경에서 개발할 때는 모든 기능을 내가 일일히 다 구현하지 않아도 해당 프레임워크의 규칙을 지켜 코드를 작성하기만 하면 누군가 미리 구현해둔 기능을 끌어와 쉽게 개발을 할 수 있다는 것이다.
그렇다면 스프링 프레임워크란 Java 언어를 사용하는 환경에서 웹 사이트를 만들 때 사용하면 스프링 프레임워크가 제공하는 여러 기능을 사용하여 훨씬 효율적으로 작업을 할 수 있게 만들어주는 소프트웨어라고 볼 수 있는 것 같다. (단, 스프링 프레임워크에서 규정하는 여러 규칙들을 지켜가며 코드를 작성해야 한다.) 또한 스프링 프레임워크는 객체 지향 언어의 특징을 최대로 살릴 수 있도록 해주어서 매우 효과적이라고 한다.
스프링 부트
스프링 부트는 스프링을 편리하게 사용할 수 있도록 지원하는 소프트웨어이며, 최근에는 스프링 프레임워크를 사용할 때 기본으로 사용한다고 한다. 스프링 부트는 그 자체로 단독으로 사용될 수 있는 소프트웨어가 아니고 스프링 프레임워크와 함께 사용되어야 하는 보조 소프트웨어이다.
객체 지향 프로그래밍
객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 모음으로 보는 것이 아니라 여러개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이라고 한다. 각각의 개체는 서로 메세지를 주고받고, 데이터를 처리할 수 있다.
객체 지향 프로그래밍은 프로그램을 유연하고 변경하기 쉽게 만들어주기 때문에 대규모 소프트웨어 개발에 많이 사용된다.
- 객체 지향 프로그래밍의 특징
- 추상화
추상화는 불필요한 부분을 생략하고 객체의 속성들 중에서 가장 필요한 정보들만 간추려 구성하는 것이다. 완전한 시스템을 구축하기에 앞서서 그 시스템과 유사한 모델을 만들어서 테스트 해보기에 적합하고 한다. 그래서 최소 비용으로 실제 상황에 대처가 가능하고 시스템의 구조를 눈으로 볼 수 있다는 특징이 있다.
- 캡슐화
캡슐화는 데이터와 데이터를 처리하는 함수를 하나로 묶는 것을 의미한다. 캡슐화된 객체의 세부 내용은 외부에 은폐되어서 변경 시에 오류가 발생해도 그 파급효과가 크지 않다. 또한 캡슐화된 객체들은 재사용이 용이하고 객체 간에 메세지를 주고받을 때 객체 세부의 내용을 알 필요가 없어 인터페이스가 단순해진다는 특징이 있다.
- 상속성
상속성은 상위 클래스의 모든 속성과 연산을 하위 클래스가 물려받는 것을 이야기한다. 따라서 하위 클래스에서는 상위 클래스의 모든 속성과 연산을 다시 정의하지 않아도 자신의 속성으로 사용할 수 있다. 이러한 특징 덕분에 코드의 재사용성이 좋아진다는 점이 장점이다.
- 다형성
다형성이란 한 가지 형태로 여러 가지의 기능을 수행할 수 있는 것을 말한다. 중요한 개념이기 때문에 아래에서 자세히 다루도록 하겠다.다형성 (polymorphism)
다형성을 이해하기 위해 실생활에서의 예시를 들어보겠다. 람보르기니라는 자동차가 있다고 하자. 우리는 직관적으로 람보르기니 == 자동차 라고 생각한다. 하지만 람보르기니와 자동차를 별개의 것으로 구분하여 인식해보자. 람보르기니라는 "객체"는 자동차라는 "역할"을 구현(수행)하고 있는 것 뿐이다. 운전자(클라이언트)는 자동차 역할을 하는 것이 람보르기니이든, 테슬라이든 상관 없이 운전할 수 있다.
이런 식으로 역할과 구현을 분리해서 바라보는 시각에는 여러 장점이 있다.
- 클라이언트(운전자)는 대상의 역할만 알면 된다.
- 클라이언트(운전자)는 구현 대상(자동차)의 내부 구조를 몰라도 된다.
- 클라이언트(운전자)는 구현 대상(자동차)의 내부 구조가 변경되어도 영향을 받지 않는다.
- 클라이언트(운전자)는 구현 대상(자동차) 자체를 변경해도 영향을 받지 않는다.
위의 내용을 프로그래밍(Java)에 적용시키면
역할 = 인터페이스
구현 = 인터페이스를 구현한 클래스, 구현 객체
라고 할 수 있다.
따라서 프로그래밍을 할 때 역할(인터페이스)을 먼저 만들고, 이후에 그 역할을 수행하는 객체를 만드는 것이 효율적이다. (추상화)
스프링은 이 다형성이라는 특성을 극대화해서 이용할 수 있게 도와주는데, 이 덕분에 기능의 확장이 용이하고 구현을 편리하게 변경할 수 있다. (레고 블럭을 조립하는 것처럼)
좋은 객체 지향 설계의 5가지 원칙 (SOLID)
-
SRP : 단일 책임 원칙
- 한 클래스는 하나의 책임만 가져야 한다.
"하나의 책임" 이라는 것은 명시적으로 정해진 것은 없지만, 대개 한 코드를 변경했을 때 그 파급효과가 적으면 SRP를 잘 지킨 설계라고 볼 수 있다.
-
OCP : 개방-폐쇄 원칙
- 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.
코드의 변경 없이 기능을 확장하기 위해서 다형성을 활용한다. 인터페이스는 그대로 두고 그 인터페이스를 구현한 새로운 클래스를 만들어서 기존 코드의 변경 없이 확장을 할 수 있다.
- 다형성만을 활용해서는 기존의 코드에 아무런 변화도 주지 않고 구현 객체를 변경할 수 없다.(OCP 원칙을 지킬 수 없다.) 이를 보완하기 위해서 스프링을 사용한다.
-
LSP : 리스코프 치환 원칙
- 하위 클래스는 인터페이스 규약을 모두 지켜야 한다는 원칙. 인터페이스를 구현한 구현체를 믿고 사용하기 위해서는 이 원칙을 지켜야 한다. 쉽게 말해서, 자동차의 엑셀을 프로그래밍 하고 있는데 컴파일 오류가 나지 않더라도 엑셀을 밟으면 자동차가 뒤로 가도록 프로그래밍 하면 안된다는 원칙이다.
(강사님이 가장 쉬운 원칙이라고 했는데 이해가 잘 안된다 ㅠㅠ)
-
ISP : 인터페이스 분리 원칙
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
즉, 인터페이스를 최대한 잘게 쪼개서 설계할수록 프로그램의 어느 한 부분을 수정했을 때 그 파급효과가 작아지기 때문에 나눌 수 있는 인터페이스는 최대한 나누라는 원칙인 것 같다. 조금 쉽게 예시를 들자면 주식에서 분산 투자를 하라는 것과 같이 어느 인터페이스를 수정해야 할지 모르니 최대한 분산해놓으라는 말과 비슷한 맥락인 것 같다.
-
DIP : 의존관계 역전 원칙
-
프로그램이 '역할(인터페이스)'에 의존하도록 설계해야지 '구현(클래스)'에 의존하도록 설계하면 안된다는 원칙.
아까 든 자동차의 예시를 다시 들고 오자면, 운전자가 "자동차"라는 큰 범주에 대해 익숙해야 어떤 자동차가 오더라도 운전할 수 있는 반면에, 운전자가 "람보르기니"라는 차량만 운전할 수 있다면 람보르기니 외의 다른 자동차가 주어졌을 때는 운전할 수 없다는 것이다.
-
하지만 기본적으로 다형성만을 활용해서는 DIP 원칙을 철저하게 지킬 수 없다. (클라이언트가 구현 클래스를 직접 선택하기 때문) 따라서 이러한 문제점을 보완하기 위해서 스프링을 사용하는 것이다.
이 내용은 정보를 공유하기 위함이 아닌 저의 개인적인 공부 기록을 남기기 위함입니다. 따라서 틀린 정보가 있을 수 있으니 유의해서 봐주시면 감사하겠습니다.