728x90
📘 Chapter 2.9: 인터페이스 활용 – 다형성 실전 예제
✅ 이 챕터에서 배울 것
- 인터페이스란 무엇인가?
- 다형성이 왜 필요한가?
- 구체 클래스 vs 인터페이스 비교
- 실무 시나리오 예제 (MessageSender, Discount 등)
- 전략 패턴과 인터페이스
- DI와 인터페이스 궁합
1️⃣ 인터페이스란?
인터페이스란?
"기능만 약속하는 설계도" – 실제 구현은 안 담고, 메서드 이름, 파라미터만 정의
public interface IAnimal
{
void MakeSound();
}
- 객체의 기능 규칙만 강제
- 클래스가 여러 인터페이스도 구현 가능
- 상속과 다르게 다중 구현 가능
2️⃣ 왜 인터페이스가 필요한가?
문제 상황
public class EmailSender
{
public void Send(string to, string msg)
{
Console.WriteLine($"📧 {to}에게 이메일 전송: {msg}");
}
}
나중에 "카카오톡도 보내줘!" 하면?
public class MessageSender
{
public void Send(string to, string msg)
{
if (사용자.카카오) { 카카오톡(); }
else if (사용자.이메일) { 이메일(); }
else if (사용자.슬랙) { ... }
}
}
👎 if-else 지옥 😱 – 유지보수 지옥행
✅ 해결책: 인터페이스 사용
public interface IMessageSender
{
void Send(string to, string message);
}
public class EmailSender : IMessageSender
{
public void Send(string to, string message)
{
Console.WriteLine($"📧 이메일 전송: {message}");
}
}
public class KakaoSender : IMessageSender
{
public void Send(string to, string message)
{
Console.WriteLine($"📱 카카오톡 전송: {message}");
}
}
3️⃣ 다형성 실전 활용
public class NotificationService
{
private readonly IMessageSender _sender;
public NotificationService(IMessageSender sender)
{
_sender = sender;
}
public void Notify(string user, string msg)
{
_sender.Send(user, msg);
}
}
📌 이제 EmailSender, KakaoSender, SlackSender
전부 갈아끼울 수 있다!
예제 코드
IMessageSender sender = new EmailSender(); // 또는 KakaoSender
var service = new NotificationService(sender);
service.Notify("jang@daegu.com", "오늘도 화이팅!");
➡️ NotificationService는 Send가 어떤 방식인진 몰라도 됨
4️⃣ 전략 패턴과 인터페이스
전략(Strategy) 패턴 =
"행동을 객체로 캡슐화해서 교체 가능하게 만드는 구조"
public interface IDiscountStrategy
{
decimal ApplyDiscount(decimal price);
}
public class PercentageDiscount : IDiscountStrategy
{
public decimal ApplyDiscount(decimal price) => price * 0.9m;
}
public class FixedAmountDiscount : IDiscountStrategy
{
public decimal ApplyDiscount(decimal price) => price - 5000;
}
public class OrderService
{
private readonly IDiscountStrategy _strategy;
public OrderService(IDiscountStrategy strategy)
{
_strategy = strategy;
}
public decimal CalculateFinalPrice(decimal price)
{
return _strategy.ApplyDiscount(price);
}
}
➡️ 할인 정책을 바꾸려면? 클래스만 갈아끼우면 된다 😎
5️⃣ DI와 인터페이스는 찰떡궁합
builder.Services.AddTransient<IMessageSender, EmailSender>();
builder.Services.AddTransient<NotificationService>();
- NotificationService는 생성자에서 IMessageSender만 의존
- 나중에
EmailSender → KakaoSender
로 교체해도 코드 수정 없음
✅ OCP (개방/폐쇄 원칙) 지킴
✅ 단위 테스트하기 쉬움
✅ Mocking도 쉬움 (xUnit/Moq 조합 가능)
✅ 정리 요약
항목 | 설명 |
---|---|
인터페이스 | 메서드 시그니처만 정의, 다중 구현 가능 |
다형성 | 구현체를 바꿔도 동일하게 동작 |
전략 패턴 | 다양한 정책을 객체로 추상화 |
DI와 궁합 | 클래스 교체 자유로움, 테스트도 쉬움 |
실무 효과 | 유지보수성 ↑, 유연성 ↑, 재사용성 ↑ |
📢 다음 챕터 예고 🎓
다음 챕터 | 주제 |
---|---|
Chapter 2.10 | 프로젝트 구조 패턴 – Layered, Clean Architecture 소개 |
728x90
'C#' 카테고리의 다른 글
C# 기초부터 고급까지 Chapter 3.1. Span , Memory , Unsafe – 퍼포먼스 챙기는 C# 코드 (0) | 2025.05.04 |
---|---|
C# 기초부터 고급까지 Chapter 2.10. 프로젝트 구조 패턴 – Layered vs Clean Architecture 소개 (0) | 2025.05.04 |
C# 기초부터 고급까지 Chapter 2.8.1: MSTest 완전정복 – 기본부터 실전 예제까지 (2) | 2025.05.02 |
C# 기초부터 고급까지 Chapter 2.8. 테스트 코드 작성 기초 – xUnit 완전정복 편 (0) | 2025.05.02 |
C# 기초부터 고급까지 Chapter 2.7. 예외처리 전략 – Retry, Fallback, Polly 패턴 (4) | 2025.05.01 |