-
8장) 8.3 POJO 프로그래밍 ~ 8.4 스프링의 기술Java & Spring/토비의 스프링 3.1 2021. 9. 7. 17:04반응형
8장 스프링이란 무엇인가?
8.3 POJO 프로그래밍
- 스프링의 기술적 지향점
- 스프링의 정수는 엔터프라이즈 서비스 기능을 POJO에 제공하는 것
- 엔터프라이즈 서비스는 보안, 트랜잭션과 같은 엔터프라이즈 시스템에서 요구되는 기술
- 엔터프라이즈 서비스 기술과 POJO라는 애플리케이션 로직을 담은 코드를 분리했다는 뜻
8.3.1 스프링의 핵심: POJO
- 스프링의 핵심은 POJO 프로그래밍
- 스프링 애플리케이션은 두 가지로 구분
- POJO를 이용해 만든 애플리케이션 코드
- POJO가 어떻게 관계를 맺고 동작하는지 정의해놓은 설계정보
- 이런 DI 개념을 애플리케이션 전반에 걸쳐 적용하는 것이 스프링의 프로그래밍 모델
- 스프링의 주요 기술인 IoC/DI, AOP, PSA(Portable Service Abstraction)은 애플리케이션을 POJO로 개발할 수 있게 해주는 가능기술
8.3.2 POJO란 무엇인가
- POJO는 Plain Old Java Object의 첫 글자를 따서 만든 약자
8.3.3 POJO의 조건
- POJO 프로그래밍이 충족되는 조건
- 특정 규약에 종속되지 않는다
- POJO는 자바 언어와 꼭 필요한 API 외에는 종속되지 않아야 함
- EJB2 같이 특정 규약에 따라 비즈니스 컴포넌트를 만드는 경우는 POJO가 아님
- 스트럿츠 1과 같이 특정 클래스를 상속해서 만들어야 하는 규약이 있는 경우도 POJO가 아님
- 특정 규약을 따라 만들게 하는 경우 자바의 단일 상속 제한 때문에 객체지향 설계 기법을 적용하기 어려워지고, 규약이 적용된 환경에 종속적이라 다른 환경으로 이전이 힘듦
- 객체지향 설계의 자유로운 적용이 가능한 오브젝트여야만 POJO라고 함
- POJO는 자바 언어와 꼭 필요한 API 외에는 종속되지 않아야 함
- 특정 환경에 종속되지 않는다
- 특정 환경이 의존 대상 검색 방식에 종속적이라면 POJO라고 할 수 없음
- 특정 벤더 서버나 특정 프레임워크 안에서만 동작하는 코드를 사용하는 경우
- 환경에 종속적인 클래스나 API를 직접 쓴 경우
- 순수한 애플리케이션 로직을 담은 오브젝트 코드가 특정 환경에 종속되게 만드는 경우 등
- POJO는 환경에 독립적
- 특히, 비즈니스 로직을 담고 있는 POJO 클래스는 웹 환경정보나 웹 기술을 담은 클래스나 인터페이스를 사용하면 안됨
- 직접적으로 웹이라는 환경으로 제한해버리는 오브젝트나 API에 의존하면 안됨
- 비즈니스 로직을 담은 코드에 HttpServletRequest나 HttpSession, 캐시 관련 API 등
- 특정 환경이 의존 대상 검색 방식에 종속적이라면 POJO라고 할 수 없음
- 특정 규약에 종속되지 않는다
- 메타정보를 추가하는 애노테이션을 사용하는 경우
- 코드로 표현하기 적절하지 않은 부가정보를 담고, 환경에 종속되지 않는다면 POJO라고 볼 수 있음
- 애노테이션이나 엘리먼트 값에 특정 기술이나 환경에 종속적인 정보가 담긴다면 POJO가 아님
- 코드로 표현하기 적절하지 않은 부가정보를 담고, 환경에 종속되지 않는다면 POJO라고 볼 수 있음
- 단순하게 자바 문법을 지키고, 순수한 JavaSE API만 사용했다고 POJO가 아니라, 객체지향적인 자바 언어의 기본에 충실하게 만들어야 POJO라고 할 수 있다
- 객체지향적인 원칙에 충실하며, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 POJO라고 부름
- POJO에 애플리케이션 핵심 로직과 기능을 담아 설계하고 개발하는 방법이 POJO 프로그래밍
8.3.4 POJO의 장점
- POJO가 될 수 있는 조건이 모두 POJO의 장점
- 특정 기술과 환경에 종속되지 않는 오브젝트는 깔끔한 코드가 될 수 있음
- 자동화된 테스트에 유리
- 객체지향적인 설계를 자유롭게 적용할 수 있음
- 스프링은 자바 언어의 객체지향 설계와 구현 방식이 그 어떤 새로운 기술과 환경, 툴보다 더 실제 프로젝트를 성공시키는 데 중요한 요소라고 여기고 개발
8.3.5 POJO 프레임워크
- POJO 프레임워크
- 스프링 프레임워크, 하이버네이트가 대표적인 POJO 프레임워크
- 스프링은 비즈니스 로직의 복잡함과 엔터프라이즈 기술의 복잡함을 분리해서 구성하지만, 자신은 기술영역에만 관여하고 비즈니스 로직을 담당하는 POJO에서는 모습을 감춤
- 데이터 엑세스 로직이나 웹 UI 로직을 다룰 때만 최소한으로 관여
- POJO 프로그래밍을 잘하기 위한 방법
- 객체지향 분석과 설계에 대한 지식을 습득하고 훈련
- 자바 언어와 JVM 플랫폼, JDK API 사용법을 잘 알아야 함
- 디자인 패턴과 구현 패턴, 리팩토링 기술 필요
- 스프링은 엔터프라이즈 기술보다는 객체지향 설계와 개발의 원리에 집중할 수 있는 기회를 제공하는 역할
8.4 스프링의 기술
- 스프링에서 POJO 프로그래밍을 지원하는 세 가지 기능 기술
- IoC/DI
- AOP
- PSA
- 스프링의 기술들은 스프링 프레임워크가 만들어진 진정한 목표인 POJO 기반의 엔터프라이즈 개발을 편리하게 해주는 도구일 뿐
- 위의 세 기능 기술이 객체지향 원리를 충실히 적용해서 나온 결과
- 스프링이 직접 제공하지 않는 기술에 대해서도 PSA를 적용할 줄 알아야함
8.4.1 제어의 역전(IoC) / 의존관계 주입(DI)
- 스프링의 기본 기술이자 핵심 개발 원칙
- AOP와 PSA도 IoC/DI에 바탕을 두고 있음
- 템플릿/콜백 패턴이 적용된 부분도 IoC/DI가 핵심 원리
- DI는 개방 폐쇄 원칙이라는 객체지향 원칙으로 설명됨
- 개방 관점에서는 유연한 확장이 가능
- 폐쇄 관점에서는 재사용이 가능
- ex) A -> B의 의존관계, B는 자유롭게 변경될 수 있음을 의미
- B1,B2,B3로 의존대상이 바뀌어도 A는 그대로 재사용 가능
- DI의 활용 방법
- 핵심기능 변경
- 의존 대상의 구현을 바꾸는 것이 DI의 대표적인 적용 방법
- 실존하는 대상이 가진 핵심기능을 DI 설정을 통해 변경
- 핵심기능의 동적 변경
- 오브젝트의 핵심기능 자체를 바꾸는 것
- 일반 DI를 이용한 변경 방법과 달리 동적으로 매번 다르게 변경 가능
- ex) 사용자 등급에 따라 다른 DataSource를 사용
- 동적인 방식으로 핵심 기능을 변경하는 것은 기술적인 관점에서 다이내믹 라우팅 프록시나 프록시 오브젝트 기법을 활용한 것
- DI가 있기 때문에 적용 가능
- 부가기능 추가
- 핵심기능은 그대로 두고 부가기능을 추가하는 것
- 데코레이터 패턴
- 인터페이스를 두고 사용하게 하고, 실제 사용할 오브젝트는 외부에서 주입하는 DI를 적용해두면 데코레이터 패턴을 쉽게 적용 가능
- 핵심기능과 클라이언트 코드에 영향을 주지 않으면서 부가 기능을 자유롭게 추가 가능
- ex) 트랜잭션 기능 부여
- 부가 기능의 추가 방식을 특정 오브젝트가 아닌 많은 대상으로 일반화해서 사용하면 AOP
- 부가기능을 추가하는 것 또한 DI 덕분이고, DI의 핵심 원칙인 OCP에 충실하게 맞음
- 확장에 열려있다는 것은 전략 패턴처럼 핵심기능을 변경해서 쓰는 수준만 말하는 것이 아님
- 핵심기능은 그대로 두고 부가기능을 추가하는 것
- 인터페이스 변경
- 클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우에도 DI가 유용
- ex) A가 C 오브젝트를 사용을 원함, A는 B인터페이스를 사용하도록 구현되어있고, C는 B를 구현하지 않음
- A가 DI로 B 구현 오브젝트를 받는다면, B 인터페이스를 구현했으면서 내부에서 C를 호출해주는 기능을 가진 어댑터 오브젝트를 만들어 A에 DI하면 사용 가능
- A -> B(C로 위임) -> C
- ex) A가 C 오브젝트를 사용을 원함, A는 B인터페이스를 사용하도록 구현되어있고, C는 B를 구현하지 않음
- 인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록 중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 방법으로 일반화한 것이 PSA
- 클라이언트가 사용하는 인터페이스와 실제 오브젝트 사이에 인터페이스가 일치하지 않는 경우에도 DI가 유용
- 프록시
- 프록시 패턴의 전형적인 응용 방법
- lazy loading을 적용하려면 프록시가 필요함
- 원격 오브젝트를 호출할 때 로컬에 존재하는 오브젝트처럼 사용하게 해주는 원격 프록시 적용에도 프록시가 필요
- 위의 두 가지 모두 DI를 필요
- 프록시 패턴의 전형적인 응용 방법
- 템플릿 콜백
- DI의 특별한 적용 방법
- 고정적인 작업 흐름과 그 사이에 자주 바뀌는 부분을 분리하여 템플릿과 콜백으로 만들고, DI 원리를 응용해 적용
- 콜백을 얼마든지 만들어서 사용할 수 있다는 것은 개방을 통한 유연한 확장성을 보여주는 것이며, 템플릿은 한 번 만들어두면 계속 재사용할 수 있다는 것은 기능 확장에도 변하지 않는다는 OCP 폐쇄 원칙에 잘 들어맞음
- 싱글톤과 오브젝트 스코프
- DI가 필요한 중요한 이유 중 하나는 DI 할 오브젝트의 생명주기를 제어할 수 있다는 것
- DI를 프레임워크로 사용한다는 것은 DI 대상 오브젝트를 컨테이너가 관리한다는 의미
- 모든 과정을 DI 컨테이너가 주관 ~> 오브젝트 스코프를 자유롭게 제어
- 싱글톤
- 전형적인 싱클톤 패턴은 오브젝트에 많은 제약 ~> 권장 X
- 컨테이너가 오브젝트를 관리하는 IoC 방식이 권장
- 임의의 생명주기를 갖는 오브젝트에도 유용
- 싱글톤
- 테스트
- 여타 오브젝트와 협력해서 동작하는 오브젝트를 효과적으로 테스트하는 방법 ~> 고립
- 다른 오브젝트와의 사이에 일어나는 일을 테스트를 위한 조작이 가능해야함
- Mock 오브젝트, Stub
- 다른 오브젝트와의 사이에 일어나는 일을 테스트를 위한 조작이 가능해야함
- 여타 오브젝트와 협력해서 동작하는 오브젝트를 효과적으로 테스트하는 방법 ~> 고립
- 핵심기능 변경
8.4.2 애스펙트 지향 프로그래밍(AOP)
- OOP 처럼 독립적인 프로그래밍 패러다임이 아님
- AOP와 OOP가 배타적이 아니라는 의미
- 복잡해져가는 애플리케이션의 요구조건과 기술적 난해함을 모두 해결하는 데 한계가 있는데, AOP가 객체지향 기술의 한계와 단점을 극복하도록 도와주는 보조적인 프로그래밍
- 스프링의 목적인 POJO만으로 엔터프라이즈 애플리케이션을 개발하면서도 엔터프라이즈 서비스를 선언적으로 제공하는데 반드시 필요한 것이 AOP
- IoC/DI로 POJO에 선언적 엔터프라이즈 서비스를 제공할 수 있지만, 일부 서비스는 순수한 객체지향 방법만으로 POJO 조건을 유지하기 힘듦
- AOP가 해결책
- AOP의 적용 기법
- AOP를 자바 언어에 적용하는 기법
- 스프링과 같이 다이내믹 프록시를 사용하는 방법
- 기존 코드에 영향을 주지 않고 부가기능을 적용하는 데코레이터 패턴을 응용
- 부가기능을 부여할 수 있는 곳은 메소드의 호출이 일어나는 지점뿐이라는 제약이 존재
- 스프링의 기본적인 AOP 구현 방법이 다이내믹 프록시를 이용하는 프록시 AOP 방식
- 자바 언어의 한계를 넘어서는 언어의 확장을 이용하는 방법
- 오픈소스 AOP 툴 AspectJ
- 프록시 방식의 AOP에서 불가능한 다양한 조인 포인트를 제공
- 별도의 AOP 컴파일러를 이용한 빌드 과정을 거치거나, 클래스가 메모리로 로딩될 때 그 바이트 코드를 조작하는 위빙과 같은 별도의 방법을 이용
- 오픈소스 AOP 툴 AspectJ
- 스프링과 같이 다이내믹 프록시를 사용하는 방법
- AOP를 자바 언어에 적용하는 기법
- AOP 적용 단계
- 미리 준비된 AOP 이용
- 스프링이 미리 만들어 제공하는 AOP 기능을 그대로 가져다 적용
- 트랜잭션이 대표적인 예시
@Configurable
애노테이션으로 도메인 오브젝트에 DI를 자동 적용해주는 것도 AOP 기능- AspectJ를 이용한 AOP피가 반드시 필요
- 스프링이 미리 만들어 제공하는 AOP 기능을 그대로 가져다 적용
- 전담팀을 통한 정책 AOP 적용
- 정책적으로 적용할 만한 기능에 AOP를 이용
- AOP를 이용해 한 번에 적용한다면 일반 개발자의 작업에는 전혀 영향 X
- AOP만 책임지는 소수만 신경 쓰면 해결
- AOP는 언제든 기능을 추가 제거할 수 있기 때문에, 개발 과정에서 정책 검증에 사용하다가 배포 때 제거하는 식으로도 사용 가능
- AOP의 자유로운 이용
- 개발자 스스로가 AOP를 활용하는 단계
- 구현하는 기능에 적용하여 세부적인 AOP를 이용하고, 모듈이나 특정 기능 안에서 AOP로 분리하여 사용하는 것이 유용한 경우를 판단하여 사용
- 미리 준비된 AOP 이용
8.4.3 포터블 서비스 추상화(PSA)
- 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근하게 도움
- POJO로 개발된 코드는 특정 환경이나 구현 방식에 종속적이지 않음
- 스프링은 JavaEE를 기본 플랫폼으로 하는 자바 엔터프라이즈 개발에 주로 사용
- 특정 환경과 기술에 종속적이지 않다는 것이 다양한 JavaEE 기술을 사용하지 않는 다는 뜻이 아니라, POJO 코드가 그런 기술에 직접 노출되어 만들어지지 않는다는 의미
- 이를 위해 스프링이 제공하는 기술이 일관성 있는 서비스 추상화기술
- 설정을 통해 어떤 종류의 기술을 사용할지 지정
- AOP나 템플릿/콜백 패턴과 결합돼서 사용되는 경우, 직접 서비스 사용이 아닌 설정으로 해결
- 직접 스프링이 제공하는 API를 사용해서 만드는 경우
- OXM, JavaMail 등 스프링이 정의한 추상 API를 이용해 코드를 작성 ~> 구체적인 기술과 설정은 XML 파일 안에서 지정
- 직접 서비스 추상화 기법을 적용
- 직접 추상 레이어를 도입하고 일관성 있는 API를 정의해서 사용
- 서비스 추상화를 위해 필요한 기술은 오직 DI
- 테스트가 어렵게 만들어진 API나 설정을 통해 주요 기능을 외부에서 제어하게 만들고 싶을 때도 이용 가능
반응형'Java & Spring > 토비의 스프링 3.1' 카테고리의 다른 글
9장) 9.3 애플리케이션 아키텍처 (vol1 마지막 정리) (226) 2021.09.24 8장) 8.1 스프링의 정의 ~ 8.2 스프링의 목적 (0) 2021.09.07 7장) 7.6 스프링 3.1의 DI (2) 2021.08.30 7장) 7.4 인터페이스 상속을 통한 안전한 기능확장 ~ 7.5 DI를 이용해 다양한 구현 방법 적용하기 (0) 2021.08.20 7장) 7.3 서비스 추상화 적용 (0) 2021.08.08 - 스프링의 기술적 지향점