Dependency Injection (DI)은 객체 지향 프로그래밍에서 사용되는 디자인 패턴 중 하나로, 클래스 간의 결합도를 낮추고 코드의 유연성과 재사용성을 높이는데 도움을 준다. DI는 클래스 내부에서 직접적으로 객체를 생성하는 대신, 외부에서 생성된 객체(의존성)를 주입하는 방식으로 작동한다.
이 패턴의 주요 이점은 다음과 같다:
① 코드의 모듈성: 의존성 주입을 사용하면 클래스들이 서로 덜 의존하게 되므로, 코드의 모듈성이 향상된다.
② 유연성과 확장성: 클래스 간 결합도가 낮아지면, 기능 변경이나 확장이 더 쉽고 간단해진다.
③ 테스트 용이성: 의존성 주입을 사용하면, 테스트 시 의존성을 쉽게 대체하거나 모의 객체로 교체할 수 있어 테스트 용이성이 향상된다.
DI는 주로 생성자 주입, 세터 주입, 인터페이스 주입 등의 방식으로 구현할 수 있다. 프레임워크나 라이브러리를 통해 자동화된 의존성 주입을 사용할 수도 있다. 대표적인 예로 Java의 Spring 프레임워크, .NET의 ASP.NET Core, Python의 Flask-Injector 등이 있다.
예시코드
- MessageService Interface를 만든다.
public interface MessageService {
String getMessage();
}
- `MessageService` 인터페이스를 구현한 `HelloMessageService` 클래스를 생성한다.
import org.springframework.stereotype.Service;
@Service
public class HelloMessageService implements MessageService {
@Override
public String getMessage() {
return "Hello, Spring Boot!"
}
}
- `MessageController` 클래스를 생성하고, `MessageService`를 의존성을 주입한다.
이때 @Autowired 사용한다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MessageController {
private final MessageService messageService;
@Autowired
public MessageController(MessageService messageService) {
this.messageService = messageService;
}
@GetMapping("/message")
public String getMessage() {
return messageService.getMessage();
}
}
위 코드에서 `MessageController`의 생성자에 `@Autowired` 사용하여
`MessageService`의 구현체인 `HelloMessageService`를 자동으로 주입한다.
이렇게 하면 `MessageController`는 `MessageService`의 구체적인 구현에 대해 알 필요 없이 인터페이스를 통해 메서드를 호출할 수 있다. 이 방식은 코드의 결합도를 낮추고 유연성을 높이는 데 도움을 준다.
만약 MessageService 인터페이스의 구현체를 바꾸고 @Autowired에 되는 걸 바꾸고 싶다면,
1.일단 MessageService 인터페이스의 구현체를 하나 더 만든다.
import org.springframework.stereotype.Service;
@Service
public class GoodbyeMessageService implements MessageService {
@Override
public String getMessage() {
return "Goodbye, Spring Boot!"
}
}
2.MessageConfiguration 설정 클래스를 하나 만들어서 GoodbyeMessageService를 사용하도록 설정한다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MessageConfiguration {
@Bean
public MessageService messageService() {
return new GoodbyeMessageService();
}
}
위의 코드에서 `MessageConfiguration` 클래스를 사용해서
`MessageService` 빈을 `GoodbyeMessageService`의 인스턴스로 설정했다.
이제 `MessageController`에서 `MessageService`인터페이스의 구현체로
`GoodbyeMessageService`가 주입되어 사용된다.
'스프링부트' 카테고리의 다른 글
IoC(Inversion of Control)/DI(Dependency Injection) (0) | 2023.05.18 |
---|---|
th 문법(with) (0) | 2023.05.14 |
데이터 전송을 위한 DTO(Data Transfer Object) 이해하기 (0) | 2023.04.13 |
데이터베이스 조작을 위한 DAO(Data Access Object) 이해하기 (0) | 2023.04.13 |
DTO와 DAO의 차이점 DTO: Data Transfer Object/DAO: Data Access Object (0) | 2023.04.13 |