6.4 KiB
bean registration 기준
목적
Spring bean 등록은 “컨테이너가 생명주기와 의존성을 관리해야 하는 객체”에만 사용한다.
아무 객체나 bean으로 올리지 않고, stereotype scanning과 @Configuration + @Bean을 역할에 따라 구분한다.
공식 의미
- Spring IoC container는 configuration metadata를 읽어 bean definition을 만들고 객체를 관리한다.
- 설정 메타데이터는 주로 annotation-based component class,
@Configuration+@Bean, 또는 외부 설정으로 표현할 수 있다. @Component와 그 특수화(@Repository,@Service,@Controller)는 classpath scanning 대상이다.@Bean은 객체를 생성·설정·초기화하는 factory method를 bean definition으로 등록한다.@Bean은@Configuration클래스에서 사용하는 것이 기본 권장 방식이다.- bean overriding은 일반적으로 권장되지 않으며 설정 가독성을 해친다.
- bean/runtime registration은 초기 단계가 아니라 live access 중에는 공식적으로 지원되지 않는다.
- 일반적으로 fine-grained domain object는 Spring container에 등록하지 않는다.
기본 규칙
1. bean은 “컨테이너 관리 가치”가 있는 객체만 등록
다음은 bean 등록 후보이다.
- application service / use case entry object
- repository adapter
- external API client
- configuration / security / filter / interceptor
- shared infrastructure object
- framework integration object
다음은 기본적으로 bean 등록하지 않는다.
- domain entity
- value object
- request / response DTO
- command / result DTO
- 단순 임시 helper object
- 매 요청/매 호출마다 새로 만들어도 되는 순수 data object
2. 애플리케이션 주 컴포넌트는 stereotype annotation 우선
다음은 stereotype을 우선 검토한다.
@Service@Repository@Controller/@RestController- generic component면
@Component
즉 프로젝트 코드 안의 “주된 역할 객체”는 scanning 기반 등록을 기본값으로 한다.
3. @Bean은 명시적 조립이 필요할 때 사용
다음은 @Configuration + @Bean을 우선 검토한다.
- 외부 라이브러리 타입 등록
- 생성자가 복잡하거나 factory method가 필요한 경우
- 조건부 조립이 필요한 경우
- 여러 collaborator를 엮어 명시적으로 wiring해야 하는 경우
- infrastructure object / client / encoder / formatter / strategy bean 생성
- 같은 config 안에서 inter-bean wiring을 명시적으로 보여주고 싶은 경우
4. @Bean은 기본적으로 @Configuration 안에서만
@Bean method는 기본적으로 @Configuration 클래스 안에 둔다.
이유:
- full configuration mode가 inter-bean dependency를 더 안전하게 다룬다
- lite mode의 subtle bug 가능성을 줄일 수 있다
기본 금지:
- 일반
@Component안에 습관적으로@Beanmethod 두기
예외:
- 아주 제한된 factory-style component가 필요하고, inter-bean dependency 호출을 하지 않는 경우
5. bean 등록 이유가 이름만 보고 드러나야 한다
- scanning bean이면 stereotype이 역할을 드러내야 한다
@Configuration클래스는 조립 목적이 이름에 드러나야 한다
좋은 방향:
SecurityConfigurationWebConfigurationVaultClientConfigurationOAuth2SecurityConfiguration
지양:
CommonConfigAppBeansGeneralConfiguration
6. domain object를 bean으로 등록하지 않는다
Spring 공식 문서도 fine-grained domain object는 보통 container가 아니라 repository/business logic이 만들고 로드한다고 설명한다.
기본 금지:
User,Money,UserEmail,CreateUserCommand를 bean으로 등록- domain 생성 책임을 container로 넘기기
7. bean 이름은 기본 규칙을 따르고, 명시적 이름은 정말 필요할 때만
Spring은 scanning bean의 이름을 일반적으로 decapitalize된 simple class name으로 만든다.
기본:
- 이름 충돌이 없으면 기본 이름 사용
- qualifier/alias/explicit name은 실제 필요가 있을 때만 사용
무분별한 명시적 이름 지정 지양:
"mySpecialUserServiceBean""appMainPrimaryService"
8. bean overriding 기본 금지
같은 이름의 bean을 덮어쓰는 방식으로 조립하지 않는다.
이유:
- 설정 가독성이 나빠진다
- 어떤 bean이 실제로 쓰이는지 추적이 어려워진다
테스트에서만 예외적으로 필요하면 별도 테스트 설정/지원 메커니즘을 사용한다.
9. 런타임 동적 bean 등록 금지
애플리케이션 실행 중 live container에 새 bean을 동적으로 등록하는 방식은 기본 금지한다.
기본:
- bean definition은 startup 시점에 확정
- 동적 확장이 필요하면 registry/plugin/factory 전략을 따로 설계
10. bean은 역할 단위로 등록하고, 잡동사니 helper를 bean으로 올리지 않는다
container가 관리할 필요가 없는 순수 helper는 bean 대신:
- static utility
- package-private helper
- mapper instance
- plain object 생성 을 우선 검토한다.
11. configuration class는 “조립”만 하고 business logic은 넣지 않는다
@Configuration 클래스는 bean wiring과 설정 소유만 담당한다.
금지:
- 비즈니스 흐름
- 상태 전이
- 외부 호출 오케스트레이션
- 의미 있는 계산 로직
12. stereotype는 의미에 맞게 쓴다
- persistence adapter면
@Repository - use case/application service면
@Service - web adapter면
@Controller/@RestController - 그 외 일반 Spring-managed component면
@Component
의미 없는 전부 @Component 관성 사용은 지양한다.
13. public API 역할이 없는 내부 구현은 과도한 bean 분해를 피한다
container bean 수를 늘리는 것이 곧 좋은 설계는 아니다.
질문:
- lifecycle 관리가 필요한가?
- 외부에서 주입받아야 하는가?
- 테스트 seam 가치가 있는가?
- 명시적 wiring으로 읽기 쉬워지는가?
아니면 plain object가 더 낫다.
프로젝트 기준 요약
- bean은 컨테이너 관리 가치가 있는 객체만 등록
- application 주 컴포넌트는 stereotype scanning 우선
- 외부 라이브러리/명시적 조립은
@Configuration+@Bean @Bean은 기본적으로@Configuration안에서만- domain object / DTO / value object는 bean 등록 금지
- bean overriding, 런타임 동적 등록 기본 금지
- configuration class는 조립만 담당