728x90
    
    
  📚 Chapter 2.1.5. DIP (Dependency Inversion Principle) – 의존성 역전 원칙
✅ DIP란?
"고수준 모듈은 저수준 모듈에 의존하면 안 된다.
둘 다 추상(인터페이스, 추상 클래스)에 의존해야 한다."
쉽게 말하면,
- 구체적인 구현체에 직접 매달리지 말고
- 인터페이스(추상)에 의존하라는 거다!
📚 왜 DIP가 중요한가?
| 문제 상황 | 결과 | 
|---|---|
| 코드가 구체 구현에 묶여 있음 | 기능 교체/확장 시 코드 수정 폭발 | 
| 테스트 힘듦 | Mock 객체로 대체 불가능 | 
| 확장성 제로 | 새로운 기능 추가 때마다 대공사 | 
✅ DIP를 지키면 →
- 기능 변경 자유로워지고
- 테스트 더 쉬워지고
- 코드 재사용성 쭉 올라간다!
🛠️ 기본 나쁜 예제: DIP 위반
public class EmailSender
{
    public void Send(string message)
    {
        Console.WriteLine($"이메일 전송: {message}");
    }
}
public class Notification
{
    private EmailSender _emailSender = new EmailSender();
    public void Alert(string message)
    {
        _emailSender.Send(message);
    }
}
❌ 문제점
- Notification 클래스가 EmailSender 구체 클래스에 딱 붙어있음
- 만약 SMS, Slack 전송 추가하려면?
- Notification도 수정해야 한다!!! (OCP 위반 + DIP 위반)
 
🛠️ 좋은 예제: DIP 적용
1. 인터페이스 만들기
public interface IMessageSender
{
    void Send(string message);
}
2. 구현체 만들기
public class EmailSender : IMessageSender
{
    public void Send(string message)
    {
        Console.WriteLine($"이메일 전송: {message}");
    }
}
public class SmsSender : IMessageSender
{
    public void Send(string message)
    {
        Console.WriteLine($"문자메시지 전송: {message}");
    }
}
3. 고수준 모듈은 인터페이스에만 의존!
public class Notification
{
    private readonly IMessageSender _messageSender;
    public Notification(IMessageSender messageSender)
    {
        _messageSender = messageSender;
    }
    public void Alert(string message)
    {
        _messageSender.Send(message);
    }
}
✅ 이제 Notification은
- EmailSender든, SmsSender든,
- 심지어 새로운 KakaoTalkSender가 생겨도!
- Notification 코드 수정할 필요가 없다!
📚 실무 스타일 예시: .NET DI 컨테이너 사용
services.AddTransient<IMessageSender, EmailSender>();
services.AddTransient<Notification>();
- 인터페이스로 등록하고
- 컨테이너가 주입해주니까
- DIP 자연스럽게 지켜진다!
(→ 이건 2.2장 "DI" 챕터에서 아주 구체적으로 들어간다!)
✨ DIP 심화 – 실전 설계 꿀팁
| 상황 | 해결법 | 
|---|---|
| 생성자에 구체 클래스 들어간다 | 100% DIP 위반이다 | 
| 테스트 더블(Mock) 만들기 힘들다 | DIP 위반 가능성 | 
| 코드 변경할 때 도미노처럼 수정된다 | DIP 안 지킨 결과다 | 
🎯 DIP를 지키면 생기는 실무 장점
| 항목 | 효과 | 
|---|---|
| 기능 교체 쉬움 | 새로운 전송 수단 추가해도 코드 수정 없음 | 
| 테스트 용이 | 가짜(Mock) 구현체로 쉽게 테스트 | 
| 재사용성 향상 | 고수준 모듈을 여러 곳에서 재활용 가능 | 
✅ DIP 요약
| 항목 | 설명 | 
|---|---|
| 목표 | 고수준/저수준 모두 추상에 의존 | 
| 신호 | 구체 클래스(new EmailSender())에 의존하면 위험 | 
| 해결책 | 인터페이스 기반 설계 + 생성자 주입(DI) | 
728x90