우선, 스프링 없는 순수 Java로 이루어진 DI 컨테이너를 떠올려보자.
여러 Client가 객체를 요청하면, 아래와같이 호출할 때마다 새로운 객체를 생성하여 반환할 것이다.
이는 수천개의 요청이 들오오면 객체또한 수천개를 생성하게 됨을 의미하고, 심각한 메모리 낭비를 야기한다.
이에 대한 해결방안으로 싱글톤 패턴이 있다.
싱글톤 패턴이란, 객체가 딱 1개만 생성되어 공유하도록 설계된 모델이다.
Spring 컨테이너는 싱글톤 패턴을 적용하지 않아도 객체를 싱글톤으로 관리한다.
즉, 아래와같은 모습으로 바뀌었음을 알 수 있다.
싱글톤 방식은 여러 Client가 하나의 객체를 공유하기 때문에, 특정 상태가 존재하면 안 된다.
즉, 값을 변경할 수 있는 필드가 없는 무상태로 설계해야 한다.
예를 들어, private int price;
와 같이 상태를 유지하는 필드가 있으면 특정 Clien가 값을 변경하여 매우 심각한 장애가 발생할 수 있다.
필드 대신 지역변수, 파라미터 등을 사용하자.
또한, 가급적 읽기만 가능하도록 설계하자.
어떠한 원리로 Spring은 싱글톤을 보장할까? 답은 @Configuration
에 있다.
Spring은 CGLIB 기술을 이용해
@Configuration
이 붙은 DI 컨테이너를 상속받은 임의의 다른 Class를 만들어 Spring Bean으로 등록한다.
이후 @Bean
이 붙은 메서드마다 이미 존재하는 Bean이면 Bean을 반환하고, 없다면 Bean을 생성한 후 반환하는 코드가 동적으로 생성된다.