우아한테크코스 레벨 2에서 학습한 내용을 정리한 글입니다.
이 글은 IoC 컨테이너와 의존성 주입(DI)에 대한 기본 이해를 바탕으로 작성되었습니다. 관련 내용은 여기에 정리해 두었으니, 참고해 주시면 감사하겠습니다.
💭 들어가며
이전 글에서 IoC 컨테이너와 의존성 주입(DI)에 대해 정리했다. 이번에는 그 내용을 바탕으로 스프링 빈(Spring Bean)에 대해 정리하고, 스프링 빈을 보다 편리하게 관리할 수 있도록 도와주는 Spring Core 어노테이션들도 함께 살펴보고자 한다.
✅ 스프링 빈(Spring Bean)이란
스프링 빈(Spring Bean)은 스프링 IoC 컨테이너가 생성하고 관리하는 객체를 의미한다. 이 객체들은 컨테이너에 의해 생명 주기가 관리되며, 의존성 주입(DI)을 통해 서로 필요한 객체들을 연결해 준다.
스프링 빈을 등록하는 방법은 크게 두 가지가 있다.
- @Component, @Service, @Repository, @Controller 등을 통한 자동 등록
- @Bean을 통한 수동 등록
1️⃣ @Component 계열 어노테이션을 통한 자동 등록
스프링은 클래스패스를 스캔하여 @Component 계열 어노테이션이 붙은 클래스를 자동으로 스프링 빈으로 등록한다. 이 어노테이션들은 스테레오타입 어노테이션이라고 불리며, 모두 @Component를 메타 어노테이션으로 가지고 있다. 기능적으로는 동일하지만, 개발자의 의도를 명확하게 표현해 주는 역할을 한다.
🔽 @Component
- 가장 기본적인 컴포넌트 등록 어노테이션이다.
- 특정 계층에 속하지 않는 일반적인 빈 등록에 적합하다.
- 나머지 세 어노테이션(@Controller, @Service, @Repository)의 기반이 되는 어노테이션이다.
@Component
public class NotificationSender {
public void send(String message) {
System.out.println("Sending: " + message);
}
}
🔽 @Controller
- 웹 요청을 처리하는 프레젠테이션 계층에서 사용하는 어노테이션이다.
- @Component처럼 빈으로 등록되며, 추가로 DispatcherServlet이 요청을 매핑할 수 있는 핸들러로 인식된다.
@Controller
public class UserController {
@GetMapping("/users")
public String listUsers(Model model) {
model.addAttribute("users", List.of("미소", "소은"));
return "userList"; // View 이름 반환
}
}
🔽 @Service
- 비즈니스 로직을 담당하는 서비스 계층에서 사용하는 어노테이션이다.
- 계층 분리를 명확히 하여 코드의 가독성을 높인다.
- 추후 AOP 적용이나 도구에서 서비스 레이어 인식이 필요할 때 유리하다.
@Service
public class UserService {
public List<String> findAllUsers() {
return List.of("미소", "소은");
}
}
🔽 @Repository
- 데이터 접근 계층(DAO)에서 사용하는 어노테이션이다.
- 스프링이 제공하는 예외 변환 기능을 통해, JDBC 예외(SQLException 등)를 스프링 예외(DataAccessException 등)로 변환해 준다.
- JPA, MyBatis에서도 자주 활용된다.
@Repository
public class UserRepository {
public List<String> findAll() {
return List.of("Alice", "Bob");
}
}
2️⃣ @Configuration과 @Bean을 통한 수동 등록
자동 등록이 어려운 경우, 예를 들어 외부 라이브러리 객체를 빈으로 등록하거나 설정 값이 필요한 객체의 경우에는 수동 등록을 사용하는 것이 더 유리하다. 이때 사용하는 어노테이션이 @Configuration과 @Bean이다.
🔽 @Configuration
- 해당 클래스가 스프링 설정 클래스임을 명시하는 어노테이션이다.
- 내부에 정의된 @Bean 메서드를 통해 필요한 객체를 직접 생성하고 빈으로 등록한다.
@Configuration
public class AppConfig {
// 설정
}
🔽 @Bean
- 메서드가 반환하는 객체를 스프링 컨테이너에 빈으로 등록하도록 지시하는 어노테이션이다.
- 메서드의 반환 객체를 스프링 빈으로 등록한다.
- 메서드의 파라미터로 다른 빈을 주입받을 수 있어, 생성자 주입과 유사한 방식으로 의존성을 주입할 수 있다.
@Configuration
public class AppConfig {
@Bean
public PaymentService paymentService() {
return new PaymentService();
}
@Bean
public OrderService orderService(MemberRepository repository) {
return new OrderService(repository); // repository는 이미 빈으로 등록된 상태
}
}
@Bean 메서드는 기본적으로 호출될 때마다 새로운 객체를 생성하지 않는다. 스프링 컨테이너가 미리 생성한 싱글톤 빈을 반환한다.
✅ @ComponentScan
그렇다면 @Component 계열 어노테이션을 통해 빈을 등록할 때, 별도로 등록하지 않아도 되는 이유는 무엇일까? 그 비밀은 바로 @ComponentScan 어노테이션에 있다.
▶ 기본 동작 방식
@ComponentScan은 스프링이 지정된 패키지를 기준으로 하위 패키지를 탐색하며, @Component 계열 어노테이션이 붙은 클래스를 자동으로 빈으로 등록한다.
@ComponentScan(basePackages = "com.example.myapp")
- basePackages에 지정된 패키지를 기준으로 하위 패키지를 스캔한다.
- 기본값은 @ComponentScan이 선언된 클래스가 속한 패키지를 기준으로 동작한다.
▶ 빈 스캔 구조 시각화
@ComponentScan
└── com.example.myapp
├── controller → @RestController MyController
├── service → @Service MyService
├── repository → @Repository MyRepository
└── config → @Configuration MyConfig
@ComponentScan은 com.example.myapp 패키지를 기준으로 하위 패키지를 탐색하여, 각 계층에서 적절히 사용된 스테레오타입 어노테이션을 통해 의미 기반으로 빈을 등록한다.
@Configuration 클래스는 @ComponentScan의 스캔 대상이 되지만, 그 안의 @Bean 메서드는 실행 시점에 빈으로 등록된다.
✅ @SpringBootApplication
@SpringBootApplication은 스프링 부트에서 가장 자주 사용되는 어노테이션이자 애플리케이션의 진입점이다. 우리가 별다른 설정 없이도 애플리케이션을 실행할 수 있는 이유는, 이 어노테이션이 위에서 배운 핵심 어노테이션을 포함하고 있기 때문이다.
- @SpringBootConfiguration: @Configuration의 특수한 형태로, 스프링 부트 애플리케이션의 기본 설정 클래스임을 나타낸다. ApplicationContext를 구성하는 데 사용되며, 특히 통합 테스트 시 애플리케이션 설정을 식별하는 기준점으로 활용된다.
- @EnableAutoConfiguration: 스프링 부트의 핵심 기능 중 하나로, 설정을 자동으로 구성해 주는 다양한 클래스를 조건에 맞게 로딩한다.
- @ComponentScan: 현재 클래스가 위치한 패키지를 기준으로 하위 패키지의 컴포넌트들을 자동으로 스캔하여 빈으로 등록한다.
따라서 애플리케이션의 시작 클래스에 @SpringBootApplication 하나만 선언해도, 스프링 부트는 자동으로 컴포넌트 스캔과 의존성 주입을 설정해 주어 개발자는 훨씬 편리하게 애플리케이션을 구성할 수 있다.
📍 참고 자료
- Spring 공식 문서 - Classpath Scanning and Managed Components
- Spring 공식 문서 - Context Configuration with Component Classes
- Spring 공식 문서 - Spring Beans and Dependency Injection
- Spring 공식 문서 - Basic Concepts: @Bean and @Configuration
- Spring 공식 문서 - Using the @Bean Annotation
- Spring 공식 문서 - Using the @Configuration annotation
- Spring 공식 문서 - Using the @SpringBootApplication Annotation
'Programming > Spring' 카테고리의 다른 글
[Spring] IoC 컨테이너, 의존성 주입(DI) (0) | 2025.04.23 |
---|---|
[Spring] Spring MVC 어노테이션 (0) | 2025.04.22 |