스프링을 사용하면 객체 간의 의존성을 관리하는 방식이 기존의 Java 코드와 다르다.
특히, **의존성 주입(DI, Dependency Injection)**은 스프링의 핵심 개념 중 하나이며, 이를 통해 객체 간의 결합도를 낮추고 유지보수를 쉽게 만들 수 있다.
✅ 의존성(Dependency)이란?
객체 A가 객체 B를 사용해야 할 때, A는 B에 **의존(Dependency)**한다고 말할 수 있다.
예를 들어, MemberService 클래스에서 MemberRepository 클래스를 사용한다고 가정해 보자.
public class MemberService {
private MemberRepository memberRepository = new MemberRepository();
}
위 코드에서는 MemberService가 MemberRepository를 직접 생성하고 있다.
이 방식은 클래스 간의 결합도가 높아지기 때문에, MemberRepository의 변경이 필요할 경우 MemberService도 함께 수정해야 한다.
이러한 문제를 해결하기 위해 DI(Dependency Injection) 개념이 등장했다.
✅ DI(의존성 주입)이란?
DI는 객체를 직접 생성하는 것이 아니라 외부에서 주입받는 방식을 의미한다.
즉, 클래스가 필요로 하는 객체를 직접 생성하는 것이 아니라, 스프링 컨테이너가 대신 생성하고 주입해 준다.
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired // 의존성 자동 주입
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
위 코드에서 MemberRepository 객체는 new 키워드로 직접 생성되지 않는다.
대신, @Autowired 어노테이션을 통해 스프링 컨테이너가 자동으로 주입해 준다.
이렇게 하면 MemberService는 MemberRepository의 변경에 영향을 받지 않고 독립적으로 동작할 수 있다.
✅ DI의 주요 장점
1️⃣ 결합도 감소 → 클래스 간의 의존성을 줄여 유지보수가 쉬워진다.
2️⃣ 객체 관리 자동화 → 스프링이 객체를 자동으로 생성하고 주입해 준다.
3️⃣ 테스트 용이 → Mock 객체를 활용하여 단위 테스트가 쉬워진다.
4️⃣ 유연한 설정 가능 → XML, Java Config, 어노테이션 방식 등 다양한 설정 방법을 지원한다.
✅ DI(의존성 주입)의 종류
DI에는 크게 생성자 주입, 필드 주입, 세터 주입 3가지 방식이 있다.
1️⃣ 생성자 주입 (Constructor Injection) - 가장 권장되는 방식
생성자를 통해 필요한 객체를 주입하는 방식이다.
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
📌 장점
✅ 객체가 반드시 주입되도록 보장할 수 있다.
✅ final 키워드를 사용할 수 있어 불변성을 유지할 수 있다.
✅ 테스트 시 Mock 객체를 쉽게 주입할 수 있다.
2️⃣ 필드 주입 (Field Injection) - 권장되지 않음
필드에 직접 @Autowired 어노테이션을 붙여 의존성을 주입하는 방식이다.
@Service
public class MemberService {
@Autowired
private MemberRepository memberRepository;
}
📌 단점
❌ 테스트 시 Mock 객체를 주입하기 어렵다.
❌ 순환 참조 문제가 발생해도 실행 전에는 알기 어렵다.
❌ 객체 변경이 불가능하다.
👉 필드 주입 방식은 사용을 지양하는 것이 좋다.
3️⃣ 세터 주입 (Setter Injection) - 선택적 의존성 주입 가능
Setter 메서드를 통해 의존성을 주입하는 방식이다.
@Service
public class MemberService {
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
📌 장점
✅ 의존성을 선택적으로 변경할 수 있다.
✅ 순환 참조 문제를 피할 수 있다.
📌 단점
❌ 불필요한 setter 메서드가 추가될 가능성이 있다.
❌ 변경이 많지 않은 객체라면 불필요한 코드가 될 수 있다.
✅ DI와 함께 알아두면 좋은 개념
개념 | 설명 |
IoC (Inversion of Control) |
제어의 역전. 객체 생성을 개발자가 아닌 스프링 컨테이너가 관리
|
Bean |
스프링이 관리하는 객체. @Component, @Service, @Repository 등을 사용해 등록
|
ApplicationContext |
스프링 컨테이너의 핵심 인터페이스
|
@Autowired |
자동 의존성 주입을 위한 어노테이션
|
@Qualifier |
동일한 타입의 여러 빈이 있을 때, 특정 빈을 선택할 때 사용
|
스프링 DI(Dependency Injection)는 스프링 프레임워크의 가장 중요한 개념 중 하나다.
의존성 주입을 활용하면 객체 간의 결합도를 줄이고, 유지보수성을 높이며, 테스트가 쉬워진다.
특히, 생성자 주입 방식이 가장 권장되며, 필드 주입은 지양하는 것이 좋다.
'IT개발 > Spring Framework' 카테고리의 다른 글
@Transactional: 데이터베이스 트랜잭션 관리의 핵심(백엔드개발/Spring Framework) (1) | 2025.02.28 |
---|---|
Koyeb 으로 백엔드 프로젝트(Spring 프로젝트) 배포해보기(Github Repository 기반 배포) - 오류발생(해결진행중) (0) | 2025.02.10 |
Spring MVC에서 컨트롤러 메소드의 매개변수 타입 (0) | 2025.01.17 |
카카오맵 api 사용 에러 해결 : Uncaught ReferenceError: kakao is not defined (1) | 2024.12.21 |
Spring Container(스프링 컨테이너/프레임워크/백엔드/개발/자바/프로그래밍/java/framework) (1) | 2024.12.04 |
댓글