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 객체를 주입하여 테스트 환경을 손쉽게 설정 가능.