728x90
DI(의존성 주입, Dependency Injection)이란
의존성 주입(DI, Dependency Injection)은 디자인 패턴 중 하나로 클래스 내 의존관계를 가진 인스턴스를 생성하는 것 대신 주입을 하는 것이 특징이다.
DI의 유형
의존성 주입의 유형은 여러가지가 있다.
- Constructor Injection
- Setter Injection
- Interface Injection
- Field Injection
DI의 장점
- 코드의 유연성과 재사용성이 높아서 생산성이 높아진다
- 테스트와 유지보수가 간편해진다
- 확장성이 좋다
- 가독성이 좋다
DI의 단점
- 클래스가 점점 많아지면 복잡도가 커진다
- 주입된 클래스 추적이 어렵다
- 프레임워크에 대한 의존성이 커진다
생성자 주입 시나리오 1
일반적인 시나리오는 이렇다.
Normal flow of API to read posts
1. request -> Controller
2. Controller -> Service
3. Service -> Repository
// Controller Layer
import { UserService } from "./UserService";
export class UserController {
userService: UserService;
constructor() {
this.userService = new UserService();
}
getUserData = () => {
this.userService.getUserData();
}
}
// Service Layer
import { UserRepository } from "./UserRepository";
export class UserService {
userRepo: UserRepository;
constructor() {
this.userRepo = new UserRepository();
}
getUserData = () => {
this.userRepo.getAll();
}
}
여기서 서비스 레이어는 리파지토리와 의존 관계를 가진다. 즉, UserRepository
- UserService
가 서로 묶여있는 상황이다.
이 경우 jest로 테스트 할 시, DB mock 데이터를 생성하기가 까다로워진다.
위 문제는 UserRepository
클래스를 UserService
의 생성자에 주입함으로서 해결할 수 있다.
Before DI
// Service Layer without DI
import { UserRepository } from "./UserRepository";
export class UserService {
userRepo: UserRepository;
constructor() {
this.userRepo = new UserRepository();
}
getUserData = () => {
this.userRepo.getAll();
}
}
After DI
// Service Layer with DI
import { UserRepository } from "./UserRepository";
export class UserService {
userRepo: UserRepository;
constructor(userRepo: UserRepository) {
this.userRepo = userRepo;
}
getUserData = () => {
this.userRepos.getAll();
}
}
테스팅도 쉬워졌다. Service 인스턴스 생성 시 mockUserRepo를 주입하기만 하면 된다.
import { UserService } from "./UserService";
import { UserRepository } from "./UserRepository";
const mockUserRepo = {
getAll: jest.fn(),
};
const userService = new UserService(mockUserRepo);
userService.getUserData();
expect(mockUserRepo.getAll).toHaveBeenCalled();
생성자 주입 Scenario 2
// Without dependency Injection
class InviteService {
sendInvitation(eventName, recipient) {
console.log(
`Dear ${recipient}, We are please to inform you that you are invited to join ${eventName}.`
);
}
}
class NotificationService {
constructor() {
// creating instance inside another instance
this.inviteService = new InviteService();
}
sendNotification(eventName, recipient) {
this.inviteService.sendInvitation(eventName, recipient);
}
}
const singleNoti = new NotificationService();
singleNoti.sendNotification('SS22 VIP trunk show', 'Sujan');
// Dear Sujan, We are please to inform you that you are invited to join SS22 VIP trunk show.
// With dependency Injection
class InviteService {
sendInvitation(eventName, recipient) {
console.log(
`Dear ${recipient}, We are please to inform you that you are invited to join ${eventName}.`
);
}
}
class NotificationService {
constructor(inviteService) {
this.inviteService = inviteService;
}
sendNotification(eventName, recipient) {
this.inviteService.sendInvitation(eventName, recipient);
}
}
// instantiate InviteService
const inviteService = new InviteService();
// Inject InviteService instance into NotificationService
const singleNoti = new NotificationService(inviteService);
// Use singleNoti method
singleNoti.sendNotification('Public Fashion Show', 'John');
// Dear John, We are please to inform you that you are invited to join Public Fashion Show.
Reference
728x90
'Research > Computer Science' 카테고리의 다른 글
Parameter와 Argument의 차이 (0) | 2023.03.30 |
---|---|
MSA(MicroService Architecture) (0) | 2023.03.29 |
DB 인덱스 (0) | 2023.03.28 |
REST API (0) | 2023.03.27 |
OOP(Object-Oriented Programming) (0) | 2023.03.27 |
댓글