Spring Bean이란?
1. Spring Bean의 개념
Spring Bean은 Spring 프레임워크의 IoC(Inversion of Control, 제어의 역전) 컨테이너에 의해 생성, 관리되는 객체입니다. 일반적인 Java 객체(POJO, Plain Old Java Object)와 달리, Spring Bean은 Spring 컨테이너에 의해 생명주기가 관리되며, 의존성 주입(Dependency Injection)을 통해 다른 Bean과 연결됩니다.
Spring Bean의 특징
- IoC 컨테이너에 의해 관리: 개발자가 직접 객체를 생성하고 관리하는 것이 아니라, Spring 컨테이너가 대신 수행합니다.
- 의존성 주입(DI): 객체 간의 의존 관계를 외부에서 설정해줍니다.
- 생명주기 관리: Bean의 생성, 초기화, 소멸 등의 생명주기를 Spring이 관리합니다.
- 싱글톤(Singleton) 패턴: 기본적으로 Bean은 싱글톤으로 관리됩니다(하나의 인스턴스만 생성).
2. Spring Bean 등록 방법
Spring에서 Bean을 등록하는 방법은 여러 가지가 있습니다. 이 프로젝트에서 사용된 방법을 중심으로 살펴보겠습니다.
1) 어노테이션을 통한 Bean 등록
가장 일반적인 방법으로, 클래스에 특정 어노테이션을 붙여 Spring이 자동으로 Bean으로 등록하도록 합니다.
주요 어노테이션
- @Component: 일반적인 컴포넌트를 Bean으로 등록
- @Service: 비즈니스 로직을 처리하는 서비스 계층의 컴포넌트
- @Repository: 데이터 접근 계층(DAO)의 컴포넌트
- @Controller: 웹 요청을 처리하는 컨트롤러
- @RestController: REST API를 제공하는 컨트롤러
- @Configuration: 설정 클래스를 정의
2) @Bean 어노테이션을 통한 수동 등록
@Configuration 클래스 내에서 @Bean 어노테이션을 사용하여 직접 Bean을 등록하는 방법입니다.
3. 프로젝트 예시로 Spring Bean 이해하기
1) @Service 어노테이션을 사용한 Bean 등록 (QuestionService)
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class QuestionService {
private final QuestionRepository questionRepository;
public QuestionDto getQuestion(Long id) {
Question question = questionRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Question not found: " + id));
return QuestionDto.from(question);
}
@Transactional
public QuestionDto createQuestion(QuestionCreateDto questionCreateDto) {
Question saveQuestion = questionRepository.save(Question.of(questionCreateDto));
return QuestionDto.from(saveQuestion);
}
// ... 기타 메서드 ...
}
이 코드에서:
@Service어노테이션은 이 클래스를 Spring Bean으로 등록합니다.@Transactional(readOnly = true)는 기본적으로 모든 메서드가 읽기 전용 트랜잭션으로 실행되도록 설정합니다.@RequiredArgsConstructor는 final 필드를 파라미터로 받는 생성자를 자동으로 생성하여 의존성 주입을 가능하게 합니다.private final QuestionRepository questionRepository는 생성자를 통해 자동으로 주입받는 의존성입니다.
2) @Configuration과 @Bean을 사용한 Bean 등록 (QuerydslConfig)
@Configuration
public class QuerydslConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
이 코드에서:
@Configuration어노테이션은 이 클래스가 Bean 설정을 포함하고 있음을 나타냅니다.@Bean어노테이션은jpaQueryFactory()메서드가 반환하는 객체를 Spring Bean으로 등록합니다.@PersistenceContext는 JPA의 EntityManager를 주입받습니다.
3) @Repository 어노테이션을 사용한 Bean 등록 (QuestionRepository)
public interface QuestionRepository extends JpaRepository<Question, Long>, QuestionCustomRepository {
// 메서드 정의
}
이 인터페이스는 직접적으로 어노테이션을 사용하지 않지만, Spring Data JPA가 자동으로 이 인터페이스의 구현체를 Bean으로 등록합니다.
4) 테스트 환경에서의 Bean 등록 (TestConfig)
@TestConfiguration
public class TestConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
이 코드에서:
@TestConfiguration어노테이션은 테스트 환경에서만 사용되는 설정 클래스임을 나타냅니다.- 테스트 시에 필요한 Bean을 등록합니다.
4. Bean의 의존성 주입(DI)
Spring에서는 다양한 방법으로 Bean 간의 의존성을 주입할 수 있습니다.
1) 생성자 주입 (Constructor Injection)
@Service
@RequiredArgsConstructor
public class AnswerService {
private final AnswerRepository answerRepository;
private final QuestionRepository questionRepository;
// 메서드 구현
}
@RequiredArgsConstructor는 final 필드를 파라미터로 받는 생성자를 자동으로 생성합니다. 이 생성자를 통해 Spring이 의존성을 주입합니다. 생성자 주입은 불변성을 보장하고 필수 의존성을 명확히 하므로 권장되는 방식입니다.
2) 필드 주입 (Field Injection)
@SpringBootTest
class QuestionServiceTest {
@Autowired
private QuestionService questionService;
// 테스트 메서드
}
테스트 코드에서는 주로 @Autowired 어노테이션을 사용한 필드 주입 방식을 사용합니다. 이 방식은 코드가 간결하지만, 의존성이 숨겨지고 테스트하기 어려운 단점이 있어 실제 애플리케이션 코드에서는 권장되지 않습니다.
5. Bean의 스코프(Scope)
Spring Bean은 다양한 스코프를 가질 수 있습니다.
- 싱글톤(Singleton): 기본 스코프로, Spring 컨테이너당 하나의 인스턴스만 생성됩니다.
- 프로토타입(Prototype): 요청할 때마다 새로운 인스턴스가 생성됩니다.
- 요청(Request): HTTP 요청마다 새로운 인스턴스가 생성됩니다.
- 세션(Session): HTTP 세션마다 새로운 인스턴스가 생성됩니다.
- 애플리케이션(Application): ServletContext 생명주기 동안 하나의 인스턴스만 생성됩니다.
- 웹소켓(WebSocket): WebSocket 생명주기 동안 하나의 인스턴스만 생성됩니다.
이 프로젝트에서는 대부분의 Bean이 기본 스코프인 싱글톤으로 관리됩니다.
6. Bean의 생명주기(Lifecycle)
Spring Bean은 다음과 같은 생명주기를 가집니다.
- 인스턴스화(Instantiation): Bean 객체 생성
- 프로퍼티 설정(Populate Properties): 의존성 주입
- 초기화 콜백(Initialization Callbacks): 초기화 메서드 호출
- 사용(In Use): 애플리케이션에서 Bean 사용
- 소멸 콜백(Destruction Callbacks): 소멸 메서드 호출
- 소멸(Destruction): Bean 제거
Bean의 초기화와 소멸 시점에 특정 작업을 수행하기 위해 @PostConstruct와 @PreDestroy 어노테이션을 사용할 수 있습니다.
7. 결론
Spring Bean은 Spring 프레임워크의 핵심 개념으로, IoC 컨테이너에 의해 생성되고 관리되는 객체입니다. Bean을 통해 객체 간의 의존성을 외부에서 주입받을 수 있으며, 이를 통해 코드의 결합도를 낮추고 테스트 용이성을 높일 수 있습니다.
이 프로젝트에서는 @Service, @Repository, @Configuration, @Bean 등의 어노테이션을 사용하여 Bean을 등록하고, 생성자 주입 방식으로 의존성을 주입받고 있습니다. 이러한 방식은 Spring 애플리케이션 개발의 표준적인 패턴으로, 유지보수성과 테스트 용이성을 높이는 데 기여합니다.
'개발' 카테고리의 다른 글
| Kafka와 RabbitMQ 비교 분석 (0) | 2025.03.21 |
|---|---|
| 테스트 코드의 중요성? (SpringBoot 기반 Mocking 학습) (0) | 2025.03.21 |
| Kafka+Docker 기반 SpringBoot 프로젝트 구축 방법 (0) | 2025.03.20 |
| Spring Boot - Builder 패턴 (0) | 2025.03.12 |
| Spring Boot에 Mysql Docker 연결 (0) | 2024.05.14 |
IT/네트워크/보안