C#

C# 기초부터 고급까지 Chapter 2.1.5. DIP (Dependency Inversion Principle) – 의존성 역전 원칙

Juan_ 2025. 4. 27. 21:08
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