18 Nov 2017

Toby's Spring Chap 08: 스프링이란 무엇인가?

스프링은 기본적으로 IoC와 DI를 위한 컨테이너로서 동작하지만, 단순히 “스프링은 IoC/DI 프레임워크” 라고는 말할 수 없다. 스프링은 엔터프라이즈 애플리케이션 개발의 전 영역에 걸쳐 다양한 종류의 기술에 관여한다.

스프링에 대해 가장 잘 알려진 정의는 이렇다.

자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크


애플리케이션 프레임워크

보통 라이브러리나 프레임워크는 웹 계층을 MVC 구조로 쉽게 만든다거나 포맷과 출력장치를 유연하게 바꿀 수 있는 로그 기능, 관계형 DB와 객체를 매핑해주는 ORM 등 특정 분야나 기술에 특화된 목표를 가지고 개발된다.

그러나 스프링은 애플리케이션 프레임워크 라는 특징을 가지고 있다.

애플리케이션 프레임워크란 특정 계층이나 기술, 분야에 국한되지 않고 애플리케이션의 전 영역을 포괄하는 범용적인 프레임워크 를 말한다. 애플리케이션 개발의 전 과정을 빠르고 편리하게 그리고 효율적으로 진행할 수 있도록 돕는데 일차적인 목표를 두는 프레임워크이다.


스프링이 단지 여러 계층의 다양한 기술을 모아두었다고 애플리케이션 프레임워크라고 불리는 것이 아니다. 애플리케이션 전 영역을 관통하는 일관된 프로그래밍 모델과 핵심 기술(IoC/DI, AOP 등)을 바탕으로 각 분야의 요구사항을 채워주고 있다. 따라서 스프링을 활용하면 애플리케이션을 빠르고 효과적으로 개발할 수 있다.

보통 스프링을 IoC/DI 프레임워크나 AOP 툴이라고 보는 건 스프링에 제공하는 핵심 기술에만 주목했기 때문이다.

스프링의 일차적인 존재 목적은 핵심 기술에 담긴 프로그래밍 모델을 일관성있게 적용해서, 애플리케이션 전 계층과 영역에 전략과 기능을 제공해줌으로써, 애플리케이션을 보다 편리하게 개발하게 해주는 애플리케이션 프레임워크로 사용되는 것이다.


경량급 (lightweight)

스프링이 경량급이라는 것은 스프링 자체가 가볍다거나 작은 규모의 기술로 만들어졌다는 것이 아닌 불필요하게 무겁지 않다는 것이다.

개발 환경과 테스트 과정, 코드 등 매우 복잡하게 만들던 EJB에 비해, 스프링은 단순한 개발 툴과 기본적인 개발 환경으로도 엔터프라이즈 개발에서 필요한 기능을 갖춘 애플리케이션을 개발할 수 있다.

또한 스프링을 활용해서 만든 비즈니스 로직이 다른 프레임워크를 사용할 때에 비해, 가볍고 단순하다는 것이다. 스프링은 기존 코드에 불필요하게 등장하던 프레임워크나 환경에 의존적인 부분을 제거해주기 때문이다.


자바 엔터프라이즈 개발을 편하게

스프링은 엔터프라이즈 개발의 복잡함을, 그 근본적인 문제점에 도전하여 해결책을 제시한다.

편리한 애플리케이션 개발이란 복잡하고 실수하기 쉬운 로우레벨 기술에 신경을 쓸 필요없이, 애플리케이션의 핵심인 비즈니스 로직을 빠르게 효과적으로 구현하는 것을 말한다.

EJB의 비전과 목표도 이 것이었지만, 다른 차원의 복잡함을 애플리케이션 개발에 끌고오는 바람에 더 복잡해지는 문제가 있었다.

스프링은 개발자들이 자신이 작성하는 비즈니스 로직에 더 많은 관심과 시간을 쏟도록 해준다. 스프링의 기본설정과 적용기술만 잘 선택하고 준비해두면, 개발할 때 스프링과 관련된 코드나 API에 대해 거의 신경 쓸 일이 없다.


오픈소스

스프링은 오픈소스 프로젝트 방식으로 개발되어 왔으며, 아파치 라이언스 2.0을 사용함으로써 비교적 사용이 자유롭다. 그리고 오픈소스 개발의 한계인 지속적이고 안정적인 개발이 계속될지가 불확실한 점을 개발을 책임지고 진행할 수 있는 전문 기업(스프링 소스)을 만듬으로써 해결하였다.


스프링의 목적

스프링의 목적은 경량급 프레임워크인 스프링을 활용해서 엔터프라이즈 애플리케이션 개발을 편하게하는 것이다. 굳이 스프링을 사용해서 엔터프라이즈 개발을 편하게 하려는 이유는 원래 엔터프라이즈 개발이란 편하지 않기 때문이다.


엔터프라이즈 개발의 복잡함

엔터프라이즈 시스템 개발이 복잡한 이유는 크게 두 가지 원인을 생각해볼 수 있다.

1. 기술적인 제약조건과 요구사항 증가

엔터프라이즈 시스템이란 서버에서 동작하며 기업과 조직의 업무를 처리해주는 시스템을 말한다. 이런 시스템은 많은 사용자 요청을 동시에 처리해야 하므로 서버 자원을 효율적으로 사용할 수 있어야 한다. 또한 보안과 안정성, 확장성 면에도 뛰어나야 하기 때문에 그런 점을 고려한 개발기술이 필요하다.

즉, 엔터프라이즈 시스템을 개발하는 데는 순수한 비즈니스 로직을 구현하는 것 외에도 기술적으로 고려할 사항이 많다는 것이다. 따라서 이런 기술적인 문제를 고려하면서 애플리케이션을 개발해야 하는 부담을 안게 된다.

2. 비즈니스 로직의 복잡함이 증가

엔터프라이즈 시스템을 이용해 기업의 핵심 업무를 처리하는 비율이 늘어났고, 그만큼 다양하고 복잡한 업무 처리 기능을 구현해야 한다는 점이다. 원래 기업 업무란 그 자체로 복잡한데다, 다양한 예외상황도 많고 처리해야 하는 정보의 규모도 상당하다.

요즘에는 경제 흐름과 사회의 변화, 업계의 추이에 따라 수시로 업무 프로세스를 변경하고 조정하는 것을 상시화할 만큼 변화의 속도가 빨라졌다. 이런 변화는 이를 뒷받침해주어야 하는 엔터프라이즈 시스템의 변경을 요구할 수밖에 없다. 이는 요구사항과 정책 등이 수시로 바뀌므로 애플리케이션을 자주 수정해주어야 하는 시대가 된 것이다.

복잡함을 가중시키는 원인

엔터프라이즈 개발이 실패하는 주요 원인은 비즈니스 로직의 복잡함과 기술적인 복잡함이다. 복잡하다는 것은 단지 양이 많고 어렵다는 뜻이 아니다. 세부 요소가 이해하기 힘든 방식으로 얽혀 있고, 그 때문에 쉽게 다루기 어렵다는 의미이다.

또한 엔터프라이즈 시스템 개발이 가장 어려운 이유는 근본적으로 비즈니스 로직과 엔터프라이즈 기술이라는 두 가지 복잡함이 같이 얽혀있기 때문이다. 만약 트랜잭션이나 각종 라이브러리, DB 관련 API 등을 비즈니스 로직과 함께 얽혀 있다면 매우 개발이 어려워진다.

전통적인 자바 엔터프라이즈 개발 기법은 대부분 복잡한 비즈니스 로직과 기술적인 코드가 혼재될 수밖에 없는 방식이었다.



복잡함을 해결하려는 도전

제거될 수 없는 근본적인 복잡함

근본적으로 엔터프라이즈 개발의 복잡함을 효과적으로 상대할 수 있는 전략과 기법이 필요하다. 문제는 비즈니스 로직의 복잡함을 효과적으로 다루는 방법과 기술적인 복잡함을 다루는 방법이 다르다는 점이다. 따라서 두 가지 복잡함이 코드에 한데 어우러져 나타나는 전통적인 개발 방식에서는 효과적으로 다루기 힘들다.

따라서 가장 먼저 할 일은 성격이 다른 두 가지 복잡함을 분리하는 것이다.

1. 실패한 해결책: EJB

EJB의 목표도 이 두 가지 종류의 복잡함을 분리하는 것이었다. 로우레벨의 기술적인 복잡함에 신경 쓰지 않고 비즈니스 로직을 효과적으로 개발하는 데 더 집중할 수 있게 하자는 목표가 있었다.

그런데 EJB는 그런 목표를 달성하는데 실패하였다. 기술적인 복잡함을 비즈니스 로직에서 분리하는 것은 성공하긴 했지만, 이를 위해 특정 인터페이스나 클래스를 구현 및 상속해야되고 서버에 종속적인 서비스를 통해서만 접근하고 사용이 가능하게 하는 EJB 개발방식은 잘못된 선택이었다.

비즈니스 로직에서 기술적인 코드가 제거된 건 사실이지만, EJB라는 환경과 스펙에 종속되는 코드로 만들어지는 더 큰 부담을 안게 되었다.

또한 EJB라는 틀 안에서 코드를 작성하게 강제함으로써 자바가 원래 갖고 있던 장점마저 잃어버렸다는 것이다. EJB의 특정 클래스를 상속받게 함으로써 더 이상 상속구조를 적용하지 못하게 만들거나 다형성 적용을 제한한다거나 하는 것들이다.

2. 비침투적인 방식을 통한 효과적인 해결책: Spring

스프링은 EJB의 실패를 교훈으로 삼아 출발했다. EJB의 목표와 마찬가지로 기술적인 복잡함을 비즈니스 로직의 복잡함에서 제거하는 데 목표를 뒀다. EJB처럼 개발자 코드에 난입해서 지저분하고 복잡한 코드를 만들어버리는 실수를 하지는 않았다.

EJB처럼 어떤 기술을 적용했을 때 그 기술과 관련된 코드나 규약 등이 코드에 등장하는 경우를 침투적인(invasive) 기술이라고 한다. 꼭 필요해서 사용하지만 그 기술을 위해 특정 클래스나 인터페이스, API 등의 코드가 마구 등장한다면 그것은 침투적인 기술이 되며 복잡함을 가중시키게 된다.

반면 비침투적인(non-invasive) 기술은 기술의 적용 사실이 코드에 직접 반영되지 않는다는 특징이 있다. 기술을 적용해야하므로 필요한 작업을 해줘야겠지만 코드에 갑자기 등장하거나 설계와 구현 방식을 제한하지 않는다.

스프링이 성공할 수 있었던 것은 바로 비침투적인 기술이라는 전략을 택했기 때문이다. 스프링을 사용하면 기술적인 복잡함과 비즈니스 로직을 다루는 코드를 깔끔하게 분리할 수 있다. 중요한 것은 그 과정에서 스프링 스스로가 애플리케이션 코드에 불필요하게 나타나지 않도록 하는 것이다.

이를 통해 성격이 다른 복잡함을 깔끔하게 분리해주어 각각의 복잡함을 효과적으로 상대할 수 있는 기반이 마련되었다.



복잡함을 상대하는 스프링의 전략

스프링의 기본적인 전략은 비즈니스 로직을 담은 애플리케이션 코드와 엔터프라이즈 기술을 처리하는 코드를 분리시키는 것이다.

1. 기술적 복잡함을 상대하는 전략

스프링은 엔터프라이즈 기술을 적용했을 때 발생하는 복잡함의 문제를 두 가지로 분류하고 각각에 대해 적절한 대응 방법을 제공한다.

가. 첫 번째 문제: 기술에 대한 접근 방식이 일관성이 없고, 특정 환경에 종속적일 때

환경이나 서버, 적용되는 조건이 바뀔 때 기술이 달라지고 그에 따라 코드도 바뀌는 것은 심각한 문제이다. 비록 동일한 목적으로 만들어졌으나 사용 방법이나 접근 방식이 서로 다른 기술들이 난립하는 것이 현실이다.

이렇게 일관성 없는 기술과 서버 환경의 변화에 따른 스프링의 공략 방법은 서비스 추상화다.

트랜잭션 추상화나 OXM 추상화, 데이터 엑세스에 관한 일관된 예외변환 기능, 데이터 엑세스 기술에 독립적으로 적용 가능한 트랜잭션 동기화 기법 등이 대표적인 예이다. 기술적인 복잡함은 추상화를 통해 로우레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리하고, 환경과 기술에 독립적인 인터페이스를 제공하는 것이 가장 좋은 해결책이다.

데이터 엑세스 예외에 대한 추상화는 비즈니스 로직을 담은 서비스 레이어의 코드가 특정 기술이 발생시키는 예외에 종속되지 않도록 한다.

템플릿/콜백 패턴은 판에 박힌 반복적인 작업 흐름과 API 사용 코드를 제거해준다. 이를 통해 기술을 사용하는 코드도 핵심로직에만 집중하도록 도와준다.

나. 두 번째 문제: 기술적인 처리를 담당하는 코드가 성격이 다른 코드에 섞여서 등장할 때

비즈니스 로직 전후로 경계가 설정되어야 하는 트랜잭션이나 보안 적용, 계층 사이에 주고받는 데이터와 예외의 일괄 변환이나 로깅과 같은 것이 대표적인 예이다.

이런 기술과 비즈니스 로직의 혼재로 발생하는 복잡함을 해결하기 위한 스프링의 접근 방법은 AOP 이다. AOP는 최후까지 애플리케이션 로직을 담당하는 코드에 남아 있는 기술 관련 코드를 깔끔하게 분리하여 별도의 모듈로 관리하게 해주는 강력한 기술이다. 기술적인 코드가 여기저기 중복돼서 나타나는 문제를 AOP를 통해 해결하였다.

2. 비즈니스와 애플리케이션 로직의 복잡함을 상대하는 전략

비즈니스 로직을 담은 코드는 애플리케이션에서 가장 핵심이 되는 부분이다. 또한 업무 변화에 따라 자주 변경되거나 수정되어야 하는 부분이기도 하다. 엔터프라이즈 기술을 처리하는 코드와는 다르게 비즈니스 로직에 오류가 발생하면 반드시 큰 사고가 발생할 수 있다. 따라서 비즈니스 로직은 가장 중요하게 다루어져야 하고 많이 신경써야 하는 부분이다.

예전에는 비즈니스 로직을 DB에 두는 것이 유행이었지만, 엔터프라이즈 시스템의 규모가 커짐에 따라 비즈니스 로직은 애플리케이션 안에서 처리하는 것이 추세이다. DB는 단지 데이터의 저장과 복잡한 조건을 가진 검색과 같은 특화된 기능에만 활용하고 데이터 분석 및 가공, 로직을 처리하는 부분은 확장하기 쉽고 비용이 싼 애플리케이선 서버 쪽으로 이동하는 것이다.

자바는 객체지향언어의 장점을 잘 살려서 설계된 언어이다. 객체지향 기법과 언어가 주는 장점인 유연한 설계가 가능하고 재사용성이 높다는 점을 활용한다면, 자주 바뀌고 조건이 까다로운 비즈니스 로직을 효과적으로 구현할 수 있다. 환경에 종속적인 기술과 침투적인 기법으로 인해 추가된 군더더기로부터 방해만 받지 않는다면 객체지향언어의 장점을 잘 살려 복잡함을 효과적으로 다루는 비즈니스 로직을 구현하는 것은 어렵지 않다.

스프링은 이 비즈니스 로직 구현에 있어서 전혀 관여하지 않으며 다만 비침투적인 기술을 통해 비즈니스 로직을 담당하는 객체들에게 적절한 엔터프라이즈 기술 서비스가 적용되도록 은밀히 도와준다.

결국 비즈니스 로직의 복잡함을 상대하는 전략은 자바라는 객체지향 그 자체이다. 단지 스프링는 객체지향 언어의 장점을 제대로 살리지 못하게 방해하는 요소를 제거하도록 도와줄 뿐이다.



스프링의 핵심도구: 객체지향과 DI

기술과 비즈니스 로직의 복잡함을 해결하는데에 있어서 스프링은 지향하는 것은 객체지향 프로그래밍의 장점을 취하자는 것이다. 객체지향에 충실한 설계가 가능하도록 객체를 개발하고 객체지향 설계 기법이 잘 적용될 수 있도록 DI와 같은 기술을 편하게 적용하도록 도와주는 것이 스프링의 기본전략이다.

서비스 추상화나 탬플릿/콜백, AOP와 같은 스프링 기술은 모두 DI를 바탕으로 하고 있다. DI란 특별한 기술이라기보다는 유연하게 확장할 수 있는 객체 설계를 하다보면 자연스럽게 적용되는 객체지향 프로그래밍 기법일 뿐이다. 스프링은 단지 그것을 더욱 편하고 쉽게 사용하도록 해준다.

DI는 객체지향적인 설계와 개발로 이끌어주는 좋은 동반자이다. 객체 설계시 성격이 다른 코드가 무엇이고 변경의 이유가 다른 기능은 무엇인지 생각하면서 DI를 적용하다보면 객체지향 설계 원칙을 잘 따르고 그 장점을 살린 설계가 나올 수도 있다.

스프링을 사용하고 DI를 적용했다고 하지만 기계적인 방법으로 항상 사용하는 틀에 박힌 구조의 빈만 적용하고 나머지 코드에는 DI를 적용할 생각을 안 한다면 DI를 잘못 사용하고 있는 것이다.

기술적인 복잡함 자체를 해결하는 것이나 이 복잡함이 비즈니스 로직에 침범하지 못하도록 하는 경우에는 DI가 바탕이 되는 여러가지 기법이 활용된다. 반면에 비즈니스 로직 자체의 복잡함을 해결하려면 객체지향 설계 기법이 더 중요하다.

스프링이 힘들게 비즈니스 로직 자체를 기술적인 코드와 기술 스펙이 침범하지 않도록 힘을 쓴 이유는 단지 코드가 좀 더 단순해지고 명확해지기 때문만이 아니다. 순수한 비즈니스 로직을 담고 있는 코드는 객체지향 분석과 설계기법을 쉽게 적용할 수 있기 때문이다.

즉, 스프링의 기술과 전략은 객체지향이라는 자바 언어가 가진 강력한 도구를 극대화해서 사용할 수 있도록 돕는 것이라고 볼 수 있다. 스프링만 잘 사용한다고 복잡한 엔터프라이즈 시스템 개발을 잘할 수 있는 것은 아니다. 객체지향을 잘 활용하여 복잡한 문제를 해결할 수 있는 개발자의 능력에 달려있다.



POJO 프로그래밍

스프링의 핵심 개발자들은 스프링의 정수는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것이라고 했다. 이를 바꾸어 말하면 엔터프라이즈 서비스 기술과 POJO라는 애플리케이션 로직을 담은 코드를 분리했다는 뜻이기도 하다.

분리되었지만 반드시 필요한 엔터프라이즈 기술을 POJO 방식으로 개발된 애플리케이션 핵심 로직을 담은 코드에 제공하는 것이 스프링의 가장 강력한 특징과 목표이다.


스프링의 핵심: POJO

다음 그림은 스프링 소스의 CTO인 아드리안 콜리어가 스프링의 핵심 개념을 설명하기 위해 만들었다.


00.png

스프링 애플리케이션은 POJO를 이용해서 만든 애플리케이션 코드와, POJO 객체가 어떻게 관계를 맺고 동작하는지를 정의해놓은 설계정보로 구분된다. 스프링의 주요기술인 IoC/DI, AOP와 PSA(Portable Service Abstraction, 서비스 추상화)는 애플리케이션을 POJO로 개발할 수 있게 해주는 가능 기술(enabling technology)이라고 불린다.

POJO는 Plain Old Java Object 의 약자다. 다음 조건을 충족해야 POJO라고 할 수 있다.

1. 특정 규약에 종속되지 않는다.

POJO는 자바 언어와 꼭 필요한 API 외에는 종속되지 않아야 한다. 따라서 EJB2와 같은 특정 규약에 따라 정의해야하는 경우는 POJO가 아니다. 특정 클래스를 상속하게 하는 것과 같이 규약에 따라 작성하면 객체지향적인 설계 기법을 적용하기가 어려워진다. 규약에 종속되지 않고, 객체지향 설계의 자유로운 적용이 가능한 객체여야 POJO라고 불릴 수 있다.

2. 특정 환경에 종속되지 않는다.

POJO는 환경에 독립적이어야하며, POJO 클래스가 환경이나 특정 기술을 담는 클래스나 인터페이스를 사용하면 안된다. 가령 비즈니스 로직에서 HttpServletRequest나 HttpSession, 캐시와 관련된 API 등이 등장하면 이는 POJO라고 부를 수 없다.

요즘에는 메타정보를 추가해주는 에너테이션을 많이 사용하는데, 이를 통해 코드로 표현하기에는 적절하지 않은 부가정보를 담거나 환경에 종속되지 않게할 수 있다면 POJO라고 불릴 수 있다.

특정 규약이나 환경에 종속되지 않는다고 모두 POJO 인 것은 아니다. POJO는 객체지향적인 자바 언어의 기본에도 충실하게 만들어져야 한다.

POJO는 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 객체를 말한다.



POJO의 장점

POJO 프로그래밍의 장점은 바로 POJO가 될 수 있는 조건이 바로 장점이다.

특정한 기술과 환경에 종속되지 않는 객체는 그만큼 깔끔한 코드가 될 수 있다. 이렇게 개발된 코드는 자동화된 테스트에 유리할 뿐만 아니라, 객체지향적인 설계를 자유롭게 적용할 수 있다.


POJO 프레임워크

스프링은 POJO를 이용한 엔터프라이즈 애플리케이션 개발을 목표로 하는 프레임워크이다. 엔터프라이즈 애플리케이션 개발의 모든 영역과 계층에서 POJO 방식의 구현이 가능하게 하려는 목적으로 만들어졌다.


01.png

위의 그림은 스프링이 어떻게 엔터프라이즈 시스템의 복잡함을 다루는지를 보여준다. 스프링은 비즈니스 로직의 복잡함과 엔터프라이즈 기술의 복잡함을 분리해서 구성할 수 있도록 도와준다.

자신은 기술영역에만 관여하지 비즈니스 로직을 담당하는 POJO에서는 모습을 감춘다. 스프링은 자신을 직접 노출시키지 않으면서, 애플리케이션을 POJO로 쉽게 개발할 수 있게 지원해준다. 이를 통해 개발자들이 복잡한 엔터프라이즈 기술보다는 객체지향적인 설계와 개발의 원리를 집중할 수 있도록 기회를 만들어주는 것이다.


스프링의 기술

스프링은 POJO 프로그래밍을 지원하기 위해 IoC/DI, AOP, PSA 기술을 지원한다. 이 세 가지 모두 객체지향의 설계와 개발원리를 잘 적용하다보면 자연스럽게 만들어지는 것이기도 하다. 다만 스프링은 그것을 통일성 있게, 더 세련된 방법으로, 자바 엔터프라이즈 개발의 전 영역에 걸쳐 효과적으로 적용될 수 있도록 프레임워크로 형태로 제공하고 있다.

스프링의 기술들은 스프링의 진정한 목표인 POJO 기반의 엔터프라이즈 개발을 편리하게 해주는 도구이다.


제어의 역전(IoC) / 의존관계 주입(Depedency Injection)

IoC/DI는 스프링의 가장 기본적인 기술이자, 핵심 개발 원칙이기도 하다. AOP와 PSA도 IoC/DI에 바탕을 두고 있다.

IoC/DI를 사용함으로써 얻는 장점에 대한 가장 간단한 답변은 유연한 확장이 가능하게 하기 위해서 라고 할 수 있다. DI는 개방 폐쇄 원칙이라는 객체지향 설계 원칙으로 잘 설명될 수 있다. 유연한 확장이라는 장점은 개방 폐쇄 원칙의 확장에는 열려있다에 해당한다. 또한 변경에는 닫혀있다라는 말로도 설명할 수 있다.

DI의 활용 방법

1. 핵심기능의 변경

DI의 가장 대표적인 적용 방법으로 바로 의존 대상의 구현을 바꾸는 것이다.

2. 핵심기능의 동적인 변경

1과 비슷하게 의존 객체의 핵심 기능 자체를 변경하는 것이다. 다만 일반적인 DI와는 다르게 동적으로 운영중에 매번 다르게 변경할 수 있다.

3. 부가기능의 추가

DI를 통해 객체의 핵심기능은 그대로 두고, 부가기능을 추가하는 것이다. 인터페이스를 두고 사용하게 하고, 실제 사용할 객체를 외부에서 주입하는 DI를 적용해두면 데코레이터 패턴을 활용하여 쉽게 부가기능을 추가할 수 있다.

부가기능의 추가 방식을 특정 객체가 아니라 좀 더 많은 대상으로 일반화해서 적용하면 AOP가 된다.

4. 인터페이스의 변경

사용하려고 하는 객체의 인터페이스가 클라이언트와 호환되지 않는 경우, 또는 실제로는 비슷한 기능을 담당하는데 인터페이스가 서로 다를 경우에도 DI가 유용하다.

만약 어떤 객체가 기존에 사용하던 인터페이스와는 다른 의존 객체를 사용하고자할 때, 기존 인터페이스를 구현한 객체를 중간에 두는, 객체 방식의 어댑터 패턴을 적용할 수 있다.

이를 좀 더 일반화해서 아예 인터페이스가 다른 다양한 기술들을 같은 방식으로 사용할 수 있도록, 중간에 인터페이스 어댑터 역할을 하는 레이어를 추가한다면 이 것이 바로 서비스 추상화이다.

5. 프록시

DI를 통해 실제 사용할 의존 객체 생성이나 사용을 미룰 수도 있다. (지연 로딩)

6. 템플릿과 콜백

반복적으로 등장하지만 항상 고정적인 작업 흐름과 그 사이에서 자주 바뀌는 부분을 분리하여 템플릿과 콜백으로 만들고 DI를 적용할 수 있다.

콜백을 얼마든지 변경하면서 사용한다는 것은 개방을 통한 유연한 확장을 보여주며, 템플릿은 한 번 만들어두면 계속 재사용할 수 있다는 것은 기능의 확장에도 변하지 않는다는 폐쇄 원칙에 가장 잘 들어맞는 것이다.

7. 싱글톤과 오브젝트 스코프

DI를 프레임워크로 이용한다는 것은 DI 대상 객체를 컨테이너가 관리한다는 의미이다. 따라서 객체 생성 및 관계설정, 이용, 소멸에 이르기까지 컨테이너가 주관하므로 객체 스코프를 자유롭게 제어할 수 있다.

수많은 요청을 처리하는, 고성능을 요구하는 엔터프라이즈 환경에서는 상태를 갖지 않도록 만든 객체가 동시에 여러 요청을 처리하는 방식을 적용해야 한다. 이런 방식을 적용하려면 객체의 개수를 제어하는 것이 매우 중요한데, 컨테이너가 객체를 관리하는 IoC 방식이 유용하다.

8. 테스트

여러 객체와 협력해서 동작하는 객체를 효과적으로 테스트하는 방법은 가능한 고립시키는 것이다.

테스트 대상인 객체 기능에만 충실한 테스트가 가능하게 하려면 의존 객체를 목 객체로 바꿔치기 할 수 있는 DI가 유용하게 쓰일 수 있다.



애스팩트 지향 프로그래밍 (AOP)

AOP는 객체지향 프로그래밍처럼 독립적인 프로그래밍 패러다임이 아니며 객체지향 기술의 한계와 단점을 극복하도록 하는 보조적인 프로그래밍 기술이다.

IoC/DI를 이용해 POJO에 선언적인 엔터프라이즈 서비스를 제공할 수 있지만, 일부 서비스는 순수 객체지향적인 기법만으로는 POJO의 조건을 유지한 채로 적용하기 힘들다. 이 문제를 해결하기 위해 AOP가 필요하다.

1. 다이내믹 프록시 사용

기존 코드에 영향을 주지 않고 부가기능을 적용하게 해주는 데코레이터 패턴을 응용한 것이다. 단, 부가기능을 부여할 수 있는 곳은 메소드의 호출이 일어나는 지점이라는 제약이 있다. 스프링의 가장 기본적인 AOP 구현 방식은 다이내믹 프록시를 이용하는 프록시 AOP 방식이다.

2. 언어의 확장

프록시 방식의 AOP 에서는 불가능한, 다양한 조인포인트를 제공하는 AspectJ라는 툴을 이용해 메소드 호출뿐만 아니라, 인스턴스 생성 / 필드 엑세스/ 특정 호출 경로를 가진 메소드 호출 등에도 부가기능을 제공할 수 있다.

  • 위빙: 클래스가 메모리로 로딩될 때 바이트코드 조작


포터블 서비스 추상화 (PSA)

스프링은 특정 환경에 종속되지 않는 POJO 프로그래밍을 위해, 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 서비스 추상화를 지원한다.


Tags:
Stats:
0 comments