토비의 스프링 reading (2)
팩토리
- 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 오브젝트
- 디자인 패턴의 추상 팩토리 패턴이나 팩토리 메서드 패턴과는 다름
- 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 분리하려는 목적으로 사용하는 것
- 애플리케이션의 컴포넌트 역할을 하는 오브젝트와 애플리케이션의 구조를 결정하는 오브젝트를 분리한다는 데 의미가 있음
제어관계 역전
일반적인 프로그램의 흐름은
- 프로그램의 시작지점(main method 등)에서 다음에 사용할 오브젝트 결정
- 결정한 오브젝트 생성
- 만들어진 오브젝트에 있는 메서드를 호출
- 메서드 안에서 다음에 사용할 것을 결정하고 호출
이는 모든 오브젝트가 능동적으로 자신이 사용할 클래스를 결정
언제 어떻게 그 오브젝트를 만들지를 스스로 관장
모든 종류의 작업을 사용하는 쪽에서 제어하는 구조
제어의 역전(Ioc)이란 이런 제어 흐름의 개념을 거꾸로 뒤집는 것
스프링 Ioc ApplicationContext 왜 사용?
- 범용적이고 유연한 방법으로 Ioc 기능을 확장하기 위해
애플리케이션이 고도화되면 Ioc를 적용한 오브젝트도 계속 추가 될텐데 매번 어떤 팩토리 클래스를 사용해야 하는 지 알아야하고 필요할 때마다 팩토리 오브젝트를 생성해야하는 번거로움이 있음
applicationContext는 알거나 직접 사용할 필요가 없고 일관된 방식으로 원하는 오브젝트를 가져올 수 있음생성, 관계설정만 하는 것이 아닌 만들어지는 방식, 시점, 전략, 부가적으로 자동생성, 오브젝트에 대한 후 처리 등 효과적으로 활용할 수 있는 다양한 기능을 제공
bean을 검색하는 다양한 방법을 제공
스프링 Ioc 용어 정리
빈(bean)
- 스프링이 Ioc 방식으로 직접 그 생성과 제어를 담당하는 오브젝트
빈 팩토리(bean factory)
- 스프링의 Ioc를 담당하는 핵심 컨테이너
- 빈을 등록, 생성, 조회하고 돌려주고 부가적인 빈을 관리하는 기능을 담당
- 보통 applicationContext를 사용
애플리케이션 컨텍스트(application context)
- 빈 팩토리를 확장한 Ioc 컨테이너
- 빈 팩토리에 스프링이 제공하는 각종 부가 서비스를 추가로 제공한 것
스프링이 싱글톤으로 빈을 생성하는 이유
- 매번 클라이언트에서 요청이 올 때 마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다면 서버가 부하를 감당하기 어려움
- 그래서 제한된 수(보통 한 개)의 오브젝트만 만들어서 사용하도록 싱클톤을 사용
Java 싱글톤 패턴의 한계
- private 생성자를 갖고 있기 때문에 상속 할 수 없음
- 초기화 과정에서 생성자 등을 통해 사용할 오브젝트를 다이나믹하게 주입하기도 힘들기 때문에 필요한 오브젝트는 직접 오브젝트를 만들어서 사용 할 수 밖에 없어 테스트가 힘듬
- 서버에서 클래스 로더를 어떻게 구성하고 있느냐에 따라 싱글톤 클래스여도 하나 이상의 오브젝트가 만들어질 수 있음
- 싱글톤의 static 메서드를 이용해 전역 상태로 사용되기 쉬우므로, 아무 객체나 자유롭게 접근하고 수정하고 공유할 수 잇는 전역 상태를 갖는 것은 객체지향 프로그래밍에서 권장되지 않음
싱글톤 레지스트리
- 스프링에서 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능
싱글톤 레지스트리의 장점
- 오브젝트 생성에 대한 모든 권한은 Application Context에 있기 때문에 static 메서드와 private 생성자를 사용하는 것이 아닌 평범한 자바 클래스를 싱글톤으로 활용하게 해줌
- 스프링이 빈을 싱글토으로 만드는 것은 결국 오브젝트의 생성 방법을 제어하는 Ioc 컨테이너로서의 역할
오브젝트의 상태
- 멀티스레드 환경이라면 여러 스레드가 동시에 싱글톤에 접근해서 사용할 수 있으므로 상태 관리에 주의해야 함
- 기본적으로 상태정보를 내부에 갖고 있지 않는 무상태 방식으로 생성되어야 함
- 서로 값을 덮어쓰고자신이 저장하지 않은 값을 읽어올 수 있기 때문에 기본적으로 인스턴스 필드의 값을변경하고 유지하는 상태유지 방식으로 만들지 않음
- 상태가 없는 방식으로 만드는 경우 생성한 정보는 파라미터와 지역변수, 리턴 값으로 이용함
- 파라미터나 지역변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어지기 때문에 싱글톤이라고 해도 여러 스레드가 변수의 값을 덮어 쓸일이 없음
- 읽기전용 정보인 자신이 사용하는 다른 싱글톤 빈을 저장하려는 용도라면 인스턴스 변수를 사용해도 무방함
의존관계
- A -> B 이면 B가 변하면 그것이 A에도 영향을 미친다는 것
- 어린 자식은 부모에 의존적이므로 부모가 변하면 자식도 변하게 됨
- 의존관계에는 방향성이 있음 (자식 -> 부모)
- 자바에서는 Interface를 통해 의존관계를 줄일 수 있음, 이것이 낮은 결합도
- 모델이나 코드에서 클래스와 인터페이스를 통해 드러나는 의존관계말고 런타임 시에 오브젝트 사이에서 만들어지는 의존관계도 있음
- 런타임 의존관계 혹은 오브젝트 의존관계라고 함
의존 오브젝트
- 프로그램이 시작되고 오브젝트가 만들어지고 런타임 시에 의존관계를 맺는 대상, 즉 실제 사용대상인 오브젝트
의존관계 주입
- 구체적인 의존 오브젝트와 그것을 사용할 주체, 보통 클라이언트라고 부르는 오브젝트를 런타임 시에 연결해주는 작업
- 클래스 모델이나 코드에는 런타임 시점에 의존관계가 드러나지 않으므로 인터페이스에만 의존하고 있어야 함
- 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제 3의 존재가 결정
- 의존관계는 사용할 오브젝트에 대한 레퍼런스를 외부에서 제공(주입)해줌으로써 만들어짐
- 핵심은 설계 시점에는 알지 못했던 두 오브젝트의 관계를 맺도록 도와주는 제 3의 존재가 있다는 것
- application context
- 빈 팩토리
- Ioc 컨테이너 등
의존관계 검색
- 외부로부터의 주입이 아니라, 스스로 검색
- 런타임 시 의존관계를 맺을 오브젝트를 검색하는 것과 오브젝트의 생성 작업은 외부 컨테이너에게 Ioc로 맡기지만, 이를 가져올 떄는 메서드나 생성자를 통한 주입 대신 스스로 컨테이너에게 요청하는 방법을 사용
- 미리 준비된 메서드를 호출하면 되니 단순히 요청으로 보이겠지만, 이런 작업을 일반화한 스프링의 application context라면 미리 정해놓은 일므을 전달해서 그 이림에 해당하는 오브젝트를 찾게 됨.
- getBean()
- 의존관계 검색 방식에서는 검색하는 오브젝트는 자신이 스프링의 빈일 필요가 없음
- 반면 의존관계를 주입하기 위해선 생성과 초기화 권한을 갖고 있어야하고, 그러려면 Ioc 방식으로 컨테이너에서 생성되는 오브젝트, 즉 빈이어야 하기 때문
DI를 원하는 오브젝트는 먼저 자기 자신이 컨테이너가 관리하는 빈이 돼야 한다는 사실을 잊지 말자.
의존관계 주입의 장점
- 코드에는 런타임 클래스에 대한 의존관계가 나타나지 않음
- 인터페이스를 통해 결합도가 낮은 코드가 되므로 의존관계에 있는 대상이 바뀌거나 변경되더라도 자신이 영향 받지 않음
- 변경을 통한 다양한 확장에는 자유로움
1장 마무리
스프링이란, 어떻게 오브젝트가 설계되고, 만들어지고, 어떻게 관계를 맺고 사용되는 지에 관심을 갖는 프레임워크