이 포스트는 인프런 사이트에 김영한 - 스프링 핵심원리 강의를 보고 정리한 포스터입니다.
스프링 핵심 원리 - 기본편 강의 | 김영한 - 인프런
김영한 | , 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢 수강 전 확인해주세요! 본 강의는 자바 스프링 완전 정복 시리즈의 두 번째 강의입니다. 우아한형제들 최연
www.inflearn.com
스프링에서는 객체 간의 의존관계를 자동으로 주입하는 기능을 제공합니다.
이를 통해 개발자가 직접 객체를 생성하고 주입하는 번거로움을 줄이고, 효율적인 애플리케이션 설계를 할 수 있습니다.
이번 포스트에서는 의존관계 자동 주입의 개념과 다양한 주입 방법, 옵션 처리, 생성자 주입을 선택해야 하는 이유, 롬복을 활용한 최신 트렌드까지 정리하겠습니다.
🔆 다양한 의존관계 주입 방법
스프링에서는 의존관계를 주입하는 방법으로 4가지 방식을 제공합니다.
각 방식의 장점과 단점이 존재하며, 상황에 맞게 선택해야 합니다.
🌀 (1) 생성자 주입 (Constructor Injection)
생성자를 통해 의존관계를 주입하는 방식
생성자 호출 시점에 한 번만 호출되므로, 불변성과 안정성이 보장됨
@Autowired 생략 가능 (생성자가 하나일 경우, 스프링이 자동으로 주입됨)
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
✔ final 키워드를 사용하여 불변 객체로 만들 수 있습니다.
✔ @Autowired 생략 가능 (생성자가 하나뿐이라면 자동으로 주입됩니다).
🌀 (2) 수정자 주입 (Setter Injection)
setXxx() 메서드를 통해 의존관계를 주입하는 방식
선택적으로 의존관계를 변경할 수 있음
필수적인 의존관계에는 적절하지 않음
자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용함
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
✔ 유연성이 높아 필요에 따라 의존관계를 변경할 수 있습니다.
❌ 반드시 의존관계가 필요한 경우에는 사용하지 않는 것이 좋습니다. (누락 가능성 존재)
🌀 (3) 필드 주입 (Field Injection)
필드에 @Autowired를 직접 붙여서 의존관계를 주입하는 방식
코드가 간결하지만, 외부에서 변경이 불가능하여 테스트가 어려움
DI 프레임워크 없이 객체를 생성할 수 없기 때문에 권장하지 않음
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
✔ 코드가 간결합니다.
❌ 외부에서 변경이 불가능하여 테스트가 어렵습니다.
❌ 스프링 컨테이너 없이 동작할 수 없는 구조가 됩니다.
🔹 실무에서는 사용하지 않는 것이 좋으며, @Configuration 같은 설정용 클래스에서만 사용이 권장됩니다.
🌀 (4) 일반 메서드 주입
일반적인 메서드를 통해 의존관계를 주입하는 방식
한 번에 여러 필드를 주입받을 수 있지만, 잘 사용되지 않음
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
✔ 한 번에 여러 필드를 주입받을 수 있습니다.
❌ 일반적으로 잘 사용되지 않으며, 가독성이 떨어집니다.
🔆 옵션 처리
스프링에서 의존관계를 자동으로 주입할 때, 주입할 대상이 존재하지 않는 경우가 있습니다.
기본적으로 @Autowired는 주입할 대상이 없으면 오류가 발생하지만, 옵션을 설정하면 예외를 방지할 수 있습니다.
방법 | 설명 |
@Autowired(required = false) | 주입할 대상이 없으면 아예 메서드가 호출되지 않습니다. |
org.springframework.lang.@Nullable | 주입할 대상이 없으면 null이 주입됩니다. |
Optional<> | 주입할 대상이 없으면 Optional.empty가 주입됩니다. |
✅ 코드 예제
@Autowired(required = false)
public void setNoBean1(Member member) {
System.out.println("setNoBean1 = " + member);
}
@Autowired
public void setNoBean2(@Nullable Member member) {
System.out.println("setNoBean2 = " + member);
}
@Autowired
public void setNoBean3(Optional<Member> member) {
System.out.println("setNoBean3 = " + member);
}
✔ setNoBean1()은 호출되지 않습니다.
✔ setNoBean2()는 null이 출력됩니다.
✔ setNoBean3()는 Optional.empty가 출력됩니다.
🔆 생성자 주입을 선택해야 하는 이유
최근에는 생성자 주입이 가장 권장되는 방식입니다.
불변성을 유지할 수 있으며, 주입 데이터를 컴파일 시점에서 체크할 수 있기 때문입니다.
✔ 생성자 주입은 필수 필드를 final로 선언할 수 있어 컴파일 오류를 방지할 수 있습니다.
✔ 테스트 시, 생성자 인자를 직접 주입할 수 있어 단위 테스트가 용이합니다.
✔ 필수적인 의존관계를 누락 없이 설정할 수 있습니다.
🔆 롬복과 최신 트렌드
스프링에서 생성자 주입을 사용할 경우, 롬복(Lombok)의 @RequiredArgsConstructor를 활용하면
코드를 간결하게 유지할 수 있습니다.
✅ 롬복 적용 후 코드
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
✔ @RequiredArgsConstructor를 사용하면 final 필드를 자동으로 생성자 주입해줍니다.
✔ @Autowired를 생략해도 됩니다.
✅ 롬복 라이브러리 적용 방법
plugins {
id 'org.springframework.boot' version '2.3.2.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
//lombok 설정 추가 시작
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
//lombok 설정 추가 끝
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
//lombok 라이브러리 추가 시작
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
//lombok 라이브러리 추가 끝
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
1. Preferences(윈도우 File Settings) -> plugin -> lombok 검색 설치 실행 (재시작)
2. Preferences -> Annotation Processors 검색 -> Enable annotation processing 체크 (재시작)
3. 임의의 테스트 클래스를 만들고 @Getter, @Setter 확인
스프링의 의존관계 자동 주입을 올바르게 활용하면 코드의 유지보수성과 확장성을 크게 향상시킬 수 있습니다. 🚀
다음 포스트에서는 빈이 2개 이상일 때 발생하는 문제와 해결 방법(@Autowired 필드 명, @Qualifier, @Primary), 애노테이션을 직접 만들어 해결하는 방법, 조회한 빈이 모두 필요할 때 List와 Map을 사용하는 방법, 그리고 자동과 수동 등록의 올바른 실무 운영 기준에 대해 자세히 정리되어 있으니 확인 부탁드립니다 ~~
의존관계 자동 주입 2편
이 포스트는 인프런 사이트에 김영한 - 스프링 핵심원리 강의를 보고 정리한 포스터입니다.https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8 스프
uplifted.tistory.com
'개발일지 > Spring' 카테고리의 다른 글
빈 생명주기 콜백 (0) | 2025.02.20 |
---|---|
의존관계 자동 주입 2편 (0) | 2025.02.19 |
컴포넌트 스캔 (0) | 2025.02.18 |
싱글톤 패턴, 싱글톤 컨테이너 (0) | 2025.02.18 |
스프링 빈 설정 메타 정보 - BeanDefinition (0) | 2025.02.13 |