8.4) 스프링의 기술
스프링의 가능기술
- 스프링에서는 POJO 프로그래밍을 손쉽게 할 수 있도록 지원하는 세 가지 가능기술인 IoC/DI, AOP, PSA를 제공한다.
- 스프링은 통일성 있게, 더 세련된 방법으로,
자바 엔터프라이즈 개발의 전 영역에 걸쳐 효과적으로 이를 적용할 수 있도록 프레임워크 형태로 제공한다.
제어의 역전(IoC) / 의존관계 주입(DI)
- IoC/D는 스프링의 가장 기본이 되는 기술이자 스프링의 핵심 개발 원칙이기도 하다.
- 나머지 두 가지 기술인 AOP와 PSA도 IoC/DI에 바탕을 두고 있다.
- 또한 템플릿/콜백 패턴이 적용된 부분도 IoC/DI가 핵심 원리다.
- 왜 DI 방식을 사용하는걸까?
- 왜 두 개의 오브젝트를 분리해서 만들고, 인터페이스를 두고 느슨하게 연결한 뒤,
실제 사용할 대상은 DI를 통해 외부에서 지정하는걸까? - 이렇게 DI 방식으로 하는 것이 그렇지 않은 경우,
즉 직접 자신이 사용할 오브젝트를 new 키워드로 생성해서 사용하는 강한 결합을 쓰는 방법보다 나은 점은 무엇일까? - 그 이유는 유연한 확장이 가능하게 하기 위해서이다.
DI는 개방 폐쇄 원칙이라는 객체지향 설계 원칙으로 확장에는 열려 있고, 변경에는 닫혀있다.
그렇기 때문에 A→B라는 의존관계를 갖는 오브젝트 구조가 있을 때 B가 변경돼도 A는 아무런 영향을 받지 않고
그대로 유지 가능하기 때문에 B는 자유롭게 변경될 수 있다.
또한 B가 구현 방법이 바뀌더라도 A는 그대로 재사용이 가능해진다.
- 왜 두 개의 오브젝트를 분리해서 만들고, 인터페이스를 두고 느슨하게 연결한 뒤,
- 좀 더 구체적으로 DI의 활용 방식을 살펴보면서 그 장점을 생각해보자.
- DI의 가장 대표적인 적용 방법은 바로 의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예이다.
만약 비즈니스 로직이 변경될 경우에 DI를 이용해 새로운 정의를 담은 클래스로 통째로 변경해주면 된다.
이처럼 실제 의존하는 대상이 가진 핵심기능을 DI 설정을 통해 변경할 수 있다.
예) DAO의 구현을 JDBC, JPA, 하이버네이트, JDO, iBatis 등으로 변경하는 것 - 두 번째 활용 방법은 동적으로 매번 다르게 의존 오브젝트의 핵심기능을 바꾸는 것이다.
DI도 기본적으로 런타임 시에 동적인 방식으로 연결되지만 한번 DI되면 바뀌지 않는 정적인 관계를 맺어준다.
하지만 DI의 다이내믹 라우팅 프록시나 프록시 오브젝트 기법을 잘 활용하면
애플리케이션이 동작하는 중간에 그 의존 대상을 다이내믹하게 변경할 수 있다.
예) 사용자의 등급에 따라서 다른 DataSource 사용 - 세 번째 활용 방법은 핵심기능은 그대로 둔 채로 부가기능을 추가하는 것이다. 데코레이터 패턴을 생각해보면 된다.
핵심기능과 클라이언트 코드에는 전혀 영향을 주지 않으면서 부가적인 기능을 얼마든지 추가할 수 있다.
예) 트랜잭션 기능 부여, 로깅, 보안 처리, 이벤트 발생 작업의 추가 - 네 번째 활용 방법은 사용하려는 오브젝트가 가진 인터페이스가 클라이언트와 호환되지 않을 때 사용하는 것이다.
또는 여러 종류의 인터페이스를 가졌지만 사실은 비슷한 기능을 담당하는 오브젝트를 바꿔가면서 사용하고 싶을 때도 있다.
이렇게 클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우에도 DI가 유용하다.
A가 C 오브젝트를 사용하려고 할 때, A는 원래 B 인터페이스를 사용하도록 만들어져 있고
C는 B 인터페이스를 구현하지 않았더라도 A가 DI를 통해 B의 구현 오브젝트를 받도록 만들어져 있다면
B 인터페이스를 구현했으면서 내부에서 C를 호출해주는 기능을 가진 어댑터 오브젝트를 만들어 A에 DI 해주면 된다.
즉, A→B(C로 위임)→C처럼 구성하면 된다. 이로 인해 A는 여전히 자신의 코드를 수정하지 않아도 된다.
이를 디자인 패턴에서 말하는 오브젝트 방식의 어댑터 패턴의 응용이라고 볼 수 있다.
이를 좀 더 일반화해서 아예 인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록,
중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 서비스 추상화(PSA) 방식이 존재한다.
PSA는 클라이언트가 일관성 있게 사용할 수 있는 인터페이스를 정의해주고
DI를 통해 어댑터 역할을 하는 오브젝트를 이용하게 해준다.
이를 통해서 다른 인터페이스를 가진 로우레벨의 기술을 변경하거나 확장해가면서 사용할 수 있다. - 다섯 번째 활용 방법은 프록시 패턴을 적용하는 것이다.
필요한 시점에 실제 사용할 오브젝트를 초기화하고 리소스를 준비해주는 지연된 로딩을 적용하려면 프록시가 필요하다.
원격 오브젝트를 호출할 때 마치 로컬에 존재하는 오브젝트처럼 사용할 수 있게 해주는
원격 프록시를 적용하려고 할 때도 프록시가 필요하다. 두 가지 방법 모두 DI를 필요로 한다.
이 외에도 웹 서비스, REST 호출, HTTP 방식의 호출 등 다양한 리모팅 기술이 모두 DI를 통해 이뤄진다. - 여섯 번째 활용 방법은 템플릿/콜백 패턴을 적용하는 것이다.
반복적으로 등장하지만 항상 고정적인 작업 흐름과 그 사이에서 자주 바뀌는 부분을 분리해서 템플릿과 콜백으로 만들고
이를 DI 원리를 응용해 적용하면 지저분하게 매번 만들어야 하는 코드를 간결하게 만들 수 있다.
콜백을 템플릿에 주입하는 방식으로 동작하게 하는 것은 DI의 원리에 가장 충실한 응용 방법이다. - 일곱 번째 활용 방법은 DI 할 오브젝트의 생명주기를 제어할 수 있다는 것이다.
DI를 프레임워크로 이용한다는 건 DI 대상 오브젝트를 컨테이너가 관리한다는 의미이므로 오브젝트의 생성부터 관계설정,
이용, 소멸에 이르기까지의 모든 과정을 DI 컨테이너가 주관하기 때문에 그 오브젝트의 스코프를 자유롭게 제어할 수 있다.
이를 통해 싱글톤으로 오브젝트를 만들어서 사용하고 관리하기 때문에
클래스 자체를 싱글톤을 고려하지 않고 자유롭게 설계할 수 있다.
때론 단일 싱글톤 외에도 다양한 스코프를 갖는 오브젝트를 만들어 DI에 사용할 수 있다. - 여덟 번째 활용 방법은 다른 오브젝트와의 사이에서 일어나는 일을 테스트를 위해 조작할 수 있도록 하는 것이다.
여타 오브젝트와 협력해서 동작하는 오브젝트를 효과적으로 테스트하기 위해서는 가능한 고립시켜야 한다.
그래야만 테스트 대상인 오브젝트의 기능에 충실하게 테스트가 가능하다.
자칫 다른 오브젝트와의 협력을 통해 동작하는 기능을 다 허용하고 테스트하다가는
한 번에 수십 개의 오브젝트와 DB, 환경까지 모두 테스트해야 하는 부담을 안을 수 있다.
그래서 테스트할 대상이 의존하는 오브젝트를,
테스트를 목적으로 만들어진 스텁 또는 목 오브젝트 같은 테스트 대역으로 대체하면 유용하다.
- DI의 가장 대표적인 적용 방법은 바로 의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예이다.
- 그 외에도 DI의 활용 방법은 다양하며 실전에서 얼마나 DI라는 개념의 활용도가 다양한지 알 수 있다.
- GoF의 디자인 패턴 중에서
인터페이스를 두고 오브젝트를 분리하는 구조를 가진 오브젝트 스코프의 패턴은 DI의 구조에 대부분 잘 들어맞는다. - 그런 패턴의 장점들을 애플리케이션 전 영역에서 간단한 설정만으로 자연스럽게 적용할 수 있게 만들어주는 것이 바로 DI다.
- GoF의 디자인 패턴 중에서
애스펙트 지향 프로그래밍(AOP)
- AOP도 스프링의 3개 가능기술의 하나이다.
- AOP는 객체지향 기술의 한계와 단점을 극복하도록 도와주는 보조적인 프로그래밍 기술이다.
AOP를 사용하면 그 결과로 OOP를 더욱 OOP답게 만들 수 있다. - 스프링의 목적인, POJO만으로 엔터프라이즈 애플리케이션을 개발하면서도
엔터프라이즈 서비스를 선언적으로 제공하는데 반드시 필요한 것이 바로 AOP 기술이다. - IoC/DI를 이용해서 POJO에 선언적인 엔터프라이즈 서비스를 제공할 수 있지만
일부 서비스는 순수한 객체지향 기법만으로는 POJO의 조건을 유지한 채로 적용하기 힘들다.
바로 이런 문제를 해결하기 위해 AOP가 필요하다. - 스프링의 AOP는 스프링이 POJO 프로그래밍을 지원하려는 그 핵심 목적을 위해 중요한 역할을 하고 있다.
- AOP는 객체지향 기술의 한계와 단점을 극복하도록 도와주는 보조적인 프로그래밍 기술이다.
- AOP를 자바 언어에 적용하는 기법은 크게 두 가지로 분류할 수 있다.
- 첫 번째는 스프링과 같이 다이내믹 프록시를 사용하는 방법이다.
이 방법은 기존 코드에 영향을 주지 않고 부가기능을 적용하게 해주는 데코레이터 패턴을 응용한 것이다.
자바의 객체지향 패턴을 활용한 방법이기 때문에 만들기 쉽고 적용하기 간편하다.
대신 인터페이스와 DI를 활용하는 데코레이터 패턴이 기반 원리이기 때문에
부가기능을 부여할 수 있는 곳은 메소드의 호출이 일어나는 지점뿐이라는 제약이 있다.
스프링의 기본적인 AOP 구현 방법은 다이내믹 프록시를 이용하는 프록시 AOP 방식이다.
엔터프라이즈 개발에서 필요로 하는 AOP는 대부분이 이 프록시 방식의 AOP면 된다. - 두 번째는 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법이다.
AspectJ라는 유명한 오픈소스 AOP 툴이 있다. 이는 강력한 고급 기능을 가진 AOP를 제공한다.
AspectJ는 프록시 방식의 AOP에서는 불가능한 다양한 조인 포인트를 제공한다.
메소드 호출 뿐만 아니라 인스턴스 생성, 필드 액세스, 특정 호출 경로를 가진 메소드 호출 등에 부가기능을 제공할 수 있다.
대신 이러한 고급 AOP 기능을 적용하려면 자바 언어와 JDK의 지원만으로는 불가능하므로
AOP 컴파일러를 이용한 빌드 과정을 거치거나, 클래스가 메모리로 로딩될 때 바이트 코드를 조작하는 방법이 필요하다.
그만큼 사용하기 까다롭고 번잡하지만 경우에 따라 프록시 방식의 AOP로는 할 수 없는 작업을 위해 사용해야 한다.
- 첫 번째는 스프링과 같이 다이내믹 프록시를 사용하는 방법이다.
- AOP를 본격적으로 적용하기에는 그 성격이 자바의 일반적인 개발 방법과는 상당히 다르기 때문에
익숙하지 않은 상태라면 차근차근 단계를 밟아 AOP를 도입하는 접근 방법이 좋다.- 일단 처음에는 스프링이 미리 만들어서 제공하는 AOP 기능을 그대로 가져다 적용하는 것으로 시작한다.
스프링이 직접 제공하는 대표적인 AOP는 바로 트랜잭션이다.
AOP 설정을 통해 트랜잭션이 어떻게 오브젝트에 투명하게 적용되는지 관찰해보고, AOP의 특성과 동작원리를 이해한다.
도메인 오브젝트에 DI를 자동적용해주는 AOP 기능인 @Configurable 애노테이션 또한
스프링이 미리 준비해서 제공하는 대표적인 AOP 기능이다. - 다음 단계로는 애플리케이션 전체적으로 이용 가능한 것을 AOP 담당자 관리하에 적용해보는 것이다.
대표적으로 비즈니스 로직을 가진 오브젝트에 대한 보안, 특정 계층의 오브젝트 이용 전후의 작업 기록을 남기는 로깅,
데이터 추적을 위한 트레이싱, 특정 구간의 실시간 성능 모니터링과 같은 정책적인 기능에 AOP를 이용하는 것이다.
이러한 부분은 개발 정책이나 기준이 바뀌면 지금까지 작업한 것을 모두 수정하고 일일이 검증해야 하는
큰 부담이 있으므로 AOP를 이용해 한 번에 적용한다면 일반 개발자의 작업에는 전혀 영향을 주지 않을 수 있다.
또한 AOP는 언제든지 기능을 추가하거나 제거할 수 있으므로 이런 특징을 잘 이용하면 운영 중에 필요한 기능 외에
개발 가이드라인이나 표준을 따라서 코드가 작성되어 있는지를 검증하는 작업을 AOP를 이용해 할 수 있다. - 첫 번째와 두 번째 단계를 거쳐서 AOP에 어느 정도 친숙해지고, 그 장단점과 응용전략, 위험성 등을 어느정도 이해했다면
이제는 개발자 스스로가 AOP를 활용할 수 있는 단계로 넘어갈 수 있다.
이전 단계에서는 애플리케이션 전체적으로 적용되는 정책 AOP를 위주로 했다면
이제는 개발자가 구현하는 기능에 적용하면 유용한 세부적인 AOP를 이용할 수 있다.
즉, 큰 범위에 걸쳐서 적용되는 기능은 아니지만 한 모듈 또는 특정 기능 안에서 AOP로 분리하면 유용한 것들이 있다.
- 일단 처음에는 스프링이 미리 만들어서 제공하는 AOP 기능을 그대로 가져다 적용하는 것으로 시작한다.
포터블 서비스 추상화(PSA)
- 세 번째 가능기술은 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 PSA다.
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다.
특정 환경과 기술에 종속적이지 않다는 것은 POJO 코드가 그런 기술에 직접 노출되어 만들어지지 않는다는 말이다. - 스프링은 이를 위해 일관성 있는 서비스 추상화 기술을 제공한다.
엔터프라이즈 개발에 사용되는 다양한 기술에 대한 서비스 추상화 기능을 제공하며
어떤 것은 AOP나 템플릿/콜백 패턴과 결합돼서 사용되기 때문에 직접적으로 서비스를 이용할 필요가 없고
대신 설정을 통해 어떤 종류의 기술을 사용할지 지정해줘야 한다. - 예를 들어 트랜잭션 서비스 추상화는 대부분 AOP를 이용해 적용하기 때문에 직접 코드를 만들지 않는다.
대신 설정에서는 스프링의 트랜잭션 추상화 인터페이스인 PlatformTrasactionManager를 구현한
구체적인 서비스 클래스를 빈으로 등록해줘야 한다.
이때 JTA를 이용해 트랜잭션을 적용하고 싶다면 JtaTrasactionManager를 빈으로 등록하고
JTA에 대한 설정을 프로퍼티로 넣어주면 된다. - 직접 스프링이 제공하는 API를 사용해서 만드는 경우도 있다.
- 예를 들어 OXM이나 JavaMail을 이용한다면 스프링이 정의한 추상 API를 이용해 코드를 작성한다.
그리고 구체적인 기술과 설정은 XML 파일 안에서 지정한다.
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다.
- 서비스 추상화를 위해 필요한 기술은 DI뿐이다.
- 결국 DI 응용 방법의 한 가지이므로 DI를 적극 활용해서 개발한다면 서비스 추상화는 자연스럽게 만들어 쓸 수 있다.
- 또한 서비스 추상화는 단지 구체적인 기술에 종속되지 않게 하기 위해서만 사용되는 것이 아니라
테스트가 어렵게 만들어진 API나 설정을 통해 주요 기능을 외부에서 제어하게 만들고 싶을 때도 이용할 수 있다.
'Java-Spring > 토비의 스프링 3.1' 카테고리의 다른 글
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링 프로젝트 시작하기 (1) (0) | 2024.04.22 |
---|---|
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링 프로젝트 시작하기 (0) (0) | 2024.04.22 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (3) (0) | 2024.04.17 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (2) (0) | 2024.04.17 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (1) (0) | 2024.04.16 |
8.4) 스프링의 기술
스프링의 가능기술
- 스프링에서는 POJO 프로그래밍을 손쉽게 할 수 있도록 지원하는 세 가지 가능기술인 IoC/DI, AOP, PSA를 제공한다.
- 스프링은 통일성 있게, 더 세련된 방법으로,
자바 엔터프라이즈 개발의 전 영역에 걸쳐 효과적으로 이를 적용할 수 있도록 프레임워크 형태로 제공한다.
제어의 역전(IoC) / 의존관계 주입(DI)
- IoC/D는 스프링의 가장 기본이 되는 기술이자 스프링의 핵심 개발 원칙이기도 하다.
- 나머지 두 가지 기술인 AOP와 PSA도 IoC/DI에 바탕을 두고 있다.
- 또한 템플릿/콜백 패턴이 적용된 부분도 IoC/DI가 핵심 원리다.
- 왜 DI 방식을 사용하는걸까?
- 왜 두 개의 오브젝트를 분리해서 만들고, 인터페이스를 두고 느슨하게 연결한 뒤,
실제 사용할 대상은 DI를 통해 외부에서 지정하는걸까? - 이렇게 DI 방식으로 하는 것이 그렇지 않은 경우,
즉 직접 자신이 사용할 오브젝트를 new 키워드로 생성해서 사용하는 강한 결합을 쓰는 방법보다 나은 점은 무엇일까? - 그 이유는 유연한 확장이 가능하게 하기 위해서이다.
DI는 개방 폐쇄 원칙이라는 객체지향 설계 원칙으로 확장에는 열려 있고, 변경에는 닫혀있다.
그렇기 때문에 A→B라는 의존관계를 갖는 오브젝트 구조가 있을 때 B가 변경돼도 A는 아무런 영향을 받지 않고
그대로 유지 가능하기 때문에 B는 자유롭게 변경될 수 있다.
또한 B가 구현 방법이 바뀌더라도 A는 그대로 재사용이 가능해진다.
- 왜 두 개의 오브젝트를 분리해서 만들고, 인터페이스를 두고 느슨하게 연결한 뒤,
- 좀 더 구체적으로 DI의 활용 방식을 살펴보면서 그 장점을 생각해보자.
- DI의 가장 대표적인 적용 방법은 바로 의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예이다.
만약 비즈니스 로직이 변경될 경우에 DI를 이용해 새로운 정의를 담은 클래스로 통째로 변경해주면 된다.
이처럼 실제 의존하는 대상이 가진 핵심기능을 DI 설정을 통해 변경할 수 있다.
예) DAO의 구현을 JDBC, JPA, 하이버네이트, JDO, iBatis 등으로 변경하는 것 - 두 번째 활용 방법은 동적으로 매번 다르게 의존 오브젝트의 핵심기능을 바꾸는 것이다.
DI도 기본적으로 런타임 시에 동적인 방식으로 연결되지만 한번 DI되면 바뀌지 않는 정적인 관계를 맺어준다.
하지만 DI의 다이내믹 라우팅 프록시나 프록시 오브젝트 기법을 잘 활용하면
애플리케이션이 동작하는 중간에 그 의존 대상을 다이내믹하게 변경할 수 있다.
예) 사용자의 등급에 따라서 다른 DataSource 사용 - 세 번째 활용 방법은 핵심기능은 그대로 둔 채로 부가기능을 추가하는 것이다. 데코레이터 패턴을 생각해보면 된다.
핵심기능과 클라이언트 코드에는 전혀 영향을 주지 않으면서 부가적인 기능을 얼마든지 추가할 수 있다.
예) 트랜잭션 기능 부여, 로깅, 보안 처리, 이벤트 발생 작업의 추가 - 네 번째 활용 방법은 사용하려는 오브젝트가 가진 인터페이스가 클라이언트와 호환되지 않을 때 사용하는 것이다.
또는 여러 종류의 인터페이스를 가졌지만 사실은 비슷한 기능을 담당하는 오브젝트를 바꿔가면서 사용하고 싶을 때도 있다.
이렇게 클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우에도 DI가 유용하다.
A가 C 오브젝트를 사용하려고 할 때, A는 원래 B 인터페이스를 사용하도록 만들어져 있고
C는 B 인터페이스를 구현하지 않았더라도 A가 DI를 통해 B의 구현 오브젝트를 받도록 만들어져 있다면
B 인터페이스를 구현했으면서 내부에서 C를 호출해주는 기능을 가진 어댑터 오브젝트를 만들어 A에 DI 해주면 된다.
즉, A→B(C로 위임)→C처럼 구성하면 된다. 이로 인해 A는 여전히 자신의 코드를 수정하지 않아도 된다.
이를 디자인 패턴에서 말하는 오브젝트 방식의 어댑터 패턴의 응용이라고 볼 수 있다.
이를 좀 더 일반화해서 아예 인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록,
중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 서비스 추상화(PSA) 방식이 존재한다.
PSA는 클라이언트가 일관성 있게 사용할 수 있는 인터페이스를 정의해주고
DI를 통해 어댑터 역할을 하는 오브젝트를 이용하게 해준다.
이를 통해서 다른 인터페이스를 가진 로우레벨의 기술을 변경하거나 확장해가면서 사용할 수 있다. - 다섯 번째 활용 방법은 프록시 패턴을 적용하는 것이다.
필요한 시점에 실제 사용할 오브젝트를 초기화하고 리소스를 준비해주는 지연된 로딩을 적용하려면 프록시가 필요하다.
원격 오브젝트를 호출할 때 마치 로컬에 존재하는 오브젝트처럼 사용할 수 있게 해주는
원격 프록시를 적용하려고 할 때도 프록시가 필요하다. 두 가지 방법 모두 DI를 필요로 한다.
이 외에도 웹 서비스, REST 호출, HTTP 방식의 호출 등 다양한 리모팅 기술이 모두 DI를 통해 이뤄진다. - 여섯 번째 활용 방법은 템플릿/콜백 패턴을 적용하는 것이다.
반복적으로 등장하지만 항상 고정적인 작업 흐름과 그 사이에서 자주 바뀌는 부분을 분리해서 템플릿과 콜백으로 만들고
이를 DI 원리를 응용해 적용하면 지저분하게 매번 만들어야 하는 코드를 간결하게 만들 수 있다.
콜백을 템플릿에 주입하는 방식으로 동작하게 하는 것은 DI의 원리에 가장 충실한 응용 방법이다. - 일곱 번째 활용 방법은 DI 할 오브젝트의 생명주기를 제어할 수 있다는 것이다.
DI를 프레임워크로 이용한다는 건 DI 대상 오브젝트를 컨테이너가 관리한다는 의미이므로 오브젝트의 생성부터 관계설정,
이용, 소멸에 이르기까지의 모든 과정을 DI 컨테이너가 주관하기 때문에 그 오브젝트의 스코프를 자유롭게 제어할 수 있다.
이를 통해 싱글톤으로 오브젝트를 만들어서 사용하고 관리하기 때문에
클래스 자체를 싱글톤을 고려하지 않고 자유롭게 설계할 수 있다.
때론 단일 싱글톤 외에도 다양한 스코프를 갖는 오브젝트를 만들어 DI에 사용할 수 있다. - 여덟 번째 활용 방법은 다른 오브젝트와의 사이에서 일어나는 일을 테스트를 위해 조작할 수 있도록 하는 것이다.
여타 오브젝트와 협력해서 동작하는 오브젝트를 효과적으로 테스트하기 위해서는 가능한 고립시켜야 한다.
그래야만 테스트 대상인 오브젝트의 기능에 충실하게 테스트가 가능하다.
자칫 다른 오브젝트와의 협력을 통해 동작하는 기능을 다 허용하고 테스트하다가는
한 번에 수십 개의 오브젝트와 DB, 환경까지 모두 테스트해야 하는 부담을 안을 수 있다.
그래서 테스트할 대상이 의존하는 오브젝트를,
테스트를 목적으로 만들어진 스텁 또는 목 오브젝트 같은 테스트 대역으로 대체하면 유용하다.
- DI의 가장 대표적인 적용 방법은 바로 의존 대상의 구현을 바꾸는 것이다. 디자인 패턴의 전략 패턴이 대표적인 예이다.
- 그 외에도 DI의 활용 방법은 다양하며 실전에서 얼마나 DI라는 개념의 활용도가 다양한지 알 수 있다.
- GoF의 디자인 패턴 중에서
인터페이스를 두고 오브젝트를 분리하는 구조를 가진 오브젝트 스코프의 패턴은 DI의 구조에 대부분 잘 들어맞는다. - 그런 패턴의 장점들을 애플리케이션 전 영역에서 간단한 설정만으로 자연스럽게 적용할 수 있게 만들어주는 것이 바로 DI다.
- GoF의 디자인 패턴 중에서
애스펙트 지향 프로그래밍(AOP)
- AOP도 스프링의 3개 가능기술의 하나이다.
- AOP는 객체지향 기술의 한계와 단점을 극복하도록 도와주는 보조적인 프로그래밍 기술이다.
AOP를 사용하면 그 결과로 OOP를 더욱 OOP답게 만들 수 있다. - 스프링의 목적인, POJO만으로 엔터프라이즈 애플리케이션을 개발하면서도
엔터프라이즈 서비스를 선언적으로 제공하는데 반드시 필요한 것이 바로 AOP 기술이다. - IoC/DI를 이용해서 POJO에 선언적인 엔터프라이즈 서비스를 제공할 수 있지만
일부 서비스는 순수한 객체지향 기법만으로는 POJO의 조건을 유지한 채로 적용하기 힘들다.
바로 이런 문제를 해결하기 위해 AOP가 필요하다. - 스프링의 AOP는 스프링이 POJO 프로그래밍을 지원하려는 그 핵심 목적을 위해 중요한 역할을 하고 있다.
- AOP는 객체지향 기술의 한계와 단점을 극복하도록 도와주는 보조적인 프로그래밍 기술이다.
- AOP를 자바 언어에 적용하는 기법은 크게 두 가지로 분류할 수 있다.
- 첫 번째는 스프링과 같이 다이내믹 프록시를 사용하는 방법이다.
이 방법은 기존 코드에 영향을 주지 않고 부가기능을 적용하게 해주는 데코레이터 패턴을 응용한 것이다.
자바의 객체지향 패턴을 활용한 방법이기 때문에 만들기 쉽고 적용하기 간편하다.
대신 인터페이스와 DI를 활용하는 데코레이터 패턴이 기반 원리이기 때문에
부가기능을 부여할 수 있는 곳은 메소드의 호출이 일어나는 지점뿐이라는 제약이 있다.
스프링의 기본적인 AOP 구현 방법은 다이내믹 프록시를 이용하는 프록시 AOP 방식이다.
엔터프라이즈 개발에서 필요로 하는 AOP는 대부분이 이 프록시 방식의 AOP면 된다. - 두 번째는 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법이다.
AspectJ라는 유명한 오픈소스 AOP 툴이 있다. 이는 강력한 고급 기능을 가진 AOP를 제공한다.
AspectJ는 프록시 방식의 AOP에서는 불가능한 다양한 조인 포인트를 제공한다.
메소드 호출 뿐만 아니라 인스턴스 생성, 필드 액세스, 특정 호출 경로를 가진 메소드 호출 등에 부가기능을 제공할 수 있다.
대신 이러한 고급 AOP 기능을 적용하려면 자바 언어와 JDK의 지원만으로는 불가능하므로
AOP 컴파일러를 이용한 빌드 과정을 거치거나, 클래스가 메모리로 로딩될 때 바이트 코드를 조작하는 방법이 필요하다.
그만큼 사용하기 까다롭고 번잡하지만 경우에 따라 프록시 방식의 AOP로는 할 수 없는 작업을 위해 사용해야 한다.
- 첫 번째는 스프링과 같이 다이내믹 프록시를 사용하는 방법이다.
- AOP를 본격적으로 적용하기에는 그 성격이 자바의 일반적인 개발 방법과는 상당히 다르기 때문에
익숙하지 않은 상태라면 차근차근 단계를 밟아 AOP를 도입하는 접근 방법이 좋다.- 일단 처음에는 스프링이 미리 만들어서 제공하는 AOP 기능을 그대로 가져다 적용하는 것으로 시작한다.
스프링이 직접 제공하는 대표적인 AOP는 바로 트랜잭션이다.
AOP 설정을 통해 트랜잭션이 어떻게 오브젝트에 투명하게 적용되는지 관찰해보고, AOP의 특성과 동작원리를 이해한다.
도메인 오브젝트에 DI를 자동적용해주는 AOP 기능인 @Configurable 애노테이션 또한
스프링이 미리 준비해서 제공하는 대표적인 AOP 기능이다. - 다음 단계로는 애플리케이션 전체적으로 이용 가능한 것을 AOP 담당자 관리하에 적용해보는 것이다.
대표적으로 비즈니스 로직을 가진 오브젝트에 대한 보안, 특정 계층의 오브젝트 이용 전후의 작업 기록을 남기는 로깅,
데이터 추적을 위한 트레이싱, 특정 구간의 실시간 성능 모니터링과 같은 정책적인 기능에 AOP를 이용하는 것이다.
이러한 부분은 개발 정책이나 기준이 바뀌면 지금까지 작업한 것을 모두 수정하고 일일이 검증해야 하는
큰 부담이 있으므로 AOP를 이용해 한 번에 적용한다면 일반 개발자의 작업에는 전혀 영향을 주지 않을 수 있다.
또한 AOP는 언제든지 기능을 추가하거나 제거할 수 있으므로 이런 특징을 잘 이용하면 운영 중에 필요한 기능 외에
개발 가이드라인이나 표준을 따라서 코드가 작성되어 있는지를 검증하는 작업을 AOP를 이용해 할 수 있다. - 첫 번째와 두 번째 단계를 거쳐서 AOP에 어느 정도 친숙해지고, 그 장단점과 응용전략, 위험성 등을 어느정도 이해했다면
이제는 개발자 스스로가 AOP를 활용할 수 있는 단계로 넘어갈 수 있다.
이전 단계에서는 애플리케이션 전체적으로 적용되는 정책 AOP를 위주로 했다면
이제는 개발자가 구현하는 기능에 적용하면 유용한 세부적인 AOP를 이용할 수 있다.
즉, 큰 범위에 걸쳐서 적용되는 기능은 아니지만 한 모듈 또는 특정 기능 안에서 AOP로 분리하면 유용한 것들이 있다.
- 일단 처음에는 스프링이 미리 만들어서 제공하는 AOP 기능을 그대로 가져다 적용하는 것으로 시작한다.
포터블 서비스 추상화(PSA)
- 세 번째 가능기술은 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 PSA다.
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다.
특정 환경과 기술에 종속적이지 않다는 것은 POJO 코드가 그런 기술에 직접 노출되어 만들어지지 않는다는 말이다. - 스프링은 이를 위해 일관성 있는 서비스 추상화 기술을 제공한다.
엔터프라이즈 개발에 사용되는 다양한 기술에 대한 서비스 추상화 기능을 제공하며
어떤 것은 AOP나 템플릿/콜백 패턴과 결합돼서 사용되기 때문에 직접적으로 서비스를 이용할 필요가 없고
대신 설정을 통해 어떤 종류의 기술을 사용할지 지정해줘야 한다. - 예를 들어 트랜잭션 서비스 추상화는 대부분 AOP를 이용해 적용하기 때문에 직접 코드를 만들지 않는다.
대신 설정에서는 스프링의 트랜잭션 추상화 인터페이스인 PlatformTrasactionManager를 구현한
구체적인 서비스 클래스를 빈으로 등록해줘야 한다.
이때 JTA를 이용해 트랜잭션을 적용하고 싶다면 JtaTrasactionManager를 빈으로 등록하고
JTA에 대한 설정을 프로퍼티로 넣어주면 된다. - 직접 스프링이 제공하는 API를 사용해서 만드는 경우도 있다.
- 예를 들어 OXM이나 JavaMail을 이용한다면 스프링이 정의한 추상 API를 이용해 코드를 작성한다.
그리고 구체적인 기술과 설정은 XML 파일 안에서 지정한다.
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않아야 한다.
- 서비스 추상화를 위해 필요한 기술은 DI뿐이다.
- 결국 DI 응용 방법의 한 가지이므로 DI를 적극 활용해서 개발한다면 서비스 추상화는 자연스럽게 만들어 쓸 수 있다.
- 또한 서비스 추상화는 단지 구체적인 기술에 종속되지 않게 하기 위해서만 사용되는 것이 아니라
테스트가 어렵게 만들어진 API나 설정을 통해 주요 기능을 외부에서 제어하게 만들고 싶을 때도 이용할 수 있다.
'Java-Spring > 토비의 스프링 3.1' 카테고리의 다른 글
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링 프로젝트 시작하기 (1) (0) | 2024.04.22 |
---|---|
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링 프로젝트 시작하기 (0) (0) | 2024.04.22 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (3) (0) | 2024.04.17 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (2) (0) | 2024.04.17 |
[토비의 스프링 3.1] Vol.1 스프링의 이해와 원리 - 스프링이란 무엇인가? (1) (0) | 2024.04.16 |