[SeSACx코딩온] 의존성 주입(Dependency Injection)
1. 의존성 주입이란?
- 의존성 주입(Dependency Injection)은 객체 간 결합도를 낮추고 코드를 더 유연하게 만들어주는 설계 방식입니다.
- 클래스가 필요한 객체를 직접 생성하지 않고, 외부에서 주입받아 사용합니다.
주요 특징
- 결합도 감소
- 유연성 증가
- 테스트 용이성 향상
2. 의존성 주입이 없는 코드
의존성 주입을 적용하지 않은 코드에서는 클래스가 특정 구현체에 강하게 결합되어 있습니다. 이를 통해 문제점을 살펴보겠습니다.
게시글 관리 기능 (BoardService.java)
public class BoardService {
private final FileBoardPersistence persistence;
public BoardService() {
this.persistence = new FileBoardPersistence();
}
public void save() {
persistence.save();
}
public void delete() {
persistence.delete();
}
}
BoardService
는 게시글 저장 및 삭제를 관리하는 클래스입니다.FileBoardPersistence
라는 파일 저장 클래스와 직접적으로 연결되어 있어, 저장 방식을 바꾸려면 이 코드 자체를 수정해야 합니다.
파일 저장 클래스 (FileBoardPersistence.java)
public class FileBoardPersistence {
public void save() {
System.out.println("파일에 게시글 저장 중...");
}
public void delete() {
System.out.println("파일에 저장된 게시글 삭제 중...");
}
}
- 이 클래스는 파일에 게시글을 저장하거나 삭제하는 역할을 합니다.
- 저장 방식을 데이터베이스로 변경하려면 모든
FileBoardPersistence
호출을 수정해야 합니다.
실행 코드 (Main.java)
public class Main {
public static void main(String[] args) {
BoardService service = new BoardService();
service.save();
service.delete();
}
}
문제점 정리
BoardService
는 특정 구현체(FileBoardPersistence
)에 강하게 결합되어 있습니다.- 저장 방식을 변경하려면 코드 전반을 수정해야 합니다.
- 테스트 환경에서 Mock 객체를 주입하기 어렵습니다.
3. 의존성 주입 적용 후
의존성 주입을 사용하면 클래스 간 결합도를 낮추고, 저장 방식을 유연하게 교체할 수 있습니다.
1) 인터페이스로 공통 동작 정의하기
저장 방식과 관계없이 공통된 동작(save
, delete
)을 정의합니다.
공통 동작 인터페이스 (IBoardPersistence.java)
public interface IBoardPersistence {
void save();
void delete();
}
해석
- 이 인터페이스는 게시글을 저장하거나 삭제하는 공통 동작을 정의합니다.
- 파일이든 데이터베이스든 상관없이 이 인터페이스를 구현하면 됩니다.
2) 저장 방식 클래스 구현
파일과 데이터베이스 저장 방식을 각각 구현합니다.
파일 저장 클래스 (FileBoardPersistence.java)
public class FileBoardPersistence implements IBoardPersistence {
public void save() {
System.out.println("파일에 게시글 저장 중...");
}
public void delete() {
System.out.println("파일에 저장된 게시글 삭제 중...");
}
}
데이터베이스 저장 클래스 (DbBoardPersistence.java)
public class DbBoardPersistence implements IBoardPersistence {
public void save() {
System.out.println("데이터베이스에 게시글 저장 중...");
}
public void delete() {
System.out.println("데이터베이스에 저장된 게시글 삭제 중...");
}
}
- 두 클래스 모두
IBoardPersistence
인터페이스를 구현하여 공통 동작(save
,delete
)을 정의합니다. BoardService
는 어떤 저장 방식을 사용할지 몰라도 이 인터페이스를 통해 동일한 방식으로 호출할 수 있습니다.
3) 게시글 관리 기능 개선
게시글 관리 기능 (BoardService.java)
public class BoardService {
private IBoardPersistence persistence;
public void setIBoardPersistence(IBoardPersistence persistence) {
this.persistence = persistence;
}
public void save() {
persistence.save();
}
public void delete() {
persistence.delete();
}
}
BoardService
는 특정 구현체에 의존하지 않고,IBoardPersistence
인터페이스에만 의존합니다.- 저장 방식을
setIBoardPersistence
메서드를 통해 외부에서 주입받습니다.
4) 실행 코드에서 저장 방식 선택
실행 코드 (Main.java)
public class Main {
public static void main(String[] args) {
IBoardPersistence persistence = new DbBoardPersistence(); // 데이터베이스 방식 선택
BoardService service = new BoardService();
service.setIBoardPersistence(persistence);
service.save();
service.delete();
}
}
- 저장 방식을 데이터베이스(
DbBoardPersistence
)로 설정했습니다. - 파일 저장 방식으로 변경하려면
FileBoardPersistence
로 객체를 교체하면 됩니다. BoardService
는 수정할 필요가 없습니다.
4. 의존성 주입의 장점
- 결합도 감소
BoardService
는 특정 저장 방식에 의존하지 않으므로 유연한 코드 작성이 가능.
- 변경 용이성
- 저장 방식을 변경하려면 실행 코드에서 객체만 교체 됨.
- 테스트 용이성 향상
- Mock 객체를 주입하여 테스트 환경을 손쉽게 설정 가능.