BeanDefinition
스프링 빈 설정 메타 정보
- 스프링 컨테이너가 다양한 형식의 설정 정보를 지원할 수 있는 이유는
BeanDefinition
이라는 추상화 인터페이스 덕분이다. BeanDefinition
은 스프링 빈 설정 메타 정보로, 스프링 컨테이너가 빈을 생성하기 위한 정보를 담고 있다.
스프링 컨테이너의 동작 원리
- 우리가 작성한
AppConfig.class
또는appConfig.xml
에서 BeanDefinition이 생성된다. - 스프링 컨테이너는
BeanDefinition
을 참조하여 스프링 빈을 생성하고 관리한다.
BeanDefinition 생성의 이유
AnnotationConfigApplicationContext
는AnnotatedBeanDefinitionReader
를 소유하여 자바 어노테이션 기반 설정을 처리한다.GenericXmlApplicationContext
는XmlBeanDefinitionReader
를 소유하여 XML 기반 설정을 처리한다.- 두 Reader는
AppConfig.class
와appConfig.xml
을 읽어 BeanDefinition을 생성한다.
실제 BeanDefinition 출력하기
- 스프링은 빈 설정을 추상화하여 관리할 수 있게 BeanDefinition을 활용한다.
- BeanDefinition은 직접 생성하여 등록할 수도 있다.
- 다만 실무에서는 거의 사용할 일이 없으며,
- 주로 스프링 코드나 오픈 소스에서 관련 코드를 볼 때 이해하는 데 도움을 줄 것이다.
스프링 빈 등록 방식
스프링 빈을 등록하는 방식은 크게 두 가지로 나뉜다:
- 직접 스프링 컨테이너에 빈을 등록
- 빈 정의 정보를 직접 작성하여 컨테이너에 추가.
- 팩토리 메서드를 통한 등록
- 팩토리 메서드에서 빈을 생성하여 등록.
- 예: 어노테이션을 활용한 방식 (
@Configuration
클래스의 메서드를 활용)
싱글톤 패턴
웹 애플리케이션과 싱글톤의 필요성
- 대부분의 스프링 애플리케이션은 웹 애플리케이션으로, 여러 사용자가 동시에 요청을 보낸다.
- 요청이 많아지면 객체를 매번 생성하는 것은 다음과 같은 문제를 초래한다:
- 메모리 낭비: 동일한 객체를 계속 생성하여 메모리를 비효율적으로 사용.
- 비용 증가: 매번 객체를 생성하고 소멸시키는 작업은 CPU와 메모리에 부하를 준다.
싱글톤 패턴의 개념
- 싱글톤 패턴: 하나의 클래스에서 단 하나의 객체만 생성하여 공유하도록 설계하는 패턴.
- 목표: JVM 메모리에 객체 인스턴스를 하나만 유지하여 메모리와 성능 문제를 해결.
간단한 싱글톤 구현 예제
가장 기본적이고 안전한 방식(미리 생성된 객체를 반환)(문제가 많음)
싱글톤 패턴의 문제점
- 코드 복잡성 증가:
- 싱글톤을 구현하기 위한 코드(예: private 생성자, static 필드 등)가 늘어난다.
- DIP 위반:
- 클라이언트가 구체 클래스에 의존하게 되어 의존성 역전 원칙(DIP)을 위반한다.
- 예:
Singleton.getInstance()
를 호출하게 되면 구체 클래스에 강하게 결합된다.
- OCP 위반 가능성:
- 구체 클래스에 의존하기 때문에 새로운 기능 추가나 변경 시 OCP(Open-Closed Principle)를 위반할 가능성이 있다.
- 테스트 어려움:
- 전역적으로 접근 가능한 상태를 가지므로, 단위 테스트에서 특정 상태를 초기화하거나 모킹(Mock)하기 어렵다.
- 확장성 부족:
- private 생성자로 인해 자식 클래스를 만들 수 없으며, 유연성이 떨어진다.
- 안티패턴이라고 불림
스프링 프레임워크의 싱글톤 컨테이너
스프링의 싱글톤 컨테이너
- 스프링은 싱글톤 패턴의 문제점을 모두 해결하며, 하나의 객체를 공유하도록 지원한다.
- 스프링 컨테이너는 빈을 싱글톤으로 관리하면서도 다음의 장점을 제공한다:
- DIP 준수: 인터페이스 기반으로 의존성을 주입받으므로 DIP 위반이 없다.
- OCP 준수: 스프링 빈 설정을 통해 변경에 유연하다.
- 테스트 용이: 의존성 주입과 컨테이너 설정으로 모킹(Mock) 및 상태 초기화가 가능하다.
- 유연한 객체 생성: private 생성자를 강제하지 않아 유연성이 높다.
- 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 한다.
- 스프링 컨테이너는 싱글톤 레지스트리로 작동하며, 필요 시 동일한 객체를 반환한다.
- 물론 싱글톤 방식말고 매번 새로운 객체를 반환하는 기능도 제공한다.
- 기본적으로 빈은 싱글톤으로 등록되지만, 특별한 경우 프로토타입 스코프나 특정 스코프로 설정할 수도 있다.
빈 스코프(Bean Scope)
스프링은 다양한 객체 생성 방식을 제공한다:
- 싱글톤 스코프 (기본값):
- 컨테이너당 하나의 인스턴스만 생성.
- 프로토타입 스코프:
- 요청마다 새로운 객체를 생성.
- 요청(Request), 세션(Session), 애플리케이션(Application) 스코프:
- HTTP 요청, 세션, 애플리케이션 범위에 따라 객체 생성과 관리.
- 99%는 싱글톤, 가끔 특별한 기능을 위해서 사용됨. (빈의 생명주기에 맞추거나 httpSession과 같은 라이프사이클 맞추거나...등등 그런 건 빈 스코프에서 언급)
싱글톤 방식의 주의점(매우 중요)
싱글톤 방식의 주의점
상태를 유지하지 않는 설계
- 싱글톤 객체는 무상태(stateless)로 설계해야 한다.
- 공유 필드를 사용하지 않고, 항상 필요한 데이터를 파라미터,지역변수,ThreadLocal 등으로 전달받아 사용해야 한다.
- 가급적 읽기만 가능해야 한다.
- 특정 클라이언트에 의존적인 필드가 있거나, 값을 변경할 수 있는 필드가 있으면 안된다.
- 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다!!!
왜 상태를 유지하면 안 되는가?
- 싱글톤 객체는 여러 요청이 동시에 접근할 수 있다.
- 상태를 공유하면 동시성 문제가 발생할 수 있다(예: 변수 값이 덮어써지는 현상).
예시
다음 예시는 실무에서 상당히 자주 발생하는 예시이다.
단축키
ctrl shift T로 테스트 파일을 쉽게 만들 수 있다.String []
가 있을 때 바로 foreach문 만드는 라이브 템플릿 iter.
'백엔드 > 김영한 스프링 기본편' 카테고리의 다른 글
김영한 스프링 핵심 원리 기본 편 복습 - 5 (1) | 2025.01.12 |
---|---|
김영한 스프링 핵심 원리 기본 편 복습 - 2 (1) | 2025.01.02 |
김영한 스프링 핵심 원리 기본 편 복습 - 1 (0) | 2024.12.30 |