본 자료는 김영한님 스프링 핵심 원리 - 기본편을 참고로 제작됐습니다.
1. 스프링의 정의
Spring 이란?
역사짧게
스프링 프레임워크 역사는 Enterprise Java Beans(줄여서 EJB) 사용이 불편해 만들어졌다.
그 시초는 2002년 로드 존슨이 오픈소스인 책을 발간하면서 시작된다.
책에 내용 중 30000 라인 이상의 기반 기술을 예제 코드로 선보였으며,
현재도 지금의 스프링 핵심 개념과 기반 코드가 로드 존슨이 만든 기술이 들어있다.
(BeanFactory, ApplicationContext, POJO, 제어의 역전, 의존관계 주입 등)
이때 Juergen Hoeller(유겐 휠러), Yann Caroff(얀 카로프)가 로드 존슨에게 오픈소스 프로젝트를 제안, J2EE(EJB)라는 겨울을 넘어 새로운 시작이라는 뜻으로 스프링이 제작됐다.
(스프링의 핵심 코드의 상당수는 유겐 휠러가 지금도 개발하고 있다)
-
JAVA의 웹 프레임워크로 JAVA 언어를 기반으로 사용한다.
JAVA로 다양한 어플리케이션을 만들기 위한 프로그래밍 틀이라 할 수 있다.
-
JAVA의 활용도가 높아지면서, JAVA를 이용한 기술이 JSP, Mybatis, JPA 등의 기술이 생겨났다.
Spring은 다른 사람의 코드를 참조하기 쉽고 편리한 구조로
앞서 말한 기술들을 더 쉽게 사용해주는 오픈소스 프레임워크 이다.
스프링의 다양한 기술을 알아보자
1. 스프링프레임워크
스프링의 가장 핵심이 되는 스프링 프레임워크
2. 스프링부트
스프링 프레임워크 여러가지 기술들을 편리하게 사용할 수 있게 해주는 스프링 부트
3. 스프링데이터
관계형 데이터 베이스 CRUD 를 편리하게 사용
4. 스프링 세션
세션 기능을 편리하게 사용
5. 스프링 시큐리티
보안
6. 스프링 Rest Docs
API 문서를 편리하게 사용
7. 스프링 배치
높은 용량을 개인이 하기 힘드니 스프링 배치를 이용해 편리하게 배치
8. 스프링 클라우드
클라우드 관련 기술
등등 다양한 기술이 더 있으나 나는 프레임워크와 부트를 우선적으로 공부할려고 하니, 나머지는 대충만 알아두고 넘어갈려고 한다.
스프링 프레임워크 핵심 기술
- 핵심 기술 : 스프링 DI 컨테이너, AOP, 이벤트, 기타
- 웹 기술 : 스프링 MVC, 스프링 WebFlux
- 데이터 접근 기술 : 트랜잭션, JDBC, ORM 지원, XML 지원
- 기술 통합 : 캐시, 이메일, 원격접근, 스케줄링
- 테스트 : 스프링 기반 테스트 지원
- 언어 : 코틀린, 그루비
- 그외 : 부트, 데이터, 세션, 등등 프레임워크 편리하게 사용
스프링 부트
- 스프링을 편리하게 사용
- 단독으로 실행할 수 있는 스프링 애플리케이션을 쉽게 생성
- Tomcat 같은 웹 서버를 내장해서 별도의 웹 서버를 설치하지 않아도 됨
- 손 쉬운 빌드 구성을 위한 starter 종속성 제공(여러가지 라이브러리를 하나로 묶어서 사용)
- 스프링과 3rd parth(외부) 라이브러리 자동 구성
- 메트릭, 상태 확인, 외부 구성 같은 프로덕션 준비 기능 제공
- 관례에 의한 간결한 설정(필요할때만 따로 설정해서 사용 가능)
스프링이 왜 만들어졌을까?
스프링이 왜 만들어졌을까 라고 물어보면
간단한 답변으로는 좋은 객체 지향 애플리케이션을 개발 할 수 있게 도와주는 프레임워크라고
답변할거 같다.
객체 지향 프로그래밍은 객체들의 모임을 파악, 객체는 메시지와 데이터를 주고받으며 처리할 수 있다.
위의 답변대로 스프링은 자바 언어 기반의 프레임워크이고, 자바는 객체 지향 언어이다.
그렇다면 좋은 객체 지향 프로그래밍이란 무엇일까?
1. 다형성 Polymorphism(컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법)
역할과 구현으로 구분하면 다형성을 이해하기 쉽고 단순해진다.
예를 들어 운전자 역할, 자동차 역할 을 분리하고
각 운전자 와, 자동차에 구현을 넣어서 자동차와 운전자가 바뀌어도 역할은 그대로 이기에
다형성 취지에 적합하고 유연하고 변경에 용이하다
정리
객체 지향 프로그래밍(OOP)
- 객체 지향 프로그래밍(Object Oriented Programming)은 컴퓨터 프로그래밍의 패러다임 중 하나이다.
- OOP 는 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위인 객체들의 모임으로 파악하고자 하는 것이다.
- 각각의 객체는 메시지를 주고받고 데이터를 처리할 수 있다.
- 객체 지향 프로그래밍은 프로그램을 유연하고 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 많이 사용된다.
유연하고 변경에 용이하다?
- 그렇다면, 유연하고 변경이 용이하다는 표현은 어떤 뜻일까? 내가 좋아하는 레고는 매우 유연하고 변경이 용이하다. 블럭(객체)을 조립하여 하나의 레고 완성품을 만드는 것처럼, 프로그래밍에서는 컴포넌트를 유연하게 변경하면서 개발하는 것을 의미한다고 생각한다.
핵심개념은 무엇일까?
- 객체 지향 프로그래밍은 추상화, 상속, 다형성 등이 있으며 추가적으로 다중 상속 등의 특징이 존재한다.
- 그 중 OOP 의 핵심 개념인 다형성(Polymorphism) 에 대하여 알아보겠다.
- 유연하고 변경이 용이한 좋은 객체 지향 프로그래밍을 하기 위해서는 다형성이 매우 중요하다. 왜 다형성이 중요할까?
역할과 구현
- 다형성을 쉽게 이해하기 위해 실세계에 비유하여 생각해보자.
- 자동차에 비유하여 생각해보자. 자동차의 종류는 매우 다양하다. 하지만 운전자는 자동차 사용방법에 대하여 알고 있다면 자동차를 운행하는데 아무런 지장이 없다.
- 자동차(역할)를 생산(구현)한 것이라 생각하면 편하다. 생산(구현)된 자동차는 매우 다양하지만, 그것이 자동차(역할)라는 것은 변함이 없다.
- 역할과 구현을 분리하면 세상이 단순해지고, 유연해지며 변경이 용이해진다.
- 따라서 우리(클라이언트)는 역할(인터페이스)만 알고있으면 구현의 구체적인 내용은 몰라도 상관없다. 역할만 알고있다면 우리는 구현내용이 변경되더라도 클라이언트에게 영향을 미치지 않는다. 마치 자동차의 엔진, 변속기, 제어 등등의 구체적인 자동차 내부구조 내용을 모르더라도 클라이언트는 인터페이스만 알고있다면 자동차를 운전하는데 큰 문제는 없을 것이다.
2. SOLID(좋은 객체 지향 설계의 5가지 원칙)
클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙 정리
1. SRP 단일 책임 원칙
(Single responsibility principle)
- 한 클래스는 하나의 책임만 가진다
- 하나의 책임이라는 것은 모호함
- 클 수 있고, 작을 수 있다
- 문맥과 상황에 따라 다르다
- 중요한 기준은 변경이다, 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것
- 예) UI 변경, 객체의 생성과 사용을 분리
- (하나를 변경할때 다른 부분에서도 여러가지 변경이 진행된다면 그건 단일 책임 원칙을 따르지 못함)
2. OCP 개방 - 폐쇄 원칙(중요***)
(Open/closed principle)
- 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다
- ?????????(추후 수정)
3. LSP 리스코프 치환 원칙
(Liskov substitutuon principle)
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
- 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다(중요). 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다(출발하는 로직 만들었으면 출발만 해라)
4. ISP 인터페이스 분리 원칙
(Interface segregation principle)
- 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다
- 자동차 인터페이스 -> 하위 인터페이스인 운전 관련, 정비 관련 인터페이스로 분리
- 이러면 장점은 자동차만 있을때는 뭐 하나 바꿀때 자동차만 있어 전부 수정해야하는 상황이 발생할 수 있지만, 분리를 하면 정비 관련 문제가 생겼을 때 정비만 수정하고 끝낼 수 있다
- 적당한 인터페이스는 괜찮지만 그렇다고 너무 많은 인터페이스를 만들면 그것도 관리에 도움되지는 않는다.
5. DIP 의존관계 역전 원칙(중요***)
(Dependency inversion principle)
- 추상화에 의존해야지, 구체화에 의존하면 안된다.
- 역할에 의존하게 해야 한다는 것과 같다. 객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 규현체를 변경할 수 있다. 구현체에 의존하게 되면 변경이 아주 어려워 진다.
하지만 SOLID만으로는 그들이 원하는 방향성을 지킬 수 없다(OCP, DIP)
그래서 그걸 해결할 수 있게 기능을 지원해주는
- DI(Dependency Injection): 의존관계, 의존성 주입
프로그램에서 구성 요소의 의존 관계가 소스코드 내부가 아닌 외부의 설정 파일을 통해 정의 되는 방식이다.
코드 간의 재사용을 높이고, 소스코드를 다양한 곳에 사용하며 모듈 간의 결합도를 낮출 수 있다.
대표적으로 라이브러리나 API, 프레임워크를 연동 할 때 연결하는 소스코드를 직접 작성하는게 아닌 외부 파일을 연결해 불러오는 방식이다.
그럼 클라이언트 코드의 변경 없이 기능 확장, 쉽게 교체 하듯 개발 가능
스프링도 이 SOLID를 지키기 위해 만들어졌다고 봐도 된다.
참고 및 학습한 자료
김영한의 스프링 핵심 원리 기본편