-
Spring Framework 시리즈 2화 – @Component와 @Autowired로 의존성 주입 구현하기기술과 산업/언어 및 프레임워크 2025. 5. 20. 12:49728x90
Spring의 의존성 주입(DI)을 구성하는 기본 애노테이션인 @Component와 @Autowired의 사용법과 주의사항을 실제 코드 예제와 함께 알아봅니다.
의존성 주입(DI)은 왜 중요한가?
Spring에서 **DI(Dependency Injection)**는 객체 간 의존 관계를 외부에서 주입받는 방식으로 구성해 유연성과 테스트 용이성을 확보합니다.
직접 new로 객체를 생성하는 방식은 강한 결합을 유발하며, 테스트 시 Mock 객체를 주입하기도 어렵습니다.Spring은 이를 해결하기 위해 주요 애노테이션들을 제공합니다:
- @Component: 스프링이 관리할 객체(빈)를 선언
- @Autowired: 스프링 컨테이너에 등록된 빈을 자동으로 주입
실습 예제 – 자동차와 엔진
1. 의존 관계 정의
// Engine.java package com.example.springcore; import org.springframework.stereotype.Component; @Component public class Engine { public void start() { System.out.println("Engine started"); } }
// Car.java package com.example.springcore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class Car { private final Engine engine; @Autowired // 생성자 주입 public Car(Engine engine) { this.engine = engine; } public void drive() { engine.start(); System.out.println("Car is moving"); } }
2. 실행 클래스
// SpringCoreApplication.java package com.example.springcore; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication public class SpringCoreApplication implements CommandLineRunner { private final Car car; public SpringCoreApplication(Car car) { this.car = car; } public static void main(String[] args) { SpringApplication.run(SpringCoreApplication.class, args); } @Override public void run(String... args) { car.drive(); } }
이렇게 하면 스프링이 Engine을 자동으로 생성하고, Car 객체 생성 시 의존성을 주입해줍니다. 개발자는 직접 new 키워드를 사용하지 않아도 됩니다.
@Component의 핵심 정리
항목 설명
역할 해당 클래스를 빈으로 등록함 기본 이름 클래스명을 소문자로 시작 (engine, car) 스캔 범위 @ComponentScan이 선언된 위치부터 하위 패키지만 스캔 ※ 클래스가 하위 패키지에 없다면, 명시적으로 @ComponentScan("패키지명") 설정이 필요합니다.
@Autowired의 3가지 방식
Spring은 다음 3가지 방식으로 DI를 지원합니다:
- 생성자 주입 (추천)
- 불변성 보장
- 테스트 용이
- 필드가 final이어야 함
- 필드 주입
@Autowired private Engine engine;
- 가장 간단하지만, 테스트에서 Mock 주입이 어려워 비권장
- 세터 주입
private Engine engine; @Autowired public void setEngine(Engine engine) { this.engine = engine; }
- 선택적인 의존성에 사용 가능
- 주로 Configuration 클래스에서 활용
@Autowired 사용 시 주의사항
- 빈이 없으면 오류 발생
→ 기본적으로 필수 빈으로 간주되어, 주입 대상이 없으면 NoSuchBeanDefinitionException이 발생합니다. - ✅ 해결 방법: @Autowired(required = false) 또는 Optional<Engine>
- 순환 참조 주의
→ 두 객체가 서로를 주입할 경우 UnsatisfiedDependencyException 발생 - 스프링이 관리하지 않는 객체에는 작동하지 않음
→ 반드시 @Component, @Configuration, 혹은 Bean으로 등록된 객체에서만 동작
빈 수동 등록 – @Bean
클래스를 수정할 수 없거나 외부 라이브러리인 경우에는 @Bean을 활용해 수동 등록이 가능합니다.
@Configuration public class AppConfig { @Bean public Engine engine() { return new Engine(); } }
마무리 – @Component와 @Autowired는 Spring Core의 출발점
Spring을 처음 학습하거나, 기존 Spring Boot 프로젝트에서 내부 구조를 이해하고 싶은 개발자라면 @Component와 @Autowired의 정확한 작동 원리를 아는 것이 중요합니다.
이 두 애노테이션은 단순한 편의 기능이 아니라 스프링 컨테이너의 DI 구조를 이루는 핵심 구성요소입니다. 앞으로 나올 @Value, @Profile, @Configuration 등도 이 기반 위에 쌓인 기능들이죠.
다음 3화에서는 @Configuration과 @Bean을 활용해 Java 기반으로 설정 클래스를 구성하고 빈을 등록하는 방법을 실습해보겠습니다.
728x90'기술과 산업 > 언어 및 프레임워크' 카테고리의 다른 글
Spring Boot 시리즈 34편 – Eureka와 서비스 디스커버리 구조: 마이크로서비스 환경에서의 자동 인스턴스 탐색 전략 (0) 2025.05.21 Spring Framework 시리즈 3화 – @Configuration vs XML – 빈 설정 방식 비교 (1) 2025.05.20 Spring Boot 시리즈 33편 – Spring Cloud Gateway: API 게이트웨이 설계와 트래픽 라우팅 전략 (0) 2025.05.20 Spring Framework 시리즈 1화 – Spring Framework 시작하기 (2) 2025.05.19 Spring Boot 시리즈 32편 – OpenFeign을 활용한 외부 API 연동 아키텍처 설계 (3) 2025.05.19