팩토리

  • 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 오브젝트
  • 디자인 패턴의 추상 팩토리 패턴이나 팩토리 메서드 패턴과는 다름
  • 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 분리하려는 목적으로 사용하는 것
  • 애플리케이션의 컴포넌트 역할을 하는 오브젝트와 애플리케이션의 구조를 결정하는 오브젝트를 분리한다는 데 의미가 있음

제어관계 역전

  • 일반적인 프로그램의 흐름은

    1. 프로그램의 시작지점(main method 등)에서 다음에 사용할 오브젝트 결정
    2. 결정한 오브젝트 생성
    3. 만들어진 오브젝트에 있는 메서드를 호출
    4. 메서드 안에서 다음에 사용할 것을 결정하고 호출
  • 이는 모든 오브젝트가 능동적으로 자신이 사용할 클래스를 결정

  • 언제 어떻게 그 오브젝트를 만들지를 스스로 관장

  • 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조

  • 제어의 역전(Ioc)이란 이런 제어 흐름의 개념을 거꾸로 뒤집는 것

스프링 Ioc ApplicationContext 왜 사용?

  • 범용적이고 유연한 방법으로 Ioc 기능을 확장하기 위해
  1. 애플리케이션이 고도화되면 Ioc를 적용한 오브젝트도 계속 추가 될텐데 매번 어떤 팩토리 클래스를 사용해야 하는 지 알아야하고 필요할 때마다 팩토리 오브젝트를 생성해야하는 번거로움이 있음
    applicationContext는 알거나 직접 사용할 필요가 없고 일관된 방식으로 원하는 오브젝트를 가져올 수 있음

  2. 생성, 관계설정만 하는 것이 아닌 만들어지는 방식, 시점, 전략, 부가적으로 자동생성, 오브젝트에 대한 후 처리 등 효과적으로 활용할 수 있는 다양한 기능을 제공

  3. bean을 검색하는 다양한 방법을 제공


스프링 Ioc 용어 정리

빈(bean)

  • 스프링이 Ioc 방식으로 직접 그 생성과 제어를 담당하는 오브젝트

빈 팩토리(bean factory)

  • 스프링의 Ioc를 담당하는 핵심 컨테이너
  • 빈을 등록, 생성, 조회하고 돌려주고 부가적인 빈을 관리하는 기능을 담당
  • 보통 applicationContext를 사용

애플리케이션 컨텍스트(application context)

  • 빈 팩토리를 확장한 Ioc 컨테이너
  • 빈 팩토리에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한 것

스프링이 싱글톤으로 빈을 생성하는 이유

  • 매번 클라이언트에서 요청이 올 때 마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다면 서버가 부하를 감당하기 어려움
  • 그래서 제한된 수(보통 한 개)의 오브젝트만 만들어서 사용하도록 싱클톤을 사용

Java 싱글톤 패턴의 한계

  1. private 생성자를 갖고 있기 때문에 상속 할 수 없음
  2. 초기화 과정에서 생성자 등을 통해 사용할 오브젝트를 다이나믹하게 주입하기도 힘들기 때문에 필요한 오브젝트는 직접 오브젝트를 만들어서 사용 할 수 밖에 없어 테스트가 힘듬
  3. 서버에서 클래스 로더를 어떻게 구성하고 있느냐에 따라 싱글톤 클래스여도 하나 이상의 오브젝트가 만들어질 수 있음
  4. 싱글톤의 static 메서드를 이용해 전역 상태로 사용되기 쉬우므로, 아무 객체나 자유롭게 접근하고 수정하고 공유할 수 잇는 전역 상태를 갖는 것은 객체지향 프로그래밍에서 권장되지 않음

싱글톤 레지스트리

  • 스프링에서 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능

싱글톤 레지스트리의 장점

  • 오브젝트 생성에 대한 모든 권한은 Application Context에 있기 때문에 static 메서드와 private 생성자를 사용하는 것이 아닌 평범한 자바 클래스를 싱글톤으로 활용하게 해줌
  • 스프링이 빈을 싱글토으로 만드는 것은 결국 오브젝트의 생성 방법을 제어하는 Ioc 컨테이너로서의 역할

오브젝트의 상태

  • 멀티스레드 환경이라면 여러 스레드가 동시에 싱글톤에 접근해서 사용할 수 있으므로 상태 관리에 주의해야 함
  • 기본적으로 상태정보를 내부에 갖고 있지 않는 무상태 방식으로 생성되어야 함
  • 서로 값을 덮어쓰고자신이 저장하지 않은 값을 읽어올 수 있기 때문에 기본적으로 인스턴스 필드의 값을변경하고 유지하는 상태유지 방식으로 만들지 않음
  • 상태가 없는 방식으로 만드는 경우 생성한 정보는 파라미터와 지역변수, 리턴 값으로 이용함
  • 파라미터나 지역변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어지기 때문에 싱글톤이라고 해도 여러 스레드가 변수의 값을 덮어 쓸일이 없음
  • 읽기전용 정보인 자신이 사용하는 다른 싱글톤 빈을 저장하려는 용도라면 인스턴스 변수를 사용해도 무방함

의존관계

  • A -> B 이면 B가 변하면 그것이 A에도 영향을 미친다는 것
  • 어린 자식은 부모에 의존적이므로 부모가 변하면 자식도 변하게 됨
  • 의존관계에는 방향성이 있음 (자식 -> 부모)
  • 자바에서는 Interface를 통해 의존관계를 줄일 수 있음, 이것이 낮은 결합도
  • 모델이나 코드에서 클래스와 인터페이스를 통해 드러나는 의존관계말고 런타임 시에 오브젝트 사이에서 만들어지는 의존관계도 있음
  • 런타임 의존관계 혹은 오브젝트 의존관계라고 함

의존 오브젝트

  • 프로그램이 시작되고 오브젝트가 만들어지고 런타임 시에 의존관계를 맺는 대상, 즉 실제 사용대상인 오브젝트

의존관계 주입

  • 구체적인 의존 오브젝트와 그것을 사용할 주체, 보통 클라이언트라고 부르는 오브젝트를 런타임 시에 연결해주는 작업
    1. 클래스 모델이나 코드에는 런타임 시점에 의존관계가 드러나지 않으므로 인터페이스에만 의존하고 있어야 함
    2. 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제 3의 존재가 결정
    3. 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어짐
  • 핵심은 설계 시점에는 알지 못했던 두 오브젝트의 관계를 맺도록 도와주는 제 3의 존재가 있다는 것
    • application context
    • 빈 팩토리
    • Ioc 컨테이너 등

의존관계 검색

  • 외부로부터의 주입이 아니라, 스스로 검색
  • 런타임 시 의존관계를 맺을 오브젝트를 검색하는 것과 오브젝트의 생성 작업은 외부 컨테이너에게 Ioc로 맡기지만, 이를 가져올 떄는 메서드나 생성자를 통한 주입 대신 스스로 컨테이너에게 요청하는 방법을 사용
  • 미리 준비된 메서드를 호출하면 되니 단순히 요청으로 보이겠지만, 이런 작업을 일반화한 스프링의 application context라면 미리 정해놓은 일므을 전달해서 그 이림에 해당하는 오브젝트를 찾게 됨.
    • getBean()
  • 의존관계 검색 방식에서는 검색하는 오브젝트는 자신이 스프링의 빈일 필요가 없음
  • 반면 의존관계를 주입하기 위해선 생성과 초기화 권한을 갖고 있어야하고, 그러려면 Ioc 방식으로 컨테이너에서 생성되는 오브젝트, 즉 빈이어야 하기 때문

DI를 원하는 오브젝트는 먼저 자기 자신이 컨테이너가 관리하는 빈이 돼야 한다는 사실을 잊지 말자.

의존관계 주입의 장점

  1. 코드에는 런타임 클래스에 대한 의존관계가 나타나지 않음
  2. 인터페이스를 통해 결합도가 낮은 코드가 되므로 의존관계에 있는 대상이 바뀌거나 변경되더라도 자신이 영향 받지 않음
  3. 변경을 통한 다양한 확장에는 자유로움

1장 마무리

스프링이란, 어떻게 오브젝트가 설계되고, 만들어지고, 어떻게 관계를 맺고 사용되는 지에 관심을 갖는 프레임워크