티스토리 뷰
이번에는 흔히 얘기하는 POJO 프로그래밍과 Spring 프레임워크의 관계에 대해 알아보도록 하겠습니다. 아래의 내용들 중에는 토비의 스프링에서 참고한 부분이 많이 있습니다.
1. EJB와 POJO 프로그래밍
[ POJO의 등장 ]
EJB(Enterprise Java Bean)란 엔터프라이즈 개발을 단순화하기 위해 Sun 사에서 만들어낸 Java 스펙이다. 스프링이 등장하기 이전에는 EJB가 자바 엔터프라이즈 애플리케이션 개발 시장을 독점하고 있었다. 하지만 EJB에는 치명적인 단점이 있었는데, 바로 코드들이 EJB 기술에 지나치게 종속되어야 한다는 것이다. 아래의 코드는 EJB 기반으로 작성된 것으로, 특정 서비스 계층에 EJB라는 기술이 마구 침투하는 모습을 확인할 수 있다. import 선언문부터 implenets, 인스턴스 변수까지 코드가 EJB에 완전히 종속된다.
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class OrdersService implements SessionBean {
private SessionContext ctx;
public Orders placeOrder(String menuName) {
Orders orders = new Orders(menuName);
orders.init()
return orders;
}
@Override
public void setSessionContext(SessionContext ctx) throws EJBException {
this.ctx = ctx;
}
@Override
public void ejbRemove() throws EJBException {
}
@Override
public void ejbActivate() throws EJBException {
}
@Override
public void ejbPassivate() throws EJBException {
}
}
마틴 파울러는 당시 인기를 끌던 EJB처럼 복잡하고 제한적인 기술보다는 자바의 단순 오브젝트를 이용해 비즈니스 로직을 구현하는 편이 낫다고 생각했다. 그럼에도 개발자는 왜 자바의 단순한 객체를 사용하길 꺼리는지 궁금해했는데, 그 이유를 찾아보니 그럴싸한 이름이 없기 때문이였다. 그래서 2000년에 마틴 파울러가 컨퍼런스 발표를 준비하다가 뭔가 있어보이도록 만든 이름이 바로 POJO(Plain Old Java Object)였고, 이는 기대 이상으로 성공적이였다.
2. 스프링 프레임워크의 탄생
[ 스프링 프레임워크의 탄생 ]
2000년대 초반 각종 자바 컨퍼런스에서 자주 논의됐던 주제는 “왜 자바 엔터프라이즈 프로젝트는 실패하는가?” 였다. 밝혀진 여러 가지 원인이 있었지만, 그 중 가장 대표적인게 “엔터프라이즈 시스템 개발이 너무 복잡해져서”였다.
엔터프라이즈 시스템 개발이 복잡한 이유는 비즈니스 자체의 복잡함과 기술적인 복잡함이 결합되기 때문이다. 비즈니스 자체의 복잡함은 우리가 구현해야 할 로직으로 제거 대상이 아니다. 대신 기술적 복잡함을 비즈니스 로직으로부터 분리해내는 것이 필요했다. 이러한 분위기 속에서 2002년에 로드 존슨(Rod Johnson)은 EJB의 문제점을 지적한 책(J2EE Design and Development)을 출간했다.
로드 존슨은 EJB의 문제점을 지적하면서 EJB 없이도 고품질의 애플리케이션 개발할 수 있다는 내용과 예제 코드를 선보였다. 그리고 이 책을 읽은 개발자 유겐 휠러(Uergen Hoeller)와 얀 카로프(Yann Caroff)가 로드 존슨에게 오픈 소스 프로젝트를 제안했고, 2004년에 탄생한 것이 바로 스프링 프레임워크이다. 실제로 해당 책의 내용을 보면 BeanFactory, ApplicationContext 등 스프링의 기본이 되는 코드들이 모두 담겨있다고 한다. 참고로 Spring은 EJB에 종속되던 겨울이 끝나고 봄이 왔다는 의미에서 붙여졌다고 한다.
[ 스프링 프레임워크의 목표: 비침투적인 해결책 ]
스프링은 EJB의 처음 목표와 마찬가지로 기술적인 복잡함을 애플리케이션 핵심 로직에서 제거하는데 목표를 뒀다.
어떤 기술을 적용했을 때 그 기술과 관련된 코드나 규약 등이 코드에 등장하는 경우를 침투적인 기술이라고 한다. 물론 꼭 필요한 기능을 위해 특정 기술의 API를 이용하는건 어쩔 수 없지만, 꼭 필요한 기능이 아닌데도 특정 클래스나 인터페이스, API 등이 코드에 마구 등장한다면 그것은 침투적인 기술이 되며 복잡함을 가중시키는 원인이 된다.
반면에 비침투적인 기술은 기술의 적용 사실이 코드에 직접 반영되지 않는다는 특징이 있다. 어딘가에서는 기술의 적용에 따라 필요한 작업을 해줘야 하겠지만, 애플리케이션 코드 여기저기에 불숙 등장하거나, 코드의 설계와 구현 방식을 제한하지는 않는다.
스프링이 성공할 수 있었던 비결은 바로 비침투적인 기술이라는 전략을 택했기 때문이다. 스프링을 이용하면 기술적인 복잡함과 비즈니스 로직을 다루는 코드를 깔금하게 분리할 수 있다. 스프링 스스로는 애플리케이션 코드에 불필요하게 나타나지 않도록 도와주며, 꼭 필요할 것 같은 경우조차도 기술 코드가 직접 노출되지 않도록 만들어졌다.
그리고 이런 문제를 해결하는데 스프링이 공통적으로 사용하는 도구가 바로 객체지향이다. 기술적인 복잡함을 효과적으로 다루게 해주는 기법은 모두 DI를 바탕으로 한다. 서비스 추상화, 템플릿/콜백, AOP와 같은 스프링의 기술은 DI 없이 존재할 수 없다. 그리고 DI는 객체지향 기술 없이 그 존재 의미가 없다. DI는 특별한 기술이라기보다는 유연하게 확장할 수 있는 오브젝트 설계를 하다 보면 자연스럽게 적용하게 되는 객체지향 프로그래밍 기법일 뿐이며 스프링은 단지 그것을 더욱 편하고 쉽게 사용하도록 도와줄 뿐이다. 결국 모든 스프링의 기술과 전략은 객체지향이라는 자바 언어가 가진 강력한 도구를 극대화해서 사용할 수 있도록 돕는 것이며 스프링은 단지 거들 뿐이다.
물론 최근에는 Spring 3.1에 등장한 어노테이션 기반의 프로그래밍 방식이 상당한 인기를 끌고 있어서 우리의 코드는 프레임워크에 꽤나 침투되고 있다. 하지만 이것은 개발자인 우리의 선택일 뿐이며, 비침투적인 코드 작성도 가능하다.
[ POJO 프로그래밍과 스프링 프레임워크 ]
스프링의 핵심 개발자들이 함께 쓴 ”Professional Spring Framework”라는 책에서 스프링 핵심 개발자들은 “스프링의 정수(essence)는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것”이라고 했다. 엔터프라이즈 서비스라고 하는 것은 보안, 트랜잭션과 같은 엔터프라이즈 시스템에서 요구되는 기술을 말한다. 이런 기술을 POJO에 제공한다는 말은 엔터프라이즈 서비스 기술과 POJO 애플리케이션 로직을 담은 코드를 분리했다는 뜻이다. “분리됐지만 반드시 필요한 엔터프라이즈 서비스 기술을 POJO 방식으로 개발된 애플리케이션 핵심 로직을 담은 코드에 제공한다”는 것이 스프링의 가장 강력한 특징과 목표이다.
스프링의 핵심이 POJO라는 사실은 스프링의 핵심을 가장 나타내는 스프링 삼각형을 통해서도 알 수 있다. 이 그림은 스프링 소스의 CTO인 아드리안 콜리어가 스프링의 핵심 개념을 설명하기 위해 만들었다. 스프링의 주요 기술인 Ioc/DI, AOP, PSA는 애플리케이션을 POJO로 개발할 수 있게 해주는 가능 기술들이며, 이것들은 모두 스프링이 있기 전에도 여러 가지 형태로 시도됐고 발전하던 기술이었다.
시간이 지나면서 스프링은 모던한 웹 프레임워크들과 비교하여 한계점을 갖게 되었습니다. 어느 개발자는 이러한 부분을 지적하고 개선해달라는 요구를 하였는데, 그것이 바로 스프링 부트(Spring Boot)의 탄생이 되었습니다. 자세한 내용은 스프링 부트의 탄생과 관련된 포스팅을 참고해주시기를 부탁드립니다. 감사합니다:)
관련 포스팅
- POJO 프로그래밍과 스프링 프레임워크의 탄생
- 스프링 부트(SpringBoot)의 탄생 배경, 컨테이너리스(Containerless) 웹 애플리케이션 아키텍처
'Spring' 카테고리의 다른 글
[Spring] Jasypt를 이용한 Yaml 또는 Properties 프로퍼티 설정 파일의 리소스 암호화 (6) | 2023.02.28 |
---|---|
[Spring] ObjectMapper의 동작 방식과 SpringBoot가 제공하는 추가 기능들 (16) | 2023.01.10 |
[Spring] OpenFeign 타임아웃(Timeout), 재시도(Retry), 로깅(Logging) 등 설정하기 (11) | 2022.11.22 |
[Spring] OpenFeign이란? OpenFeign 소개 및 사용법 (8) | 2022.11.15 |
[Spring] 스프링의 트랜잭션 전파 속성(Transaction propagation) 완벽하게 이해하기 (23) | 2022.08.22 |