ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 토비의 스프링 - 1. 오브젝트와 의존관계(2)
    공부일기/스프링 2021. 5. 13. 00:39

    스프링의 IoC

    오브젝트 팩토리를 이용한 스프링 IoC

    • 빈: 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트. 스프링 컨테이너가 생성과 관계설정, 사용 등을 제어해주는 오브젝트
    • 빈 팩토리(애플리케이션 컨텍스트): 빈의 생성과 관계 설정 같은 제어를 담당하는 오브젝트
    • @configuration: 스프링이 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식하게 만드는 애노테이션
    • getBean(): ApplicationContext가 관맇는 오브젝트를 요청하는 메소드. 파라미터 값으로 등록된 빈의 이름과 리턴타입(클래스)을 전달한다.

    애플리케이션 컨텍스트의 동작방식

    • 애플리케이션 컨텍스트는 IoC를 적용해 관리할 모든 오브젝트에 대한 생성과 관계설정을 담당한다. 생성정보와 연관관계 정보는 별도의 설정정보를 통해 얻는다(예제에선 @configuration이 붙은 DaoFactory).
    • 설정정보에서 @bean이 붙은 메소드의 이름을 가져와 빈 목록을 만들어둔다.
    • 클라이언트가 애플리케이션 컨텍스트의 getBean() 메소드 호출 시 자신의 빈 목록에서 요청한 이름이 있는지 찾아 빈을 생성하는 메소드를 호출, 오브젝트를 만들어 클라이언트에게 돌려준다.

    애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점

    1. 클라이언트는 구체적인 팩토리 클래스를 알 필요가 없다.
      오브젝트 팩토리가 아무리 많아지는 경우라도 클라이언트가 알아야 하거나 직접 사용할 필요가 현저히 적다.
      일관된 방식으로 원하는 오브젝트를 가져올 수 있다.
    2. 종합 IoC 서비스를 제공해준다.
      오브젝트의 생성, 관계설정 + 만들어지는 방식, 시점, 전략을 다르게 가져갈 수 있다.
    3. 빈을 검색하는 다양한 방법을 제공한다.
      타입만으로 빈을 검색하거나, 특별한 애노테이션이 설정되어 있는 빈을 찾을 수도 있다.

    스프링 IoC의 용어 정리

    • 빈(bean)
      스프링이 IoC 방식으로 관리하는 오브젝트. 스프링이 직접 생성과 제어를 담당하는 오브젝트만 해당된다.
    • 빈 팩토리(bean factory)
      스프링의 IoC를 담당하는 핵심 컨테이너. 빈의 등록, 생성, 조회, 반환과 부가적인 관리를 담당한다. 보통은 빈 팩토리를 확장한 애플리케이션 컨텍스트를 사용한다.
    • 설정정보/설정 메타정보
      빈 팩토리(애플리케이션 컨텍스트)가 IoC를 적용하기 위해 사용하는 메타정보(configuration). 주로 IoC 컨테이너에 의해 관리되는 오브젝트를 생성 및 구성할 때 사용된다.
    • 컨테이너/IoC 컨테이너
      IoC 방식으로 빈을 관리하는 주체. 컨테이너는 주로 애플리케이션 컨텍스트를 지칭하며, IoC 컨테이너는 주로 빈 팩토리를 지칭한다.
    • 하나의 애플리케이션에서 여러 개의 애플리케이션 컨텍스트 오브젝트가 만들어 사용되는 경우는 어떤 경우일까?
    • 스프링 프레임워크
      IoC 컨테이너, 애플리케이션 컨텍스트를 포함한 스프링이 제공하는 모든 기능을 제공하는 소프트웨어 환경.

    싱글톤 레지스트리와 오브젝트 스코프

    getBean("userDao", UserDao.class)으로 호출해서 가져온 오브젝트는 동일할까? 정답은 yes!
    어떻게 가능한 것일까?

    싱글톤 레지스트리로서의 애플리케이션 컨텍스트

    애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리이다. 스프링에서 별다른 설정이 없을 경우 내부에서 생성하는 빈 오브젝트는 모두 싱글톤으로 만들어진다.

    서버 애플리케이션과 싱글톤

    스프링은 엔터프라이즈 시스템을 위해 고안된 기술이기 때문에 서버환경에서 사용될 때 그 가치가 있다. 간단히 말해 서버의 성능을 위해 싱글톤을 사용한다.

    싱글톤 패턴의 한계

    • 상속할 수 없음
      싱글톤 패턴은 생성자를 private으로 제한하기 때문에 다른 생성자가 없다면 상속이 불가능하다. 이는 객체지향적인 설계의 장점을 적용하기 어렵다.
    • 테스트 하기 힘듦.
      만들어지는 방식이 제한적이기 때문에 목 오브젝트 등으로 대체하기 힘들다. 초기화 과정에서 사용할 오브젝트를 주입하기도 힘든 것도 테스트 하기 힘든 이유 중 하나.
    • 서버 환경에서 싱글톤이 하나만 만들어지는 것을 보장하지 못함
      클래스 로더를 어떻게 구성하고 있냐에 따라 싱글톤 클래스임에도 하나 이상의 오브젝트가 만들어질 수 있다.(ex. 여러 개의 JVM에 분산되어 설치되는 경우)
    • 전역 상태를 만들 수 있음.
      싱글톤의 static 메소드를 이용해 언제든지 싱글톤에 쉽게 접할 수 있어 전역 상태(global state)로 사용될 수 있다.

    싱글톤 레지스트리

    스프링이 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는 것이 싱글톤 레지스트리이다.
    스프링 컨테이너는 싱글톤을 생성, 관리, 공급하는 싱글톤 관리 컨테이너이다. 덕분에 싱글톤 방식으로 사용될 애플리케이션 클래스도 public 생성자를 사용할 수 있다. 따라서 테스트 환경에서 자유롭게 사용 가능한 점과 더불어 자바의 싱글톤 패턴이 가진 한계를 극복할 수 있게 한다.

    싱글톤과 오브젝트의 상태

    싱글톤은 멀티스레드 환경에서 여러 스레드가 동시에 접근 가능하므로 상태 관리에 주의를 기울여야 한다. 따라서 서비스 형태의 오브젝트로 사용되는 경우 무상태 방식으로 만들어져야 한다.
    스프링의 싱글톤 빈으로 사용되는 클래스를 만드는 경우 개별적으로 바뀌는 정보는 로컬 변수로 정의하거나 파라미터로 주고 받으며 사용해야 한다.(읽기 전용 정보인 경우는 예외)
    자신이 사용하는 다른 스프링 빈을 저장하려는 용도의 경우 인스턴스 변수 사용이 가능하다.(생성자 주입 방식이 가능한 이유인듯)

    스프링 빈의 스코프

    스프링 빈의 기본 스코프는 스프링 컨테이너 내에 한 개의 오브젝트가 만들어져 강제로 제거하지 않고, 스프링 컨테이너가 존재하는 동안 계속 유지된다.

    추후 10장에서 자세히 소개 될 싱글톤 외의 스코프
    프로토 타입 스코프: 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트 반환.
    요청 스코프: HTTP 요청이 생길 때마다 생성되는 요청 스코프
    세션 스코프: 웹의 세션과 스코프가 유사하다.

    의존관계 주입(DI)

    제어의 역전과 의존관계 주입

    의존관계란? 두 클래스 또는 모듈이 의존관계에 있다고 말할 때는 항상 방향성을 부여해줘야한다. 그리고 두 클래스의 의존관게는 아래와 같이 표현한다.

    여기서 B가 변하면 A에 영향을 미친다. A에서 B에 정의된 메소드를 호출할 때 사용에 대한 의존관계가 있다고 한다. B에 새로운 메소드가 추가되거나 기존 메소드의 형식이 바뀌면 A도 영향을 받고, B에서 사용된 기능이 내부적으로 변경되는 경우 A의 기능 수행에 영향을 미칠 수 있다. 이런 사용 관계의 경우 A와 B는 의존관계가 있다고 말한다.

    DaoFactory

    예제에서 DaoFactory는 두 오브젝트 사이의 런타임 의존관계를 설정해주는 의존관계 주입 작업을 주도하는 존재이며, 동시에 IoC 방식으로 오브젝트의 생성, 초기화 및 제공을 하는 컨테이너다. 따라서 의존관계 주입을 담당하고 있다고 볼 수 있다.
    DI 컨테이너에 의해 런타임 시에 의존 오브젝트를 사용할 수 있도록 레퍼런스를 전달받는 과정을 의존관계 주입이라고 부른다.

    의존관계 검색과 주입

    의존관계를 맺는 방법이 외부로부터의 주입이 아니라 스스로 검색을 이용하는 경우 의존관계 검색이라 한다. 자신이 필요로 하는 의존 오브젝트를 능동적으로 찾지만 어떤 클래스의 오브젝트를 이용할지 결정하지는 않는다.

     

    public UserDao() { 
        AnnotationConfigApplicationContext context 
            = new AnnotationConfigApplicationContext(DaoFactory.class); 
        this.connectionMaker = context.getBean("connectionMaker", ConnectionMaker.class); 
    }

    DI를 원하는 오브젝트는 컨테이너가 관리하는 빈이어야 한다.

    '공부일기 > 스프링' 카테고리의 다른 글

    Spring REST Docs 적용  (0) 2021.07.26
    토비의 스프링 2. 테스트  (0) 2021.05.16
    토비의 스프링 - 1. 오브젝트와 의존관계(1)  (0) 2021.05.01
Designed by Tistory.