-
Notifications
You must be signed in to change notification settings - Fork 0
Description
지금까지 스프링의 주요 특징과 사용된 기술을 살펴보았다. 스프링은 기본적으로 IoC와 DI를 위한 컨테이너로서 동작하지만, 이것이 스프링의 전부는 아니다. 8장에서는 스프링의 사상과 가치, 그리고 적용된 원칙을 좀 더 깊이 있게 알아본다.
8.1 스프링의 정의
스프링의 대한 정의는 다음과 같다.
자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
보통 라이브러리나 프레임워크는 애플리케이션의 특정 계층에서 동작하는 기술 분야에 집중된다. 하지만 스프링은 애플리케이션 프레임워크라고 정의하고 있다.
애플리케이션 프레임워크는 애플리케이션 전 영역을 포괄하는 범용적인 프레임워크를 말한다. 애플리케이션 개발 전 과정을 편리하고 효율적으로 진행하는데 1차적인 목표를 둔다. 스프링의 일차적인 존재 목적은 단지 MVC 개발 지원이나 AOP 툴같은 것이 아닌, 핵심 기술에 담긴 프로그래밍 모델을 일관되게 적용해서 엔터프라이즈 애플리케이션 전 계층과 전 영역에 전략과 기능을 제공해줌으로써 애플리케이션을 편리하게 개발하게 해주는 것이다.
그리고 스프링은 경량급 애플리케이션 프레임워크이다. 스프링 자체가 가볍다거나 코드의 양이 적다는 것은 아니고, 불필요하게 무겁지 않다는 의미이다. 이는 스프링의 창시자 로드 존슨이 비판한 자바 엔터프라이즈 기술의 불필요한 복잡함에 반대되는 개념이다. EJB와 같은 복잡한 기술을 지양하는 것이다. 스프링은 가볍고 단순한 환경에서도 복잡한 EJB와 고가의 WAS를 갖추어야만 가능했던 엔터프라이즈 개발의 고급 기술을 대부분 사용할 수 있다. 추가로, 경량급이라는 의미는 스프링을 기반으로 한 코드가 기존 EJB를 사용한 코드에 비해 상대적으로 작고 단순하다는 의미도 있다.
마지막으로 스프링은 자바 엔터프라이즈 개발을 편하게 해준다. 스프링은 근본적인 부분에서 엔터프라이즈 개발의 복잡함을 제거하고 개발을 편하게 해주는 해결책을 제시한다. 편리한 애플리케이션 개발이란, 복잡하고 실수하기 쉬운 로우 레벨 기술에 신경을 쓰지 않으면서 비즈니스 로직을 효과적으로 구현하는 것을 말한다.
오픈소스에 대한 이야기는 생략한다.
8.2 스프링의 목적
스프링의 개발 철학과 궁극적인 목표가 무엇인지 알아보자. 스프링의 목적을 분명히 알고, 그 목적을 이루는 도구로 잘 활용해야 그 가치를 제대로 얻을 수 있다.
스프링의 목적은 정의에서 보았던 경량급 프레임워크인 스프링을 활용해서 엔터프라이즈 애플리케이션 개발을 편하게 하는 것이다. 기존의 자바 엔터프라이즈 시스템 개발은 너무 복잡했다. 첫 번째 이유로는 기술적인 제약 조건과 요구사항이 계속해서 늘어가기 때문이고, 두 번째 이유는 엔터프라이즈 애플리케이션이 구현해야 할 비즈니스 로직의 복잡함이 증가하기 때문이다.
스프링은 EJB의 처음 목표와 마찬가지로 기술적인 복잡함을 애플리케이션 핵심 로직의 복잡함에서 분리하는데 목표를 뒀다. 스프링의 기술의 적용이 개발자의 코드에 직접 침투하지 않는 식으로 구성이 되었다. 즉, 비침투적인 기술이라는 것이다. 어딘가에는 기술의 적용에 따라 필요한 작업을 해주어야 하지만, 애플리케이션 코드 곳곳에 불쑥 등장하거나 코드의 설계와 구현 방식을 제한하지 않는 것이 비침투적인 기술의 특징이다.
스프링은 기술적 복잡함, 비즈니스 로직의 복잡함 각각을 상대하는 전략이 있다.
먼저 기술적 복잡함 중 기술에 대한 접근방식이 일관성없고 특정 환경에 종속적인 문제점이 있다. 이에 대한 해결 방안은 서비스 추상화이다. 기술적인 복잡함을 일단 추상화를 통해 로우 레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리하고, 환경과 세부 기술에 독립적인 접근 인터페이스를 제공하는 것이다.
두 번째 문제는 기술적인 처리를 담당하는 코드가 성격이 다른 코드에 섞여서 등장하는 문제점이다. 로깅, 비즈니스 로직 전후로 경계가 설정되는 트랜잭션, 비즈니스 로직에 대한 보안 적용 등이 있다. 저번에 보았듯이 이러한 복잡함을 해결하기 위한 스프링의 접근 방법은 AOP 이다.
복잡한 비즈니스 및 애플리케이션 로직을 처리하는 스프링의 전략은 따로 없다. 예전에는 비즈니스 로직을 DB에 두었다고 한다. SQL을 통해 비즈니스 로직을 표현하고, DB에서 동작하는 저장 프로시져를 통해 핵심 로직을 처리했다. 하지만 엔터프라이즈 규모가 커지고 복잡해짐에 따라 비즈니스 로직을 애플리케이션에 담기 시작했고, 객체지향 기법과 자바 언어가 주는 장점인 유연성을 잘 활용해서 까다로운 비즈니스 로직을 효과적으로 구현할 수 있게 되었다. 따라서 비즈니스 로직의 복잡함을 상대하는 전략은 자바라는 객체지향 기술 그 자체라고 볼 수 있다.
객체지향적으로 프로그래밍할 때 DI 개념이 많은 도움을 준다. 그리고 DI 역시 객체지향 설계 기술 없이는 존재 의미가 없다. 스프링은 단지 DI를 편하고 쉽게 하도록 도와줄 뿐이다. 결국 모든 스프링의 기술과 전략은 객체지향이라는 자바 언어가 가진 강력한 도구를 극대화해서 사용할 수 있도록 돕는 것이다.
8.3 POJO 프로그래밍
Professional Spring Framework라는 책에서 스프링 핵심 개발자들은 스프링의 정수는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것이라고 했다. 엔터프라이즈 서비스는 보안, 트랜잭션과 같은 엔터프라이즈 시스템에서 요구되는 기술을 말한다. 위의 말을 풀어보면, 이러한 엔터프라이즈 서비스를 POJO 방식으로 개발된 애플리케이션 핵심 로직에 제공한다는 의미가 된다. 이것이 스프링의 가장 큰 특징과 목표이다.
- POJO(Plain Old Java Object): 특별한 제한에 종속되지 않고, 클래스 패스를 필요로 하지 않는 일반적인 Java Object를 의미한다.
위 그림은 스프링으로 개발한 애플리케이션의 기본 구조를 보여준다. 스프링 애플리케이션은 POJO를 이용해서 만든 애플리케이션 코드와, POJO가 어떻게 관계를 맺고 동작하는지를 정의해놓은 설계 정보로 구분된다. 스프링의 주요 기술인 IoC/DI, AOP, PSA(Portable Service Abstraction)은 애플리케이션을 POJO로 개발할 수 있게 해주는 가능 기술이라고 불린다.
단순하게 생각해보면 POJO란 그냥 평범한 자바 오브젝트라고 볼 수 있다. 하지만 좀 더 명확히 하자면 다음 세 가지 조건을 충족해야 POJO라고 볼 수 있다.
- 특정 규약에 종속되지 않는다
- 특정 환경에 종속되지 않는다
- 객체지향적인 자바 언어의 기본에 충실하게 만들어져야 한다.
위 조건이 그대로 POJO의 장점이 된다. 특수한 기술과 환경에 종속되지 않는 오브젝트는 그만큼 깔끔한 코드가 될 수 있고, 자동화된 테스트에도 유리하다. 객체지향적인 설계를 자유롭게 적용할 수 있다는 것도 큰 장점이다.
8.4 스프링의 기술
스프링에서는 POJO 프로그래밍을 쉽게 할 수 있도록 지원하는 세 가지 가능 기술을 제공한다. 바로 IoC/DI, AOP, PSA 이다. 이 세 기술은 모두 스프링이 생기기도 전에 여러 형태로 시도됐고 발전하고 있던 기술이었는데, 스프링은 이것들을 통일성 있게, 더 세련된 방법으로 자바 엔터프라이즈 개발의 전 영역에서 효과적으로 적용될 수 있도록 프레임워크 형태로 제공하고 있다. 그렇다고 스프링을 IoC/DI 컨테이너라거나, AOP 툴이라거나, 엔터프라이즈 서비스 추상화를 제공해주는 프레임워크라고만 이해하면 스프링 자체의 목적과 가치를 놓칠 수 있다. 이러한 기술들은 스프링의 진정한 목표인 POJO 기반의 엔터프라이즈 개발을 편리하게 해주는 도구일 뿐이다.
IoC/DI
두 개의 오브젝트를 분리하고, 인터페이스를 두어 느슨하게 연결한 뒤, 실제 사용할 대상은 DI를 통해 외부에서 지정하는 방식이 그렇지 않은 경우보다 나은 점이 무엇일까?
가장 단순한 답변은 유연한 확장이 가능하게 하기 위해서라고 할 수 있다. DI는 확장에는 열려 있고, 변경에는 닫혀 있다는 개방 폐쇄 원칙으로 설명할 수 있다. A->B라는 의존관계가 있을 때, 확장에 열려 있단 말은 B가 자유롭게 변경(기능의 추가)될 수 있음을 말한다. 그리고 변경에 닫혀 있다는 말은 A 관점에서 봤을 때 A의 코드 변경없이 재사용(새로운 기능 사용)이 가능하다고 보는 것이다.
DI의 적용 방법은 다음과 같다.
-
의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예이다.
-
첫 번째와 비슷하게 의존 오브젝트의 핵심 기능 자체를 바꾸는 것이다. 하지만 일반적인 DI와 달리, 동적으로 변경할 수도 있다.
-
핵심 기능은 그대로 둔 채로 부가 기능을 추가하는 것이다. 데코레이터 패턴에서, 인터페이스를 그대로 두고, 실제 사용할 오브젝트는 DI를 적용해 데코레이터 패턴을 쉽게 적용할 수 있다.
-
클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우 DI가 유용하다. 인터페이스가 다른 다양한 구현을 같은 방식으로 사용할 수 있도록 중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 방법이 있겠다.
-
프록시 패턴의 전형적인 응용 방법도 있다.
-
템플릿/콜백 패턴
-
싱글톤과 오브젝트 스코프
-
테스트
AOP
AOP는 완전 새로운 프로그래밍 패러다임은 아니다. AOP를 사용하면 그 결과로 OOP를 더욱 OOP답게 만들 수 있다. AOP를 자바 언어에 적용하는 기법은 크게 두 가지로 분류할 수 있다.
- 스프링과 같이 다이나믹 프록시를 사용하는 방법
- 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법
AOP는 모듈 하나가 많은 오브젝트에 보이지 않게 적용되기 때문에 매우 주의해서 사용해야 한다. 다음 단계를 밟아 AOP를 도입하는 접근 방법이 좋다.
- 미리 준비된 AOP 이용
- 전담팀을 통한 정책 AOP 적용
- AOP의 자유로운 이용
PSA
PSA 기술은 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해준다. POJO 코드는 특정 환경이나 구현 방식에 종속적이면 안된다. 하지만 스프링은 JavaEE 플랫폼 기반이기 때문에 JavaEE 기술에 의존적일 수밖에 없다. 이런 경우 중간에서 POJO 코드가 JavaEE 기술에 직접 노출되지 않도록 제공하는 대표적인 기술이 일관성있는 서비스 추상화 기술이다.
