-
Spring Framework란?Java 2021. 9. 10. 22:27반응형
스프링은 2002년 릴리즈되어 JEE(Java Enterprise Edition) 서버를 대체하며 다양한 프로젝트가 추가되며 마이크로서비스, 애플리케이션 등을 만들기 위한 광범위한 기술로 자라났습니다 [1].
이 글에서는 스프링에 대해 아래와 같은 점들을 알아보겠습니다:
- 스프링이란?
- IoC(Inversion of Control)와 DI(Dependency Injection)
- DI 외의 다양한 기능들
- 스프링 프레임워크의 진화 과정
스프링이란?
스프링은 보통 자바 애플리케이션 개발을 위한 경량 프레임워크라고 할수 있는데요. 이 부분에서 2가지 명확히해야할 부분은 아래와 같습니다.
첫 번째는 다른 프레임워크(Apache Struts 등)는 웹 애플리케이션에 제한되는 반면, 스프링은 어떠한 자바 애플리케이션 개발에든 사용될 수 있다는 부분입니다.
두 번째는, 경량이라는 설명은 프레임워크의 크기가 클래스 숫자를 말하는 것이 아니라, 가장 최소한의 영향이라는 관점에서의 스프링의 핵심 철학을 나타낸다는 점입니다. 스프링은 경량인데, 그 점은 스프링 코어가 제공하는 다양한 기능을 사용하기 위해 아주 적은 코드 변경만이 필요하다는 점에서 그러합니다.
IoC(Inversion of Control)와 DI(Dependency Injection)
스프링 프레임워크의 핵심은 제어의 역전(IoC, inversion of control)이라는 개념에 기반합니다. IoC는 컴포넌트 의존성의 생성과 관리를 외부화하는 기술인데요.
클래스 Foo가 Bar라는 클래스의 인스턴스에 의존한다고 할 때, 전통적으로는 Foo는 Bar 인스턴스를 new 연산자로 생성하거나 팩토리 클래스와 같은 곳에서 얻게 됩니다. 이 부분을 IoC 방식으로 접근하면, Bar의 인스턴스는 Foo에게 런타임 시에 어떠한 외부 프로세스에 의해서 주입되게 합니다. 이렇게 의존성을 런타임 시에 주입하는 부분에 있어서, IoC는 마틴 파울러에 의해 추후에 좀 더 특징을 잘 묘사할 수 있는 단어인 DI(Dependency Injection)로 불리게 되었습니다.
스프링의 DI 구현은 자바의 2가지 주요 개념인 JavaBeans와 인터페이스에 기반합니다. 사용자가 스프링을 DI 제공자로 사용한다면, 사용자는 애플리케이션 설정을 위해 스프링이 제공하는 다양한 설정 방식(XML, Java configuraion classes, annotation 등)을 선택적으로 사용할 수 있습니다. JavaBeans(POJOs)는 몇 가지 방법으로 설정가능한 자바 리소스를 생성하는 기본적인 메커니즘을 제공해줍니다(constructor, setter method 등).
인터페이스와 DI는 서로 잘 보완해주는 기술 조합인데요. 명료하게 애플리케이션을 디자인하고 인터페이스로 코딩하는 것은 애플리케이션을 유연하게 만들지만, 인터페이스를 사용해 디자인된 애플리케이션을 잘 엮어내는 것은 매우 복잡하고 개발자에게 추가적인 부담을 지우게 됩니다. 이 부분에서 DI를 사용함으로써, 인터페이스에 기반해 디자인 된 애플리케이션 사용 시 필요한 코드양을 매우 줄일 수 있습니다. 마찬가지로, beans 설정 시 의존성을 만족시키기 위해 여러 인터페이스를 사용할 수 있고 인터페이스를 사용함으로써 DI의 장점을 극대화할 수 있습니다. 이러한 인터페이스를 통해서 스프링은 AOP와 같은 강력한 개념을 제공하기 위해서 JDK dynamic proxy를 이용할 수 있게 되었습니다.
DI의 관점에서, 스프링은 프레임워크보다는 컨테이너와 같이 행동하며 사용자 클래스에 필요한 모든 의존성을 넣어서 인스턴스를 제공해줍니다. DI를 사용하면서 애플리케이션에 가하는 변경은 단순히 JavaBeans에 있는 프로퍼티들을 더 노출하여 더 많은 의존성이 런타임 시에 주입되도록하는 점입니다. 그렇기에 DI는 비교적 적은 침해(less intrusive)로 위의 장점을 제공합니다.
DI 외의 다양한 기능들
Java 9 지원
Java 8의 람다 표현식, 스프링 콜백 인터페이스를 통한 메소드 레퍼런스 등은 스프링 프레임워크 5가 지원하는 다양한 기능들에 기반이 되었습니다. 스프링 5 릴리즈 계획은 원래 Java 9 릴리즈 계획과 맞춰져 있었으나, Java 9 릴리즈가 지연되었지만 스프링 5는 계획된 일정으로 릴리지 되었습니다. 스프링 5.1은 완전히 JDK 9를 받아들였습니다. 스프링 5는 compact strings, ALPN stacks, 새로운 HTTP client 구현체 등의 JDK 9 기능을 사용합니다.
AOP 프로그래밍
Sprint Expression Language
EL(Expression Language)은 애플리케이션이 자바 객체를 런타임 시에 조작할 수 있도록 합니다. 그러나 EL의 문제점은 다른 EL 언어는 다른 문법과 구현을 제공한다는 점인데요. 예로, JSP(Java Server Pages)와 JSF(Java Server Faces)는 각각의 EL을 제공하고 다른 문법을 제공합니다. 이러한 문제를 해결하기 위해, 스프링은 Spring Expression Language를 제공합니다.
Validation
검증은 비지니스 데이터를 포함한 JavaBeans의 attributes를 일관되게 적용할 수 있도록 하는 것이 목적인데요. 이 부분을 달성하기 위해서, 스프링은 Validate 인터페이스를 통해서 검증 API를 제공합니다.
또한, 스프링은 ValidationUtils를 제공하여 빈 스트링 값과 같은 일반적인 검증을 제공하는 다른 validators를 호출할 수 있도록 합니다.
이러한 필요성이 커짐에 따라, JCP 또한 JSR-303(Bean Valiidation)을 개발하여 bean 검증 룰을 정의하는 스탠다드를 확립하려고 하였습니다.
Data Accessing
스프링은 데이터 접근 도구들에 대한 뛰어난 연동 기능을 제공합니다. 추가로 스프링은 플레인 JDBC를 간단한 wrapper API로 제공하여 적절한 대안으로 사용될 수 있도록 해주는데요. JDBC, Hibernate, JDO, JPA 등을 out-of-the-box 형태로 지원합니다.
그러나 최근 몇 년간 NoSQL, Graph 등 다양하고 수많은 저장소가 개발되었습니다. 이러한 수많은 데이터 접근 연동을 관리하기 위해서 스프링은 스프링 Data를 분리된 프로젝트로 만들었습니다.
Object/XML Mapping
애플리케이션에게 흔하게 발생하는 요구사항은 다른 시스템과 데이터를 교환하는 일입니다. 스프링은 가장 흔한 데이터 포맷인 XML을 지원하여 Java-to-XML 매핑을 쉽게 만듭니다.
트랜잭션 관리
스프링은 트랜잭션 관리를 위해 완전한 추상화 레이어를 제공하여 프로그래밍적으로 또는 declarative 트랜잭션 조정이 가능하도록 합니다.
JEE와의 단순화된 연동
스프링과 같은 DI 프레임워크가 널리 받아들여지면서 많은 개발자들이 JEE의 EJB 접근방식을 통해 DI 프레임워크를 사용합니다.
그러나 EJB에 기반해 작성된 애플리케이션이나 JEE 컨테이너에 배포되는 스프링 기반의 애플리케이션을 배포하기 위해서나 애플리케이션 서버의 서비스(Java Transaction API의 트랜잭션 매니저, 데이터 소스 커넥션 풀링 등)를 이용하기 위해서, 스프링은 그러한 기술들을 단순화된 형태로 제공합니다. EJB를 위해서, 스프링은 JNDI 룩업을 수행하기 위해 간단한 declaration을 제공합니다. 반대로, 스프링은 또한 스프링 beans을 EJB에 삽입하기 위한 간단한 annotation을 제공합니다.
MVC
비록 스프링은 데스크톱에서 웹까지 어떠한 세팅에서도 사용될 수 있지만, 웹 시반 애플리케이션을 만들기 위한 풍부한 기능들을 제공합니다. 최근 버젼에서, 스프링은 점진적으로 간단한 웹 프레임워크에서 완전한 MVC 구현체로 진화했습니다.
WebSocket 지원
스프링 프레임워크 4.0에서 시작해서 JSR-356(Java API for WebSocket) 지원이 추가되었습니다. 웹소켓은 클라이언트와 서버 간의 영속적인 커넥션을 생성하기 위한 API를 정의합니다.
Remoting 지원
Java에서 Remote 컴포넌트를 노출하고 반대로 접근하는 것은 간단한 일이 아니었는데요. 스프링을 사용해서 다양한 범위의 remoting 기술들을 이용하여 빠르게 remote 서비스를 만들 수 있습니다. 스프링은 Java Remote Method Invocation(RMI), JAX-WS, Caucho Hessian and Burlap, JSM, Advanced Message Queueing Protocol(AMQP), REST 등 다양한 remote 접근 메커니즘을 지원합니다. 이러한 remoting 프로토콜에 더해서, 스프링은 자바 직렬화에 기반한 HTTP 기반의 invoker도 제공해줍니다.
Mail 지원
다양한 애플리케이션에서 메일을 송신하는 것은 주된 요구사항이기에 메일도 스프링에서 지원하고 있습니다.
Job 스케쥴링 지원
대부분 무게감 있는 애플리케이션들은 특정 종류의 스케쥴링 기능을 요합니다. 스프링은 스케쥴링 지원을 통해서 이러한 애플리케이션에서 발생하는 대다수의 시나리오에 대한 해결책을 제공해주고 있습니다.
Dynamic scripting 지원
JDK 6에서 시작해서, Java는 동적 언어 지원을 도입하였고 이를 통해 사용자는 다른 언어로 작성된 코드를 JVM 환경에서 실행할 수 있게 되었습니다. Groovy, JRuvy, JavaScript 등이 이런 언어에 해당됩니다. 스프링 역시도 동적 스크립트를 스프링 기반의 애플리케이션에서 실행할 수 있도록 지원합니다(Groovy, JRuby, BeanShell).
단순화된 Exception 처리
스프링이 특히 반복적인 코드를 줄여주는 부분은 예외 처리 부분입니다. 이것과 관련한 스프링의 철학은 checked exception이 과도하게 Java에 사용되고 있고 프레임워크가 사용자가 회복할(recover) 수 없는 지점에서 예외 처리를 강제하지 않아야 한다는 것입니다. 실제로, 많은 프레임워크는 checked exception을 처리하는 코드를 적아야만 하는 것에 대한 영향을 최소화하기 위해 디자인 되었습니다.
그러나 이러한 많은 프레임워크들은 checked exception을 고수하며 인위적으로 예외 클래스 수직구조의 granularity를 줄이고 있습니다. 스프링은 개발자가 unchecked exception을 사용하도록 하여 예외 클래스의 수직구조가 granular하도록 해준다는 부분입니다.
스프링 프레임워크의 진화 과정
스프링 프레임워크는 Rod Johnson의 책(2002) 'Expert One-on-One: J2EE Design and Development' [4]에서 기원합니다. 지난 수십년 동안 스프링 프레임워크는 코어의 기능, 관련 프로젝트, 커뮤니티 지원 3가지 부분에서 지속적으로 발전해 왔습니다. 아래에서 최근의 5.0 버젼까지의 발전사를 살펴보며, 구체적으로 어떤 부분이 변경되어 왔는지 알아보겠습니다.
스프링 0.9
책 [4]에 기반한 스프링 프레임워크의 첫 퍼블릭 릴리즈로 bean 설정, AOP 지원, JDBC 추상화, 추상 트랜잭션 지원 등의 기능들이 제공되었습니다.
스프링 1.X
공식 레퍼런스 문서와 같이 릴리즈 된 첫 버젼입니다. 아래와 같은 7개의 모듈로 구성되어 있습니다:
- 스프링 코어: Bean 컨테이너와 지원 유틸리티
- 스프링 컨택스트: ApplicationContext, UI, 검증, JNDI, EJB(Enterprise JavaBeans), remoting, 메일
- 스프링 DAO: 트랜잭션 인프라, JDBC, DAO 지원
- 스프링 ORM: 하이버네이트, iBatis, JDO(Java Data Objects) 지원
- 스프링 AOP: AOP Alliance를 따르는 AOP(Aspect-oriented programming) 구현체
- 스프링 Web: 멀티파트 기능, 서블릿 리스너를 통한 컨택스트 초기화, web-oriented 애플리케이션 컨택스트와 같은 기본적인 연동 기능
- 스프링 Web MVC: 웹 기반 MVC 프레임워크
스프링 2.X
아래 이미지와 같이 6개의 모듈로 구성되어 있습니다. 스프링 컨택스트 모듈은 스프링 코어 모듈로 편입되었고, 스프링 웹 컴포넌트들은 하나로 묶여서 표시되었습니다:
- DTD 포맷 대신 XML 스키마 기반의 손쉬운 XML 설정
- 웹과 포털 사용(요청, 세션, 글로벌 세션)을 위한 새로운 bean scope
- AOP 개발을 위한 @AspectJ annotation 지원
- JPA(Java Persistence API) 추상화 레이어
- 비동기 JMS message-driven POJOs full 지원
- Java 5+ 사용 시, SimpleJdbcTemplate을 포함한 JDBC 단순화
- JDBC 네임드 파라미터 지원
- 스프링 MVC를 위한 Form 태그 라이브러리
- Portlet MVC 프레임워크 도입
- 동적 언어 지원. Beans이 JRuby, Groovy, BeanShell로 작성될 수 있음
- JMX 관련 알림 지원, controllable MBean 등록
- task 스케쥴링을 위해 TaskExecutor 추상화 도입
- Java 5 annotation 지원 (@Transactional, @Required, @AspectJ)
스프링 2.5.X
- 새로운 설정 annotation인 @Autowired와 JSR-250 annotation 지원(@Resource, @PostConstruct, @PreDestroy)
- 새로운 스테레오 타입 annotation: @Component, @Repository, @Service, @Controller
- 스테레오타입 annotation으로 annotated된 클래스들 발견 및 wire를 위한 자동 classpath 스캐닝 지원
- AOP 업데이트: new bean pointcut element와 AspectJ 로드 타임 weaving
- Full WebSphere 트랜잭션 관리 지원
- @RequestsMapping, @RequestParam, @ModelAttribute annotation 추가
- Tiles 2 지원
- JSF 1.2 지원
- JAX-WS 2.0/2.1 지원
- 스프링 TestContext 프레임워크 도입
- JCA 어댑터로 Spring 애플리케이션 컨택스트 배포 기능
스프링 3.0.X
Java 5에 기반한 첫 스프링 버젼으로 Java 5의 generics, varargs과 다른 언어 기능 개선점을 사용하여 디자인 되었습니다. 자바 기반의 @Configuration 모델을 도입하였고, 프레임워크 모듈들은 모듈 Jar 별로 하나의 소스 트리로 분리되 관리되기 위해 아래와 같이 개정되었습니다:
- Java 5 기능 지원
- Callables, Futures, ExecutorService 어댑터에 대한 First-class 지원과 ThreadFactory 연동 \
- 프레임워크 모듈들은 모듈 Jar 당 하나의 소스트리로 분리되어 관리
- SpEL(Spring Expression Language) 도입
- core Java Config 기능과 annotations 연동
- General-purpose type conversion system과 field-formatting system
- 전반적인 REST 지원
- 새로운 MVC XML 네임스페이스와 추가적인 @CookieValue, @RequestHeaders와 같은 annotation
- 검증 강화와 JSR-303(Bean Validation) 지원
- Java EE 6 지원 (@Async, @Asynchronous annotation, JSR-303, JSF 2.0, JPA 2.0 등)
- HSQL, H2, Derby와 같은 임베디드 데이터베이스 지원
스프링 3.1.X
- 새로운 캐시 추상화
- XML을 통한 Bean 정의 프로파일과 @Profile annotation 지원
- 통합 프로퍼티 관리를 위한 환경 추상화
- @ComponentScan, @EnableTransactionManagement, @EnableCaching, @EnableWebMvc, @EnableScheduling, @EnableAsync, @EnableAspectJAutoProxy, @EnableLoadTimeWeaving, @EnableSpringConfigured 와 같은 annotation 지원
- 하이버네이트 4 지원
- @Configuration 클래스와 Bean 정의 프로파일을 위한 TestContext 프레임워크 지원
- 단순화된 생성자 삽입을 위한 c: 네임스페이스 추가
- 서블릿 컨테이너의 서블릿 3의 코드 기반 설정 지원
- persistence.xml 없이도 JPA EntityManagerFactory 부트스트랩 기능
- 스프링 MVC에 Flash와 RedirectAttibutes 추가하여 HTTP 세션을 통해 attibutes이 redirect 후에도 살아남는 것을 가능하게 함
- URI 템플릿 변수 강화
- 스프링 MVC @RequestBody 컨트롤러 메소드 아규먼트에 @Valid, @RequestParam 사용이 가능하도록 함
스프링 3.2.X
- 서블릿 3 기반의 비동기 요청 프로세싱 지원
- 새로운 스프링 MVC 테스트 프레임워크
- 새로운 스프링 MVC annotation: @ControllerAdvice, @MatrixVariable
- RestTemplate과 @RequestBody 아규먼트에 제네릭 타입 지원
- Jackson JSON 2 지원
- Tiles 3 지원
- @RequestBody 또는 @RequestPart 아규먼트에 Errors 아규먼트를 더해 검증 에러 처리가 가능하도록 함
- MVC 네임스페이스와 Java Config 설정 옵션을 통해 URL 패턴 exclude가 가능하도록 함
- Joda Time 없이 @DateTimeFormat 지원
- 글로벌 Date과 time 포매팅
- 프레임워크 간의 동시성 개선, lock을 최소화하고 일반적으로 scoped/prototyped beans의 동시적 생성을 개선함
- GitHub으로 이관: https://github.com/SpringSource/spring-framework
- Java SE 7 / OpenJDK 7 지원 개선. 스프링에 CGLIB과 ASM을 포함함. AspectJ 1.6/1.7 지원
스프링 4.0.X
처음으로 Java 8을 완전하게 지원하는 스프링 릴리즈입니다. 이전 버젼의 자바가 사용될 수 있으나, 최소 요구 버젼이 Java SE 6로 올라갔습니다. 모듈의 구조는 큰 차이 없이 아래와 같습니다:
- www.spring.io/guides 사이트를 통한 Getting Started 가이드 제공
- 스프링 3 버젼에서 deprecated된 패키지와 메소드 제거
- Java 8 지원, 최소 Java 버젼을 6으로 변경
- 스프링 프레임워크 4.0을 위해서 baseline을 Java EE 6 이상으로 변경
- Groovy syntax를 통해 bean 정의가 가능하도록 지원
- 코어 컨테이너, 테스팅, 일반적인 웹 관련 개선
- WebSocket, SockJS, STOMP 메시징
스프링 4.2.X
- 핵심 개선(@AliasFor annotation 추가 및 기존 annotation 변경)
- 하이버네이트 ORM 5.0 지원
- JMS와 웹 개선
- WebSocket 메시징 개선
- 테스팅 개선: @Rollback(false)를 대체하기 위해 @Commit 추가, 스프링 프록시 뒷단에 숨겨진 객체에 접근할 수 있도록 AopTestUtils 유틸리티 클래스 추가
스프링 4.3.X
- 프로그래밍 모델 정리
- MVC와 코어 컨테이너 개선(ASM 5.1, CGLIB 3.2.4, Objenesis 2.4 포함)
- Composed annotation 추가
- 스프링 TestContext 프레임워크의 JUnit 최소 버젼이 4.12로 변경
- 하이버네이트 ORM 5.2, 하이버네이트 밸리데이터 5.3, 톰캣 8.5 및 9.0, Jackson 2.8 등 지원
스프링 5.0.X
Major 릴리즈로 모든 프레임워크 코드베이스가 Java 8에 기반하였고 2016년 7월 이후 Java 9와 호환가능하게 되었습니다.
- Portlet, Velocity, JasperReports, XMLBeans, JDO, Guava, Tiles2, 하이버네이트3 지원 종료
- XML 설정 네임스페이스가 unversioned schemas로 제공됨. version-specific한 설정은 여전히 지원되나 최신 XSD schema로 검증함.
- Java 8 기능을 사용하면서 전반적인 개선
- Resource 추상화가 isFile 표시를 제공하여 defensive getFile 접근을 가능하게 함
- 스프링이 제공하는 Filter 구현체에서 서블릿 3.1 시그니쳐 지원
- Protobuf 3.0 지원
- JMS 2.0+, JPA 2.1+ 지원
- 이벤트 루프 실행 모델 vs 전통적인 커다란 쓰레드 풀을 통한 요청마다 한 개의 쓰레드로 실행하는 모델에서 전자를 지원하기 위한 스프링 Web Flow 도입. 스프링 MVC의 대체제로 reactive foundation에 의해 만들어졌으며, fully 비동기이고 non-blocking임.
- 웹과 코어 모듈에 reactive 프로그래밍 모델을 적용
- 스프링 테스트 모듈 개선. JUnit 5 지원과 Jupiter 프로그래밍과 확장 모델을 지원하기 위해 @SpringJUnitConfig, @SpringJUnitWebConfig, @EnabledIf, @DisabledIf와 같은 annotation 추가
- 스프링 TestContext 프레임워크에서 테스트 병렬 실행 지원
Reference
[1] Pro Spring 5
[2] https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring
[3] https://www.martinfowler.com/articles/injection.html#FormsOfDependencyInjection
[4] Expert One-on-One: J2EE Design and Development
반응형'Java' 카테고리의 다른 글
코틀린, 스프링 기반 마이크로서비스 개발을 위해 읽은 책들 (0) 2022.03.11 Kotlin Coroutines for Backend (0) 2022.02.21 Kotlin Inline modifier의 장점 (0) 2022.01.02 JDBC란? (feat. 데이터베이스 커넥션 풀링) (0) 2021.10.24 서블릿의 세션 관리 (Servlet Session Management) (0) 2021.02.21 아파치 톰캣 내부구조 (Apache Tomcat Internals) (0) 2021.02.17 서블릿(Servlet)의 구조와 접근방식 (feat. CGI) (0) 2021.02.16 웹서버, 앱서버 그리고 CGI (Web & Application Server and CGI) (0) 2021.02.14