Spring Framework에서 개발자는 POJO 클래스를 개발하고 스프링 컨테이너는 이 POJO 객체(스프링 빈)를 관리한다.
POJO 객체는 특정 기술에 종속되지 않는 순수 자바 객체를 의미한다. Spring Framework에서는 프레임워크의 메서드가 사용자 클래스에 구현되지 않아 프레임워크 코드와 사용자 코드 간의 결합이 느슨해진다. 개발자가 개발하는 클래스는 프레임워크의 코드와 분리되어 있어 개발자는 비즈니스 로직을 구현하는 데 집중할 수 있다.
객체의 생명 주기를 관리할 책임을 프레임워크(스프링 컨테이너, IoC 컨테이너)에 위임함으로써 개발자가 비즈니스 로직에 집중할 수 있도록 한다.
제어 역전의 방법 중 하나이다. 사용할 객체를 직접 생성하지 않고 외부 컨테이너가 생성한 객체를 주입받아 사용하는 방식이다. 이렇게 하면 클래스 간의 복잡한 관계를 개발자가 직접 관리할 필요가 없게 된다.
스프링에서 의존성 주입을 받는 방법은 다음의 세 가지가 있다.
이중에서 스프링에서 권장하는 의존성 주입 방법은 생성자 주입인데, 그 이유는 다음과 같다.
AOP는 관점을 기준으로 묶어 개발하는 방식을 의미한다. 어떤 기능을 구현할 때 그 기능을 '핵심 기능'과 '부가 기능'으로 구분해 각각을 다른 관점으로 보는 것이다. 스프링은 부가 기능을 핵심 기능과 분리하는 기능을 제공함으로써 코드의 복잡성을 낮추고 재사용성을 높인다.
AOP의 관점이 적용되지 않은 경우, 각 핵심 기능을 수행하는 로직마다 부가 기능을 수행하는 로직이 함께 구현이 되어 있을 것이다. 하지만 부가 기능이 수행해야 하는 로직은 모든 핵심 기능에 공통적으로 적용될 확률이 높기에 코드의 중복이 발생하게 된다.
반면 AOP의 관점에서는 이렇게 반복되는 부가 기능을 하나의 공통 로직으로 처리할 수 있도록 모듈화한다.어떤 핵심 기능이 수행되는지와 무관하게 로직이 수행되기 전 또는 후에 부가 기능이 수행될 수 있도록 하는 것이다. 이렇게 하면 모듈화된 객체를 편하게 적용할 수 있게 되어 개발자가 비즈니스 로직을 구현하는 데에만 집중할 수 있게 된다.
스프링에서는 프록시 패턴(Proxy Pattern)을 통해 AOP 기능을 제공하고 있다.
스프링 프레임워크는 수많은 기능을 일정한 수준의 추상화를 한 클래스로 제공하여 어떤 기능(구현체)를 사용하든지 간에 일관된 방식으로 접근할 수 있도록 한다.
대표적인 예가 트랜잭션 기능이다. 스프링 프레임워크에서는 데이터를 저장하여 객체를 계속 유지할 수 있도록 하는 다양한 영속성 프레임워크를 붙여 사용할 수 있다. 스프링 프레임워크가 RDB의 트랜잭션 기능을 정리한 PlatformTransaction
인터페이스를 제공함으로써 각 영속성 프레임워크에 적합한 구현 클래스를 제공하기 때문이다. 따라서 개발자는 어떤 구현체 혹은 프레임워크를 사용하더라도 추상화되어 있는 PlatformTranscationManager
의 메서드만 사용하면 된다.
스프링 프레임워크는 애플리케이션을 개발할 수 있는 여러 기능을 포함하고 있으며, 기능들을 성격에 따라 분류하여 '모듈'이라는 단위로 관리한다. 개발자는 필요한 모듈들을 조합하여 필요한 기능만 사용할 수 있다.
스프링 프레임워크는 약 20여개의 모듈로 구성되어 있다. 스프링 부트에서는 스프링 프레임워크의 모든 모듈을 기본으로 포함한다.
스프링 프레임워크는 여러 가지 기술과 연동 및 확장할 수 있는 다양한 형태의 프로젝트를 제공한다. 따라서 스프링 프레임워크를 사용하면 확장이 용이한 범용적인 애플리케이션을 만들 수 있다.
스프링 부트는 빠른 개발을 목적으로 '설정보다 관례'라는 패러다임을 채택한 프레임워크이다. 그래서 스프링 부트 프로젝트에서는 가장 보편적으로 많이 사용하는 형태로 스프링 애플리케이션을 미리 설정해 두었다. 직접 설정하는 대신 관례(CoC)에 맞게 코드를 작성하면 미리 설정된 형태로 애플리케이션을 개발할 수 있다.
기존 스프링 프레임워크로 개발할 때는 필요한 라이브러리를 찾고 애플리케이션에 적합한 버전을 선택하며 이를 설정하고 테스트하는 데 많은 시간이 필요했다. 스프링 부트는 컨트리뷰터와 커미터가 이미 적절한 라이브러리를 선택하고 이를 일반적인 형태로 설정하고 테스트까지 완료했기 때문에, 개발자는 그저 사용하기만 하면 되어 시간이 훨씬 단축된다.
모든 스프링 프로젝트는 스프링 프레임워크를 반드시 포함한다. 따라서 위에 작성한 스프링 프레임워크의 특징 역시 스프링 부트에도 적용된다. 그리고 스프링 프레임워크에서 제공하는 모든 기능을 스프링 부트에서도 똑같은 방법으로 사용할 수 있다. 그렇다면 스프링 부트가 추가적으로 제공하는 기능에는 무엇이 있을까?
스프링 부트 프로젝트는 빌드 플러그인을 제공하고, 이를 실행하면 단독 실행이 가능한 JAR 파일을 만들 수 있다. 그리고 java 명령어와 -jar 옵션을 사용하면 간단하게 애플리케이션을 실행할 수 있다. 그래서 전통적인 배포 방법에 비해 매우 간단하고 빠르게 배포할 수 있다는 장점이 있다.
스프링 부트 프로젝트는 기능별로 라이브러리 의존성을 포함한 스타터(starter)를 제공한다. Gradle의 경우, build.gradle에 다음과 같이 의존성을 추가함으로써 사용할 수 있다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
스타터 내부에 라이브러리 의존성 설정이 포함되어 있어 한 줄만 추가하면 기능을 사용하는 데 필요한 모든 라이브러리를 한 번에 추가할 수 있다.
스프링 부트의 모듈인 spring-boot-autoconfigure
가 제공하는 자동 구성 기능은 특정 조건들이 충족되면 미리 설정된 자바 설정 클래스가 동작하고 애플리케이션을 구성할 수 있도록 한다. 자동 구성을 충족하는 특정 조건들은 여러 가지 형태이다. 예를 들어 애플리케이션에 특정 스프링 빈이 있거나 class path에 특정 라이브러리가 포함되어 있거나 환경 설정 값이 있으면 실행되는 방식이다. 그리고 이러한 특정 조건들은 다양하게 조합하여 사용할 수 있다.
스프링 부트를 이용해서 애플리케이션을 개발했다면 기본 모니터링 지표와 헬스 체크 기능을 기본으로 제공한다. 그래서 모니터링 솔루션을 이용해서 각 서버들의 상태와 지표를 수집하기가 매우 쉽다. 이 기능을 제공하는 모듈이 spring-boot-actuator
이다.
스프링 부트의 spring-boot-starter-web
스타터를 이용하여 웹 애플리케이션을 개발한 경우 톰캣이 내장되어 있다. 내장된 WAS 덕분에 앞서 언급한 단독 실행이 가능한 애플리케이션 배포가 가능하다. 톰캣 대신 다른 WAS가 필요하다면 쉽게 교체할 수 있다.
스프링 부트에서 spring-boot-starter-web
스타터를 사용하면 기본적으로 톰캣을 사용하는 스프링 MVC 구조를 기반으로 동작한다.
서블릿은 클라이언트의 요청을 처리하고 결과를 반환하는 자바 웹 프로그래밍 기술이다. 서블릿을 사용하여 웹 페이지를 동적으로 생성할 수 있다. 그리고 이 서블릿이 관리되는 곳이 서블릿 컨테이너이다.
서블릿 컨테이너의 특징은 다음과 같다.
들어온 요청을 가장 먼저 받고, 요청을 적절하게 처리할 컨트롤러를 찾아서 정해주는 역할을 하는 서블릿이다. 다음과 같은 과정을 거쳐 동작한다.