📌 DI : 강한 결합 문제


게시판을 만든다고 가정하자. 그럼 게시글을 저장하는 기능이 필요하다

public class PostService {
    private PostRepository repository = new PostRepository();

    public void savePost(String title, String content) {
        repository.save(title, content);
    }
}
public class PostRepository {
    public void save(String title, String content) {
        // DB에 저장하는 로직
        System.out.println("MySQL에 저장: " + title);
    }
}

겉보기엔 문제가 없어 보이지만, 이 코드에는 심각한 문제가 있다

⇒ 만약 DB를 MySQL에서 PostgreSQL로 바꿔야 한다면?

public class PostgresPostRepository {
    public void save(String title, String content) {
        System.out.println("PostgreSQL에 저장: " + title);
    }
}

새 Repository를 만들었지만, PostService 내부의 코드를 직접 수정해야 한다:

public class PostService {
    // 이 줄을 수정해야 함
    private PostgresPostRepository repository = new PostgresPostRepository();
}

지금은 PostService 하나지만, 실제 프로젝트에서 PostRepository를 쓰는 클래스가 50개라면? 50군데를 전부 찾아서 수정해야 한다! 이것이 “강한 결합(tight coupling)”의 문제이다

✅ 해결 1: 인터페이스로 분리


Java의 인터페이스를 사용해서 "무엇을 하는지"와 "어떻게 하는지"를 분리

public interface PostRepository {
    void save(String title, String content);
}
public class MysqlPostRepository implements PostRepository {
    @Override
    public void save(String title, String content) {
        System.out.println("MySQL에 저장: " + title);
    }
}
public class PostgresPostRepository implements PostRepository {
    @Override
    public void save(String title, String content) {
        System.out.println("PostgreSQL에 저장: " + title);
    }
}
public class PostService {
    private PostRepository repository = new MysqlPostRepository(); // 여전히 문제!

    public void savePost(String title, String content) {
        repository.save(title, content);
    }
}

인터페이스를 도입했지만, PostService 안에서 여전히 new MysqlPostRepository()를 직접 만들고 있다(DB를 바꾸려면 이 줄을 수정해야 하는 건 마찬가지)

✅ 해결 2: 외부에서 주입 (DI의 탄생)