스프링이 직접 생성하고 의존관계를 부여하는 오브젝트.
스프링은 기본적으로 별다른 설정이 없다면 default로 Bean을 Singleton으로 만든다. -> 요청 때 마다 새로운 객체를 생성
그렇다면 왜 스프링은 싱글톤 방식으로 빈을 생성하며, 싱글톤 방식의 장단점이 무엇인지 알아보겠다.
여러 클라이언트가 동시에 요청이 온다면? -> 수십만명의 클라이언트에서 동시에 요청한다면 수십만개의 객체가 생성된다.
이렇게 객체가 요청이 오는대로 계속 생성이 된다면, 감당할 수 없게 생성된 객체때문에 메모리가 과부하되고, 성능에 큰 영향을 미친다.
그렇다면 어떻게 이런 문제를 해결 할 수 있을까? - > 싱글톤 패턴을 사용(싱글, 생성된 한개의 객체를 사용)
private을 붙인 생성자를 사용해서 임의로 다른 개발자가 밖에서 생성 할 수 없도록 하기.
이를 이용해서 getInstance 메서드를 하나 만들어 객체 생성을 한 변수를 참조해서 만들어준다. 밖에서는 new로 새로운 인스턴스를 생성하지 못하고 오로지 get Instance 메서드를 이용해서만 참조할 수 있다. (생성된 객체를 계속 사용하는 것.)
이 방법은 객체를 미리 생성해두는 가장 단순하고 안전한 방법. 싱글톤을 만드는 다른 방법은 이 외에도 더 있다.
문제점 : 순수하게 자바를 이용하면 코드가 너무 많이 들어간다. 또한 클라이언트가 구체화 클레스에 의존하게 된다. ( DIP 위반, OCP도 위반할 가능성이 높다.) 테스트하기 어렵다. 내부 속성을 초기화하거나 변경하기 어려움.
=> 유연성이 떨어진다. 안티 패턴으로 불리기도 한다.
이는 순수한 자바 코드를 이용해서 만들었을때의 이야기이다. 이런 문제를 해결하고 객체를 싱글톤으로 관리하는것을 제공하는것이 스프링이다. 스프링은 싱글톤 패턴으로 만들지 않아도 등록된 빈을 스프링 프레임워크가 Container를 이용하여 싱글톤으로 관리한다.
스프링컨테이너는 싱글톤 컨테이너의 역할을 한다. -> 싱글톤 패턴을 위한 코드가 들어가지 않아도 된다. DIP, OCP, 테스트 , private생성자로부터 자유롭게 싱글톤을 사용가능. (이미 스프링 자체에서 싱글톤으로 코드가 생성되게 작성 돼 있다)
여러 클라이언트가 하나의 같은 객체 인스턴스를 공유 -> 중요 : 상태를 유지(Stateful)하게 설계하면 안된다.
무상태(Stateless)로 설계해야 한다!!
스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다.
@Configuration => 싱글톤을 위해 존재한다?
@Bean memberService -> new MemberRepository()
@Bean orderService -> new OrderRepository()
싱글톤이 깨질까? => 깨지지 않는다. 같은 객체를 사용한다. 근데 new 로 생성을 하는데 어떻게 된것일까?.
자바코드로는 잘 설명이 안된다.
하지만 스프링이 @Configuration이라는 애노테이션으로 바이트코드 조작을 해서 보장해준다.
실제 클래스의 명을 찍어보면 AppConfig를 상속받은 다른 임의의 클래스를 만들고, 그 클래스를 스프링 빈으로 등록한다. $$xxxCGLIB등이 붙음. 이 상속받은 클래스가 내부에서 스프링에 빈이 존재하면 빈을 반환, 스프링 빈이 없으면 생성해서 반환.
만약 설정 정보에 @Configuration이 없다면? @Bean으로만 등록한다면?? => 싱글톤이 없이, 객체를 전부 새롭게 생성한다. 또한 스프링 빈이 관리하지 않는 객체가 생성되어서 들어오기 때문에 문제가 있다. 스프링 설정 정보에는 @Configuration을 넣어주도록 하자.
참고 : 본 글은 김영한님의 스프링 강의를 정리한 것이다.