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