1. 스프링 프레임워크란?
스프링 프레임워크를 정의하기 쉽지 않다.
중요하게 생각하는 것이 다양하기 때문이다.
- IoC/DI, AOP, PSA를 제공해주는 프레임워크
- IoC Container를 기반으로 객체지향 설계를 도와주는 프레임워크
- 빈의 생명주기와 주입 등을 제공해주는 프레임워크
- POJO를 도와주는 툴
2. 스프링 프레임워크 정의
스프링의 핵심 개발자들이 함께 쓴 Professional Spring Framework
에서
스프링은 엔터프라이즈 서비스 기능을 POJO에 제공하는 것 이라고 정의했고
가장 잘 알려진 정의는 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크이다.
2-1) 애플리케이션 프레임워크
일반적으로 라이브러리나 프레임워크는 특정 업무 분야나 한 가지 기술에 특화된 목표를 가지고 만들어진다.
예) 관계형 DB와 자바 객체를 매칭해주는 ORM 기술을 제공하는 JPA
그래서 프레임워크는 애플리케이션의 특정 계층에서 주로 동작하는 한 가지 기술 분야에 집중된다.
그러나 스프링은 애플리케이션 프레임워크라는 특징을 가지고 있다.
애플리케이션 프레임워크는 특정 계층이나 기술, 업무 분야에 국한되지 않고
애플리케이션 전 영역을 포괄하는 범용적인 프레임워크를 의미한다.
애플리케이션 프레임워크는 애플리케이션 개발의 전 과정을 빠르고 편리하며 효율적으로 진행하는데 일차적인 목표를 둔 프레임워크다.
여러 계층의 다양한 기술을 한 곳에 모아뒀다고 해서 애플리케이션 프레임워크라고 할 수 없다.
애플리케이션의 전 영역을 관통하는 일관된 프로그래밍 모델과 핵심 기술을 바탕으로
각 분야의 특정에 맞는 필요를 채워주고 있기 때문에 애플리케이션을 빠르고 효과적으로 개발할 수 있는 것이다.
MVC 프레임워크, JDBC/ORM 지원 프레임워크, IoC/DI 프레임워크, AOP 툴이라고 보는 이유는 스프링이 제공하는 핵심 기술에만 주목했기 때문이다.
스프링의 일차적인 존재 목적은 핵심 기술에 담긴 프로그래밍 모델을 일관되게 적용해서
애플리케이션 전 계층과 전 영역에 전략과 기능을 제공해줌으로써
애플리케이션을 편리하게 개발하게 해주는 애플리케이션 프레임워크로 사용되는 것이다.
2-2) 경량급 (lightweight)
스프링 자체가 가볍다거나 작은 규모의 코드로 이뤄졌다는 뜻은 아니다.
스프링은 여러 모듈로 세분화되고 수십만 라인의 코드를 가진 복잡하고 큰 규모의 프레임워크다.
경량급이라는 표현은 불필요하게 무겁지 않다는 의미다.
스프링 이전의 EJB 같은 과도한 엔지니어링이 적용된 기술과 대비시켜 설명하기 위한 표현이다.
EJB가 동작하려면 고가의 느리고 무거운 자바 서버(was)가 필요했다.
설정 파일 구조, 패키징이 난해하고 서버 배치도 불편하다는 부담이 있다.
그에 비해 스프링은 가장 단순한 서버 환경인 톰캣이나 제티에서도 완벽하게 동작한다.
단순한 개발툴과 기본적인 개발 환경으로도 엔터프라이즈 개발에서 필요로 하는 주요한 기능을 갖춘 애플리케이션을 개발하기에 충분하다.
2-3) 자바 엔터프라이즈 개발을 편하게
스프링은 근본적인 부분에서 엔터프라이즈 개발의 복잡함을 제거해내고 진정으로 개발을 편하게 해주는 해결책을 제시한다.
스프링이라는 프레임워크가 제공하는 기술이 아니라 개발자가 작성하는 애플리케이션 로직에 더 많은 관심과 시간을 쏟게 해준다.
3. 스프링의 목적
경량급 프레임워크를 이용해서 엔터프라이즈 애플리케이션 개발을 편하게
하는 것이 스프링의 정의였다.
그렇다면 스프링을 사용해서 엔터프라이즈 개발을 편하게 하려는 이유는 뭘까?
❗️️ 엔터프라이즈 개발이 편하기 않기 때문이다.
엔터프라이즈 시스템이란? 서버에서 동작하며 기업과 조직의 업무를 처리해주는 시스템
3-1) 엔터프라이즈 개발의 복잡함
이유1: 기술적인 제약과 요구사항이 늘어났기 때문이다.
엔터프라이즈 시스템은 많은 사용자의 요청을 동시에 처리해야 하기 때문에
서버의 자원을 효율적으로 공유하고 분배해서 사용할 수 있어야 한다.
중요한 기업의 핵심 정보를 처리하거나 금융, 국방 등의 시스템을 다루기도 하기 때문에
보안성과 안정성, 확장성 면에서도 뛰어나야 한다.
타 시스템과의 연계 / 클라이언트와의 접속을 위한 리모팅 기술,
트랜잭션을 하나로 묶어서 사용하는 분산 트랜잭션의 지원도 필요하다.
이유2: 엔터프라이즈 애플리케이션이 구현해야 할 핵심기능인 비즈니스 로직의 복잡함이 증가하기 때문이다.
점차 대부분의 업무를 컴퓨터 없이 처리하기 힘들 정도로 엔터프라이즈 시스템에 대한 업무 의존도가 높어졌다.
다양하고 복잡한 업무 처리 기능을 엔터프라이즈 시스템이 구현해야 한다는 뜻이다.
이유3: 복잡함을 증가시키는 원인
비즈니스 로직과 엔터프라이즈 기술이라는 두 가지 복잡함이 얽혀있기 때문이다.
3-2) 복잡함 해결 ?
엔터프라이즈 개발에 나타나는 복잡함의 원인은 제거 대상이 아니다.
대신 복잡함을 효과적으로 상대할 수 있는 전략과 기법이 필요하다.
문제는 비즈니스 로직의 복잡함을 효과적으로 다루기 위한 방법과 기술적인 복잡함을 처리하는데 적용되는 방법이 다르다.
해결책1: 실패한 EJB
EJB의 기본 전략도 이 두 가지 종류의 복잡함을 분리하는 것이다.
애플리케이션 로직을 담은 핵심 코드에서 일부 기술적인 코드가 제거된 건 사실이지만
오히려 EJB라는 환경과 스펙에 종속되는 코드로 만들어져야 하는 더 큰 부담을 안게 되었다.
- EJB라는 틀 안에서 자바 코드를 만들게 강제한다.
- 특정 클래스를 상속하게 함으로써 더 이상 상속 구조를 적용하지 못하게 만들어 다형성 적용을 근본적으로 제한한다.
해결책2: 비침투적인 방식을 통한 효과적인 해결책 Spring
EJB 처럼 어떤 기술을 적용했을 때 기술과 관련된 코드나 규약이 코드에 등작하는 경우 침투적인 기술이라고 한다.
스프링을 이용하면 기술적인 복잡함과 비즈니스 로직을 다루는 코드를 깔끔하게 분리할 수 있다.
중요한 것은 그 과정에서 스프링 스스로가 애플리케이션 코드에 불필요하게 나타나지 않게 하는 것이다.
3-3) 복잡함을 상대하는 스프링의 전략
스프링의 기본적인 전략은 비즈니스 로직을 담은 애플리케이션 코드와 엔터프라이즈 기술을 처리하는 코드를 분리시키는 것이다.
기술적 복잡함을 상대하는 전략
기술적인 복잡함을 분리해서 생각하면 효과적인 전략을 발견할 수 있다.
문제1: 기술에 대한 접근 방식이 일관성이 없고, 특정 환경에 종속적이다.
일관성 없는 기술과 서버 환경에 대한 스프링의 공략 방법은 바로 서비스 추상화이다.
앞서 얘기했던 트랜잭션 추상화나 OXM 추상화, 데이터 액세스 기술에 독립적으로 적용 가능한 트랜잭션 동기화 기법 등이 대표적인 예이다.
기술적인 복잡함은 일단 추상화를 통해 로우 레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리하고,
환경과 세부 기술에 독립적인 접근 인터페이스를 제공하는 것이 가장 좋은 해결책이다.
예) JavaMail 자바 메일은 테스트 작성이 어려운데 표준 기술이다. 이 경우 서비스 추상화를 적용할 필요가 있다.
서비스 추상화를 통해 테스트 편의성을 증대시키고 기술에 대한 세부 설정과 환경으로부터 독립적인 코드를 만들 수 있다.
문제2: 기술적인 처리를 담당하는 코드가 성격이 다른 코드에 섞여서 등장한다.
비즈니스 로직 전후로 경계가 설정되어야 하는 트랜잭션, 보안 적용, 로깅 기능 등이 대표적인 예이다.
책임에 따라 계층을 분리하고 그 사이에 서로의 기술과 특성에 의존적인 인터페이스나 예외처리 등을 최대한 제거한다고 할지라도 근본적인 엔터프라이즈 서비스를 적용하는 한 이런 문제를 쉽게 해결할 수 없다.
▶️ 이런 복잡함을 해결하기 위한 스프링의 접근 방법은 AOP다.
AOP는 기술을 다루는 코드로 인한 복잡함을 기술 그 자체 이상으로 불필요하게 증대되지 않도록 도와주는 가장 강력한 수단이다.
비즈니스와 애플리케이션 로직의 복잡함을 상대하는 전략
비즈니스 로직의 복잡함을 상대하는 전략은 자바라는 객체지향 기술 그 자체이다.
스프링은 객체지향 언어의 장점을 제대로 살리지 못하게 방해했던 요소를 제거하도록 도와주는 것이다.
핵심 도구: 객체지향과 DI
기술과 비즈니스 로직의 복잡함을 해결하는 데 스프링이 공통적으로 사용하는 도구는 객체지향이다.
자바 엔터프라이즈 기술의 가장 큰 장점은 객체지향 설계를 가능하게 해주는 자바 언어이다.
EJB는 자바의 개게지향 장점을 취하지 못하게 한다.
스프링의 목적은 결국 “기본으로 돌아가자” 이다.
자바의 기본인 객체지향에 충실한 설계가 가능하도록 단순한 오브젝트로 개발할 수 있고,
객체지향의 설계 기법을 잘 적용할 수 있는 구조를 만들기 위해 DI 같은 유용한 기술을 편하게 적용하도록 도와주는 것이 스프링의 기본 전략이다.
서비스 추상화, 템플릿/콜백, AOP와 같은 스프링의 기술은 DI 없이는 존재할 수 없다.
4. POJO 프로그래밍
조금 더 기술적으로 스프링이 지향하는 목적이 무엇인지 알아보자.
<Professional Spring Framework>
에서 스프링의 정수는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것이라고 나와있다.
엔터프라이즈 서비스 기능을 POJO에 제공한다는 말은
엔터프라이즈 서비스 기술과 POJO라는 애플리케이션 로직을 담은 코드를 분리했다는 뜻이다.
분리됐지만 반드시 필요한 엔터프라이즈 서비스 기술을 POJO 방식으로 개발된 애플리케이션 핵심 로직을 담은 코드에 제공한다는 것이 스프링의 가장 강력한 특징과 목표다.
4-1) 스프링의 핵심: POJO
DI의 기본 아이디어는 유연하게 확장 가능한 오브젝트를 만들어두고 그 관계는 외부에서 다이나믹하게 설정해준다는 것이다.
이런 DI의 개념을 애플리케이션 전반에 걸쳐 적용하는 것이 스프링의 프로그래밍 모델이다.
스프링의 주요 기술인 IoC/DI, AOP, PSA는 애플리케이션을 POJO로 개발할 수 있게 해주는 기능 기술이라고 불린다.
POJO란?
POJO는 plain old java object의 약자이다.
POJO의 조건
그냥 평범한 자바 오브젝트라고 할 수 있지만 좀 더 명확하게 정의하면
다음 세 가지 조건을 충족해야 한다.
(1) 특정 규약에 종속되지 않는다.
POJO는 자바 언어와 꼭 필요한 API외에 종속되지 않아야 한다.
따라서 EJB2와 같이 특정 규약을 따라 비즈니스 컴포넌트를 만들어야 하는 경우는 POJO가 아니다.
자바는 단일 상속 제한 때문에 특정 클래스를 상속해서 만들어야 하는 규약이 있는 경우 객체지향적인 설계 기법을 적용하기 어려워지고 규약이 적용된 환경에 종속적이 되면 다른 환경으로 이전이 힘들다는 문제가 발생한다.
(2) 특정 환경에 종속되지 않는다.
특정 환경에 종속되어야 하는 오브젝트도 POJO라고 할 수 없다.
특히 비즈니스 로직을 담고 있는 POJO 클래스는 웹이라는 환경정보나 웹 기술을 담고 있는 클래스나 인터페이스를 사용해서는 안된다.
나중에 웹 컨트롤러와 연결돼서 사용될 것이 뻔하더라도 직접적으로 웹이라는 환경으로 제한해버리는 오브젝트나 API에 의존해서는 안된다.
이렇게되면 웹 외의 클라이언트가 사용하지 못하게 된다. 또한 웹 서버에 올리지 않고 독립적인 테스트도 힘들어진다.
비즈니스 로직을 담은 코드에 HttpServletRequest나 HttpSession, 캐시와 관련된 API가 등장하거나 웹 프레임워크의 클래스를 직접 이용하는 부분이 있다면 그것은 진정한 POJO라고 볼 수 없다.
요즘은 소스코드에 직접 메타 정보를 추가해주는 어노테이션을 많이 사용한다.
그렇다면 어노테이션을 사용하는 경우 POJO라고 할 수 있을까?
어노테이션이 단지 코드로 표현하기 적절치 않은 부가적인 정보를 담고 있고,
그래서 환경에 종속되지 않는다면 여전히 POJO라고 할 수 있다.
하지만 특정 기술과 환경에 종속적인 정보를 담고 있다면 POJO로서의 가치를 잃어버린다고 할 수 있다.
그렇다면 특정 기술 규약과 환경에 종속되지 않으면 모두 POJO라고 할 수 있을까?
자바 클래스를 써서 개발했다고 POJO 방식으로 개발했다고 할 수는 없다.
POJO는 객체지향적인 자바 언어의 기분에 충실하게 만들어져야 하기 때문이다.
POJO는 객체지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 말한다.
그런 POJO에 애플리케이션의 핵심 로직과 기능을 담아 설계하고 개발하는 방법을 POJO 프로그래밍이라 할 수 있다.
POJO의 장점
POJO가 될 수 있는 조건이 바로 장점이 된다.
특정한 기술과 환경에 종속되지 않는 오브젝트는 그만큼 깔끔한 코드가 될 수 있다.
유연한 방식으로 원하는 레벨의 코드를 빠르고 명확하게 테스트할 수 있다.
객체지향적인 설계를 자유롭게 적용할 수 있다는 것도 큰 장점이다.
우리가 알고있는 자바와 객체지향 프로그래밍, 모델링과 설계, 디자인 패턴 등은 POJO가 아니고는 적용하기 힘들다.
POJO 프레임워크
스프링은 POJO를 이용한 엔터프라이즈 애플리케이션 개발을 목적으로 하는 프레임워크라고 했다.
POJO 프로그래밍이 가능하도록 기술적인 기반을 제공하는 프레임워크를 POJO 프레임워크라고 한다.
스프링 프레임워크와 하이버네이트를 대표적인 POJO 프레임워크로 꼽을 수 있다.
스프링을 이용하면 POJO 프로그램의 장점을 그대로 살려서 엔터프라이즈 애플리케이션의 핵심 로직을 객체지향적인 POJO를 기반으로 깔끔하게 구현하고, 동시에 엔터프라이즈 환경의 각종 서비스와 기술적인 필요를 POJO 방식으로 만들어진 코드에 적용할 수 있다.
참고
- https://12bme.tistory.com/157?category=682904#
- https://jongmin92.github.io/2018/02/11/Spring/spring-ioc-di/
- https://tech.wheejuni.com/2018/05/02/spring-aop-how/