Spring 심화 주차4일차
1. 스프링 기초
1) 스프링의 역사
- EJB : Spring 이전에 사용된 비싼 기술, 어렵고 복잡하고 느렸다.
- EJB 이후에 하이버네이트, EclipseLink 등을 합쳐 JPA 표준 인터페이스가 만들어 졌다
- 2002년 로드 존슨의 책으로 시작, 스프링의 핵심 개념과 기반 코드를 작성
- 이후 유겐 휠러와 얀 카로프가 존슨과 함께 오픈 소스로 개발
2) 스프링 특징
- Spring Framework
- 핵심 기술 : 스프링 DI 컨테이너, AOP, 등등
- 웹기술 : 스프링 MVC, 스프링 WebFlux
- 데이터 접근 기술 : 트랜잭션, JDBC, ORM 지원, XML 지원
- 기술 통합 : 캐시, 이메일, 원격접근, 스케쥴링
- 테스트 : 스프링 기반 테스트 지원
- 언어 : 코틀린, 그루비
- 스프링 부트 : 스프링을 편리하게 사용할 수 있도록 지원, 최근에는 기본으로 사용
- 단독으로 실행할 수 있는 스프링 어플리케이션을 쉽게 생성
- Tomcat 같은 웹 서버를 내장(별도 설치X)
- 손쉬운 빌드 구성을 위한 starter 종속성 제공
- 스프링과 3rd party(외부) 라이브러리 자동 구성
- 메트릭, 상태 확인, 외부 구성 같은 프로덕션 준비 기능 제공
- 관계에 의한 간결한 설정
- 자바 언어 기반의 프레임 워크
- 스프링은 좋은 객체 지향 어플리케이션을 개발할 수 있게 도와주는 프레임워크
3) 객체지향
- 유연하고 변경이 용이하다 > 컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법
- 다형성 : 운전자는 자동차를 운전하지, 특정 자동차 모델만 운전하는게 아니다. 새로운 자동차가 나와도 운전 가능, 즉 클라이언트에 영향을 주지 않고 새로운 기능을 구현할 수 있는 것
- 역할과 구현으로 구분하면 단순해지고, 유현해지며 변경이 편리하다
- 클라이언트는 대상의 역할만 알면된다
- 클라이언트는 구현대상의 내부 구조를 물라도 되고 내부구조가 변경되도 영향을 받지 않는다.
- 클라이언트는 구현 대상 자체를 변경해도 영향을 받지 않는다.
- SOLID : 객체지향 설계의 5가지 원칙 정리
- SRP 단일 책임 원칙 : 중요한 기준은 변경이다. 변경이 있을 때 파급효과가 적으면 해당 원칙을 잘 따른 것
- OCP 개방-폐쇠 원칙 : 요소는 확장에 열려있으나 변경에는 닫혀있어야 한다.
- LSP 리스코프 치환 원칙 : 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것
- ISP 인터페이스 분리 원칙 : 범용 인터페이스 한 개를 인터페이스 여러개로 분리한다.
- DIP 의존관계 역전 원칙 : 구현 클래스에 의존하지말고 인터페이스에 의존
- 다형성 만으로 OCP, DIP를 지킬 수 없다.
- DI와 DI 컨테이너로 가능하게 해준다.
- 기능 확장할 가능성이 없다면 구체 클래스를 직접 사용하고, 향후 필요시 리팩터링 해서 인터페이스를 도입하는 것도 방법이다.
- 애자일 소프트웨어 개발 선언문
우리는 소프트웨어를 개발하고, 또 다른 사람의 개발을 도와주면서 소프트웨어 개발의 더 나은 방법들을 찾아가고 있다.
이 작업을 통해 우리는 다음을 가치 있게 여기게 되었다:
공정과 도구보다 개인과 상호작용을
포괄적인 문서보다 작동하는 소프트웨어를
계약 협상보다 고객과의 협력을
계획을 따르기보다 변화에 대응하기를
가치 있게 여긴다.
이 말은, 왼쪽에 있는 것들도 가치가 있지만, 우리는 오른쪽에 있는 것들에 더 높은 가치를 둔다는 것이다.
4) AppConfig
- 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체 생성과 연결하는 책임을 가지는 별도의 클래스
- 관심사 분리 : 객체를 생성하고 연결하는 역할과 실행하는 역할을 명확히 분리
- AppConfig는 애플리케이션 실제 동작에 필요한 구현 객체를 생성
- AppConfig는 생성한 객체 인스턴스의 참조를 생성자를 통해 주입해준다.
- 이를 통해 serivce에서 의존관계에 대한 고민은 외부에 맡기고 실행에만 집중할 수 있다.
- DIP완성 : service는 repository 추상에만 의존하면 된다. 구현 클래스는 신경 끌 수 있다.
5) IoC, DI, Container
ㄱ.제어의 역전
- 구현 객체가 프로그램의 제어 흐름을 스스로 조종했지만 프로그램에 제어 흐름을 AppConfig로 넘기는 것
- 즉 프로그램의 제어 흐름을 직접 제어하는 것이 아닌 외부에서 관리하는 것
- 프레임워크가 내가 작성한 코드를 제어하고, 대신 실행하면 그것은 프레임워크가 맞다
- 반면 내가 작성한 코드가 제어의 흐름을 담당하면 그것은 라이브러리다.
ㄴ.의존관계 주입(DI)
- 실제 어떤 구현 객체가 사용될지는 모른다.
- 의존관계는 정적인 클래스 의존 관계와, 실행 시점에 결정되는 동적인 객체(인스턴스) 의존 관계 둘을 분리해서 생각해야한다.
- 정적인 의존 관계 : 애플리케이션을 실행하지 않아도 분석할 수 있다.
- 동적인 의존 관계 : 애플리케이션 실행 시점에 실제로 생성된 객체 인스턴스의 참조가 연결된 의존 관계
- DI를 통해 client 코드 변경을 안하고 client가 호출하는 대상의 타입 인스턴스를 변경 가능
- 정적인 클래스 의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경 가능
ㄷ.IoC컨테이너 와 DI 컨테이너
- AppConfig 처럼 객체를 생성하고 관리하면서 의존관계를 연결해주는 것을 말한다.
- 의존관계 주입에 초점을 맞추어 최근에 DI컨테이너라고 부른것이다.
ㄹ. 스프링 컨테이너
- ApplicationContext를 스프링 컨테이너라 한다.
- 기존에는 AppConfig를 사용해 직접 객체를 생성하고 DI했지만, 이제 스프링컨테이너를 통해서 한다.
- 스프링 컨테이너는 @Configuration 이 붙은 AppConfig 를 설정(구성) 정보로 사용한다. 여기서 @Bean
이라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. 이렇게 스프링 컨테이너에
등록된 객체를 스프링 빈이라 한다. - 스프링 빈은 @Bean 이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다.
- 이전에는 개발자가 필요한 객체를 AppConfig 를 사용해서 직접 조회했지만, 이제부터는 스프링
컨테이너를 통해서 필요한 스프링 빈(객체)를 찾아야 한다. 스프링 빈은 applicationContext.getBean() 메서드를 사용해서 찾을 수 있다. - 기존에는 개발자가 직접 자바코드로 모든 것을 했다면 이제부터는 스프링 컨테이너에 객체를 스프링 빈으로
등록하고, 스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다. - 코드가 더 길어진 것 같은데, 스프링 컨테이너의 장점은?
- 싱글톤을 유지해준다. > 추후 학습을 통해 더 자세히 알아보자
2. 참고자료
1) 더티체킹 : https://github.com/gyoogle/tech-interview-for-developer/blob/master/Web/Spring/%5BSpring%20Data%20JPA%5D%20%EB%8D%94%ED%8B%B0%20%EC%B2%B4%ED%82%B9%20(Dirty%20Checking).md