본문 바로가기
웹개발/SpringBoot

의존성 주입(DI), 스프링 빈과 의존관계

by 철없는민물장어 2023. 3. 19.
728x90
반응형

의존성 주입(DI)을 간단히 말하면, 클래스에서 필요로 하는 의존성을 직접 생성하지 않고, 외부에서 주입받는 방식이다.

이를 통해 클래스 간의 결합도를 낮추어 유연성을 높일 수 있다.

예를들어, A클래스가 B클래스를 의존한다면, A클래스에서 B클래스의 객체를 생성하고 사용하는것이 아니라, 외부에서 B클래스의 객체를 생성하여 주입하는 방식을 사용하는 것이다.

 

public class UserService {
    private final UserRepository userRepository = new UserRepositoryImpl();

    public void addUser(User user) {
        userRepository.save(user);
    }
}

예를들어, UserService클래스는 UserRepository클래스에 의존하고 있는데,

UserService클래스 내에서 UserRepository객체를 생성하여 사용하고 있다.

 

이를 DI를 적용한다면

public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void addUser(User user) {
        userRepository.save(user);
    }
}

(생성자를 이용한 DI)

UserService클래스의 생성자에서 UserRepository객체를 주입받도록 하였다.

이제 UserService객체를 생성할 때, UserRepository객체를 주입하면 된다.

더보기
(필드주입)
@Autowired private MemberService memberService;

필드주입은 위의 생성자를 이용한 DI예시에서 생성자 대신 필드에 바로 작성한 것임

(필드주입은 권장하지 않음)

@Autowired
public void setMemberService(MemberService memberService){
	this.memberService = memberService;
}

setter 주입은 위와 같다

setter가 public으로 되어있기 때문에, 언제나 setter에 접근가능하다.. 는 것이 문제!

생성자 주입을 권장한다.


@Autowired 어노테이션은 객체를 자동으로 주입해주는 기능을 한다.

스프링 컨테이너가 해당 클래스 타입의 빈을 찾아서 자동으로 주입해준다.

이를 사용하면, 클래스 내부에서 객체 생성 코드를 작성하지 않고, 스프링 컨테이너에서 주입받아 사용할 수 있다.

 

@Autowired 어노테이션을 사용하기 위해서는, 해당 클래스가 스프링 빈으로 등록되어야 하는데

빈을 등록하는 방법은 크게 2가지가 있다.

 

1. ComponentScan 과 자동 의존관계 설정

@Component 어노테이션이 있으면 스프링 빈으로 자동 등록되는데,

@Controller, @Service, @Repository 들도 @Component를 포함하기 때문에 스프링 빈으로 등록된다.

 

@Controller
public class MemberController {

    private final MemberService memberService;
    @Autowired//멤버컨트롤러가 생성될 때 스프링 빈에 등록되어있는 멤버 서비스 객체를 가져다 넣어줌.
    public MemberController(MemberService memberService){
        this.memberService = memberService;
    }
}

위 코드는:

MemberController의 생성자에 @Autowired 어노테이션을 사용하여, 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입하도록 한다. 

 

(참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본적으로는 유일한 하나의 객체만 등록해서 공유한다. 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. )

 

스프링 빈을 등록하는 2번째 방법:

자바 코드로 직접 스프링 빈 등록하기.

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}

@Bean 어노테이션을 사용하면 개발자가 직접 빈을 등록할 수 있다.

해당 어노테이션을 붙인 메소드의 반환값이 빈으로 등록된다.

 

 

.

.

실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리같은 코드는 컴포넌트 스캔방식을 사용하고,

정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.


 

728x90
반응형

'웹개발 > SpringBoot' 카테고리의 다른 글

[JPA] 엔티티 수정시 Dirty checking(변경 감지), Merge(병합)  (0) 2023.05.07
JPA, Spring Data JPA  (0) 2023.03.21
빌드하고 실행하기  (0) 2023.03.18
ObjectMapper  (0) 2023.03.14
AOP(Aspect Oriented Programming)  (1) 2023.03.14

댓글