530 likes | 789 Views
1. 4 제어의 역전 (Inversion of Control, IoC ). 1.4.1 오브젝트 팩토리 (Object Factory). UserDaoTest 에서 “ 관계설정 기능 ” 의 분리 필요 UserDaoTest 는 테스트 본연의 기능으로 한정 팩토리 (Factory) 객체의 생성 방법을 결정하고 생성한 객체를 돌려주는 객체. 1.4.1 오브젝트 팩토리 (Object Factory). 팩토리를 사용하는 UserDaoTest UserDao 가 어떻게 만들어졌는지 신경쓰지 않음
E N D
1.4.1 오브젝트 팩토리(Object Factory) • UserDaoTest에서 “관계설정 기능”의 분리 필요 • UserDaoTest는 테스트 본연의 기능으로 한정 • 팩토리(Factory) • 객체의 생성 방법을 결정하고 생성한 객체를 돌려주는 객체
1.4.1 오브젝트 팩토리(Object Factory) • 팩토리를사용하는 UserDaoTest • UserDao가 어떻게 만들어졌는지 신경쓰지 않음 • 자신의 본래 관심사인 테스트에 집중 가능
1.4.1 오브젝트 팩토리(Object Factory) • 설계도로서의 팩토리 • 어플리케이션을 구성하는 컴포넌트들의 구조와 관계를 정의 • 어플리케이션의 컴포넌트 역할을 하는 객체들로부터 어플리케이션의 구조를 결정하는 객체를 분리함
1.4.1 오브젝트 팩토리(Object Factory) • 소스코드의 배포와 활용 • 어플리케이션을 구성하는 컴포넌트들의 구조와 관계를 정의 클래스와 api설명서만 제공 클래스만 제공하거나샘플로 소스까지 제공할 수 있음 소스를 필수로 제공
1.4.2 오브젝트 팩토리의 활용 • 중복 코드 발생 수정 • 다양한 DAO의 DAO 생성 메소드의 추가로 인해 발생하는 중복 List1-17 List1-16 ↳
1.4.3 제어권 이전을 통한 제어관계 역전 • 전통적인 제어권 소유 방법 • main() 메소드에서활용할 객체 결정 및 생성 • 각 객체들은 주체적으로 자신 또는 다른 객체들의 메소드들을 호출 • 즉, 각 객체들이 프로그램의 흐름을 결정하거나 사용할 객체를 구성하는 작업에 능동적으로 참여 • 초난감UserDao소스 • main() 메소드가UserDao객체 생성 • UserDao가 능동적으로 자신이 사용할 ConnectionMaker객체 결정 및 생성
1.4.3 제어권 이전을 통한 제어관계 역전 • 제어의 역전 (Inversion of Control) • 임의의 객체는 자신이 사용할 다른 객체를 선택/생성하지 않는다. • 객체 스스로가 향후 어떻게 만들어지고 어디서 사용될지 알 수 없다. • 모든 제어 권한은 다른 객체에게 위임 • 제어의 역전 활용 예 • 서블릿(JSP) 등의 컨테이너 안에서 동작하는 구조 • 서블릿을 개발해서 서버에 배포는 가능하지만 그 실행은 컨테이너가 제어함 • 스프링을포함한 각종 프레임워크 • 프레임워크에 올려지는 각종 프로그램들은 프레임워크에서 직접 흐름이 제어된다. • 프레임워크라는 이름 자체가 IoC를 사용하고 있다는 뜻
1.4.3 제어권 이전을 통한 제어관계 역전 • UserDao와 DaoFactory에서의 제어의 역전 • 어플리케이션의 핵심 객체인 UserDao는 수동적인 존재 • UserDao자신도 팩토리에 의해 생성 • 자신이 활용할 ConnectionMaker도 팩토리에 의해 생성되어 공급됨 • DaoFactory는 가장 단순한 IoC프레임워크 • IoC의 장점 • 프로그램 소스 코드의 유연성 및 확장성 증가 • 스프링과 IoC • IoC는 스프링에서 제공하는 모든 기능의 기초가 되는 기반기술
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC • 빈 (Bean) • 스프링이 제어권을 가지고 직접 생성하고 관계를 부여하는 수동적인 제어의 역전이 적용된 객체 • 빈 팩토리(Bean Factory) • 빈의생성, 등록, 조회 및 관계설정 제어를 담당하는 IoC객체 • 보통은 빈 팩토리를 직접 사용하지 않고 이를 확장한 어플리케이션 컨텍스트(Application Context)를 이용함 • 스프링에 o.s.beans.factory.BeanFactory인터페이스가 존재
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC • 애플리케이션 컨텍스트(Application Context) • 빈팩토리에 각종 부가기능 서비스를 추가로 제공하는 빈 백토리 확장 IoC객체 • 애플리케이션 전반에 걸친 구성요소의 제어 작업을 담당하는 IoC엔진 • 스프링에 o.s.context.ApplicationContext인터페이스 존재 o.s.beans.factory.BeanFactory 상속 o.s.context.ApplicationContext
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC • 설정 정보/설정 메타 정보 (Configuration Metadata) • 애플리케이션 컨텍스트 또는 빈 팩토리가IoC를 적용하기 위하여 사용하는 메타 정보 • 애플리케이션의 형상 정보 또는 구성 정보 • 애플리케이션의 전체 그림이 그려진 청사진 (Blueprints) • 컨테이너(Container)또는 IoC컨테이너 • IoC방식으로 빈을 관리하는 의미에서 애플리케이션 컨테이너나 빈 팩토리를 일컫는 또 다른 단어 • 스프링 프레임워크 • 스프링이 제공하는 모든 기능을 통합하여 말할 때 사용하는 단어 스프링 컨테이너 ≒ IoC컨테이너 ≒ 컨테이너 ≒ IoC엔진 ≒ 애플리케이션 컨텍스트≒ 빈 팩토리
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC • 스프링 컨테이너가 사용할 설정정보를 담은 DataFactory클래스 • Java의 annotation 을 활용하여 설정정보를 기술
1.5.1 오브젝트 팩토리를 이용한 스프링 IoC • @Configuration이 붙은 자바 코드 설정정보를 활용하는 애플리케이션 컨텍스트 생성 및 활용 • AnnotationConfigApplicationContext클래스 활용 userDao빈 이름 지정 @bean으로 지정된 userDao() 메소드 호출 리턴 타입을 지정. 명시적 캐스팅이 필요없어짐
1.5.2 애플리케이션 컨텍스트의 동작방식 • ApplicationContext의 역할 • 애플리케이션에서 IoC를 적용해서 관리할 모든 객체 대한 생성과 관계설정을 담당 • 하지만, 직접 객체를 생성하고 관계를 맺는 코드는 외부의 설정정보(@Configuration 이 붙은 DaoFactory)를 통해 얻는다.
1.5.2 애플리케이션 컨텍스트의 동작방식 • ApplicationContext 활용장점 • 클라이언트는 구체적인 팩토리 클래스를 사용할필요가 없다. • 오브젝트 팩토리가 많아져도 문제 없음 • 이후 DaoFactory를 대체할 XML 방법 활용하면 더욱 편리함 • 종합적인 IoC서비스를 제공받을 수 있다. • 객체 자동생성, 객체 후처리, 정보 조합, 설정 방식의 다변화, 인터셉팅등의 기능 활용 • 빈을 검색하는 다양한 방법을 제공받을 수 있다.
1.6.0 싱글톤레지스트리 • DaoFactory 직접사용 vs. 애플리케이션 컨텍스트 사용 애플리케이션 컨텍스트는 각각의 빈에 대해 Singleton으로 저장하고 관리하는 Singleton Registry이다.
1.6.1 싱글톤레지스트리로서의 애플리케이션 컨텍스트 • 클라이언트/서버 구조에서의 SingletonRegistry를 사용하지 않는다면… • 상황 가정 • 요청 한개당5개의 객체 생성 • 초당 500번의 요청이 들어옴 • 결과 • 초당 2500개의 새로운 객체 생성 • 한 시간이면 9백만개의 새로운 객체 생성 • 자바의 Garbage Collection 성능이 아무리 좋아도 서버의 자원 사용량이 매우 높아짐 • 서버의 동작 방식 (서블릿 동작 방식) • 서블릿 클래스당 하나의 객체만 생성 • 사용자 요청당 스레드를 생성하여 멀티스레드 형태로 해당 객체를 공유하여 활용
1.6.1 싱글톤레지스트리로서의 애플리케이션 컨텍스트 • 전통적인 자바에서의 Singleton 패턴 • 클라이언트/서버 환경에서 권장되는 서버 코딩 방법 패턴 • 전형적인 Singleton 패턴 구현 형태
1.6.1 싱글톤레지스트리로서의 애플리케이션 컨텍스트 • Singleton 패턴의 한계 • private 생성자를 갖고 있기 때문에 해당 클래스는 상속 불가 • 객체 지향적 설계의 장점을 활용하기가 어려움 • Static 필드와 메소드를 활용하는 것도 객체 지향적 설계에 위배됨 • 테스트 프레임워크에서의 활용 어려움 • 오브젝트 주입이 불가 IoC활용 못함 테스트의 어려움 • 분산 서버 환경에서는 Signleton패턴을 활용하더라도 여러 개의 독립된 객체 생성 가능 • 여러 개의 JVM에 분산 배치된 서버 애플리케이션 • Static 필드는 Global State를 자연스럽게 만들기 때문에 멀티스레딩환경에서 여러 위험에 처할 수 있음
1.6.1 싱글톤레지스트리로서의 애플리케이션 컨텍스트 • 스프링의 Singleton Registry • private 생성자/static 필드 및 메소드가 없는 평범한 클래스 객체에 대해서도 Singleton으로 활용하게 해줌 • 즉, 고전적인 Singleton 패턴을 대신하여 Singleton 객체를 생성하고 관리해주는 레지스트리 • 앞에서 언급한 한계점을 대부분 극복
1.6.2 싱글톤과 오브젝트의 상태 • 스프링의 Singleton 빈 (Bean) 객체 활용시 주의점 • 객체의 인스턴스 필드는 읽기 전용으로만 사용해야 함 • 잘못된 코딩 방식 • 대부분의 읽기/쓰기 변수는 메소드 내의 로컬 변수로 정의하거나 파라미터로 주고 받아야 함
1.6.3 스프링 빈의 스코프 • 빈객체 Scope • 빈 객체가 생성되고, 존재하고, 적용되는 시간/공간적인 범위 • 스프링 빈 객체의 기본 Scope • Singleton Scope • 컨테이너 내에 한 개의 객체로 생성 • 강제로 제거하지 않는 한 스프링 컨테이너 내에 계속해서 유지됨 • 스프링 빈 객체의 다른 Scope • Prototype: 빈 요청할 때 마다 새로운 객체 생성 • Request: http 요청때 마다 새로운 객체 생성 • Session: http 세션과 동일한 Scope 유지 • 본교재의 10장에서 자세히 다루게 됨
1.7.1 제어의 역전 (IoC)와 의존 관계 주입 (DI) • 제어의역전 (IoC) • 설계 패턴 (Design Pattern)에서 사용되는 광범위하게 활용되는 용어 • 스프링이 제공하는 기능적 특징을 명확하게 설명 못함 • 의존관계 주입 (DI, Dependency Injection) • 스프링에서 객체간의 관계설정 의도를 명확히 표현하는 용어 • 스프링을 다른 프레임워크와 차별화되어서 제공해주는 기능은 DI 라는 용어를 사용할 때 분명하게 드러남
1.7.2 런타임 의존관계 설정 • 의존 관계 (Dependency) • 클래스의의존관계 UML 다이어그램 • “A가 B에 의존한다“ • B의 기능이 추가 및 변경되거나 메소드 형식이 변경되면 그 영향이 A로 전달됨 • 의존관계에는 방향성이 있다.
1.7.2 런타임 의존관계 설정 • UserDao의 의존관계 • 인터페이스를 통한 느슨한 결합을 갖는 의존관계 • ConnectionMaker의 변경사항은 UserDao에 직접적인 영향을 준다. • DConnectionMaker의 변경사항은 UserDao에 영향을 주지 않는다 낮은결합도 • 의존 오브젝트 (Dependent Object) • 런타임시에 의존관계를 맺는 대상 객체 • UserDao의 의존 오브젝트는 DConnectionMaker객체
1.7.2 런타임 의존관계 설정 • 스프링에서의 의존관계 주입 조건 • 클래스 모델이나 코드에서는 런타임 시점의 의존관계가 잘 드러나지 않는다. • 인터페이스 사용 • 런타임 시점의 의존관계는 스프링 컨테이너 (애플리케이션 컨텍스트)같은 제 3의 객체가 결정한다. • 스프링 컨테이너 = DI 컨테이너 • 의존관계는 사용할 (의존할) 객체에 대한 레퍼런스를 제 3의 객체가 제공(주입, DI)해줌으로써 만들어진다.
1.7.2 런타임 의존관계 설정 • UserDao의 의존관계 주입 • DI 컨테이너에서 활용할 의존관계 주입을 위한 코드
1.7.2 런타임 의존관계 설정 • UserDao의 의존관계 주입 • 런타임 시에 의존관계 주입을 수행하는 주체는 제 3의 존재이다. • 예를 들어 DaoFactory가 담당 • 의존관계 주입을 담당하는 컨테이너, DI 컨네이너라고 부른다. • 런타임 시의 의존관계 주입과 사용되는 의존관계
1.7.2 런타임 의존관계 설정 • 의존관계 검색 (vs. 의존관계 주입) • 의존관계 검색 (DL, Dependency Lookup)을 이용하는 UserDao생성자 • 애플리케이션 컨텍스트에게getBean() 메소드 활용 • 의존관계 검색(DL)은 다소 코드가 지저분하다. • 가능하면 의존관계 주입 (DI) 사용
1.7.2 런타임 의존관계 설정 • 반드시 의존관계검색을 활용해야 할 때 • main()과 같은 애플리케이션 수행 메소드 • 애플리케이션을 기동하는 시점에서는 어쩔 수 없이 최소한 한번은 DL을 통해 객체를 가져와야 한다. • 스태틱메소드인main()에서는 DI를 통해 객체를 주입받을 수 없음 • 스프링 빈 (의존 오브젝트)을 사용할 객체가 빈이 아닐 때 • UserDao는 빈이 아니고 ConnectionMaker만 빈일 때 • 즉, 의존관계주입 (DI)을받기원하는 객체는 자신도 컨테이너가 관리하는 빈이 되어야 한다. • 의존관계 주입은 DI 컨네이터가 수행
1.7.4 의존관계 주입의 응용 • 사례 1. 개발용과 운영용 객체의 교환 • 개발용 ConnectionMaker생성 코드 • 개발 중에는 로컬 DB를 사용 • 운영용 ConnectionMaker생성 코드 • 운영서버에 배포할 시에는서버가 제공하는 DB를 사용 • 배포시점에 오른쪽과 같이 한 줄 변경
1.7.4 의존관계 주입의 응용 • 사례 2. 부가기능 추가 • 연결횟수 카운팅 기능이 있는 DB 연결 객체 반환 클래스
1.7.4 의존관계 주입의 응용 • 사례 2. 부가기능 추가 • CountingConnectionMaker의존관계가 추가된 DI 설정용 클래스 • 런타임 오브젝트 의존관계
1.7.4 의존관계 주입의 응용 • 사례 2. 부가기능 추가 • CountingConnectionMaker에 대한 테스트 클래스
1.7.5 메소드를 이용한 의존관계 주입 • 다양한 의존관계 주입 방법 • 생성자를 이용한 주입 • setter메소드를 이용한 주입 • 반드시 setXxx(…) 라는 메소드 이름 형태를 지님 • 한 개의 파라미터 한번에 하나의 객체만 주입받음 • 가장 많이 활용되어 왔음
1.7.5 메소드를 이용한 의존관계 주입 • 다양한 의존관계 주입 방법 • setter 메소드를 이용한 DI를 사용하는 팩토리메소드 • 일반 메소드를 이용한 주입 • 메소드 이름을 다양하게 정할 수 있음 • 여러 개의 파라미터 한번에 여러 개의 객체를 주입 받을 수 있음
1.8.0 XML을 이용한 설정 • 설정 정보 구성의 다변화 • 자바 코드를 통한 설정 정보(DaoFactory) 구성의 단점 • DI 구성이 변경될 때 마다 재컴파일 과정 필요 • 그러한 설정 정보 구성은 대부분 틀에 박힌 뻔한 구조 • 대안 XML 활용 • 단순 텍스트 파일 • 컴파일의 별도 과정 요구되지 않음 • XML스키마를 이용하여 정해진 포맷대로 작성되었는지 쉽게 확인 가능
1.8.1 XML 설정 • 클래스 설정과 XML 설정의 대응항목 • 빈 설정 • connectionMaker() 메소드의<bean> 태그 전환
1.8.1 XML 설정 • 의존 관계 주입 • 빈 객체에 setter 메소드 존재 • userDao빈 객체 선언 및 의존관계 동시 주입 • 기존 클래스 파일과 XML 설정의 대응
1.8.1 XML 설정 • applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="myConnectionMaker" class="springbook.user.dao.DConnectionMaker“ /> <bean id="userDao" class="springbook.user.dao.UserDao"> <property name="connectionMaker" ref="myConnectionMaker" /> </bean> </beans> • 완성된 XML 설정 • 파트 설명 • XML 선언 • beans 루트엘리먼트: 설정 파일임을 지정함 • beans 루트 엘리먼트 속성으로 XML 스키마 지정 • myConnectionMaker빈 객체 선언 • userDao빈 객체 선언 및 의존 관계 주입
1.8.1 XML 설정 • 전략 패턴을 XML 설정에 기술하는 방법 • 동일한 인터페이스를 구현한 의존 오브젝트들을 여러 개 정의해 두고 그 중에서 원하는 것을 골라서 DI 하는 방법
1.8.2 XML 설정을 이용하는 애플리케이션 컨텍스트 //ApplicationContext context // = new AnnotationConfigApplicationContext(DaoFactory.class); ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml"); //daoContext.xml이 springbook.user.dao패키지 안에 있을 때 ApplicationContext context = new GenericXmlApplicationContext("springbook/user/dao/daoContext.xml"); //UserDao.class로 부터의 상대위치를 지정할 때 ApplicationContext context = new ClassPathXmlApplicationContext("daoContext.xml", UserDao.class); • 애플리케이션 컨텍스트 설정 코드
1.8.3 DataSource인터페이스로 변환 • DataSource인터페이스 및 구현 클래스 사용 • ConnectionMaker대신 DB 커넥션 기능을 제공하는 전통적인 자바 및 스프링 라이브러리 사용 권장 • DataSource인터페이스
1.8.3 DataSource인터페이스로 변환 • DataSource인터페이스를 사용하는 UserDao
1.8.3 DataSource인터페이스로 변환 • DaoFactory를 통한 설정 • DataSource인터페이스를 구현한클래스 사용 • org.springframework.jdbc.datasource.SimpleDriverDatasource