Spring에서 Singleton으로 객체를 관리 하는 방법

Kevin·2024년 10월 5일
1

Spring

목록 보기
23/27
post-thumbnail

서론

저번 글에서 Singleton Pattern이 무엇인지와 이러한 Singleton Pattern의 대표적인 단점인 “DIP 위반 문제”를 Spring은 어떠한 방식으로 피했는지에 대해서 다뤘다.

그러면서 자연스럽게 Spring은 어떻게 객체들을 Singleton으로 관리하고 있는지에 대해서 궁금해졌다.

단순히 Spring이 Bean으로 등록된 클래스들을 Singleton 객체로 생성 해서 이를 DI 해준다라고만 이해를 하고 있었다.

이 때 중점적으로 알아볼 것들은 아래와 같다.

Spring이 Bean으로 등록된 클래스를 어떤 방식으로 Singleton 객체로 생성하는가?


Spring이 Bean으로 등록된 클래스를 어떤 방식으로 Singleton 객체로 생성하는가?

Spring에서 객체의 생성, 관계, 소멸등의 생명 주기는 Spring IoC 컨테이너인 ApplicationContext에서 담당한다.

이 때 ApplicationContext 는 직접 객체를 Singleton 형태로 만들고, 관리하는 Singleton Registry의 역할을 수행하며 Bean으로 등록된 클래스를 싱글톤 형태의 객체로 만들고 관리하는 기능을 제공한다.

이 때 설정으로 Bean 객체를 Singleton이 아닌 일반 객체로 만들 수도 있다.

우리가 Spring을 사용하면서, Singleton Pattern을 직접 구현하지 않았음에도 객체들이 Singleton으로 관리되는 이유는 무엇 때문일까?

Spring은 @Component 를 메타 데이터로 가지고 있는 @Configuration, @Service, @Controller 등의 어노테이션의 클래스를 Bean 객체로 등록한다.

이 때 위 어노테이션들은 Component Scan 방식으로 Bean에 등록이 되고, 별도 옵션을 주지 않는다면 싱글톤으로 객체가 만들어진다.

Component Scan이란 @Component가 선언된 클래스들을 스캔하여 Spring Container에 Bean으로 시켜주는 기능을 의미한다.

Spring은 위 과정에서 CGLIB이라는 바이트코드 조작 라이브러리를 사용하여 등록된 Bean들을 Singleton Patten으로 관리 해준다.


이 때 CGLIB이라는 바이트코드 조작 라이브러리를 사용하여 어떻게 Singleton으로 관리가 된다는 걸까?

Spring에서는 Proxy Pattern을 AOP 등에 자주 사용하는데, Proxy를 생성할 때 2가지 방법을 사용한다.

첫번째는 JDK 동적 Proxy로 인터페이스 기반으로 Proxy를 생성하는 방식이고, 두번째는 우리가 다룰 CGLib 방식이다.

CGLib 은 클래스 기반의 프록시를 생성할 때 사용되며, 위 사진과 같이 바이트 코트를 조작하여 동적으로 클래스를 상속받아 Proxy를 만든다.

이 때 Proxy는 원본 객체를 감싸는 래퍼 객체를 의미한다.


Spring에서는 @Service, @Controller등의 @Component를 메타 데이터로 지닌 어노테이션으로 Bean을 등록하게 되면, 해당 Bean의 Proxy 객체를 만들고 나서, 이 Proxy 객체를 Singleton Bean으로 저장한다.

이후 다른 곳에서 해당 Bean을 요청하면 같은 Proxy 객체가 반환되게 된다.

이러한 방식을 통해 Spring은 CGLib을 통해 바이트코드를 조작해 Proxy 객체를 생성하고, 이를 Singleton으로 관리함으로써 AOP 기능과 Singleton Pattern을 효과적으로 적용할 수 있다.

profile
Hello, World! \n

0개의 댓글