10. SOLID - ISP

1. SOLID 원칙
더보기
1. SOLID
OOP, 객체 지향 프로그래밍 설계의 기본 원칙
SOLID | Eng. | Kor. |
SRP | Single Responsibility Principle | 단일 책임 원칙 |
OCP | Open-Closed Principle | 개방-폐쇄 원칙 |
LSP | Liskov Substitution Principle | 리스코프 치환 원칙 |
ISP | Interface Segregation Principle | 인터페이스 분리 원칙 |
DIP | Dependency Inversion Principle | 의존성 역전 원칙 |
2. 인터페이스 분리 원칙(ISP, Interface Segregation Principle)
더보기
Many client-specific interfaces are better than one general-purpose interface
"구현할 필요가 없는 기능을 가진, 인터페이스에 의존하도록 강요받으면 안 된다."
→ 즉, 클라이언트는 자신이 필요로 하는 메서드만 가진 작은 인터페이스에 의존해야 한다.
ISP의 주요 목표
- 작고 구체적인 인터페이스를 정의하여 , 사용하지 않는 메서드를 구현하지 않도록 한다.
- 인터페이스를 필요에 따라 분리 → 단일 책임 원칙(SRP) 강화
3. 참새, 팽귄 + 오리 예시
더보기

...이전 포스트의 LSP 예제를 이어 사용합니다.
1. 가정 (ISP 위반 사례)
- 하나의 커다란 인터페이스에서 여러 기능을 정의하고, 모든 클래스가 이를 강제 구현
- 클라이언트가 필요하지 않은 메서드까지 구현해야 하는 경우 발생
2. ❌ ISP를 위반한 코드
using System; namespace ISPViolationExample { // ❌ 너무 많은 책임을 가지는 인터페이스 (ISP 위반) public interface IBird { void Eat(); void Fly(); void Swim(); } // ❌ 참새는 수영할 수 없지만 인터페이스의 Swim()을 구현해야 함 → ISP 위반 public class Sparrow : IBird { public void Eat() { Console.WriteLine("참새가 먹이를 먹는다."); } public void Fly() { Console.WriteLine("참새가 날아간다."); } public void Swim() { Console.WriteLine("참새는 수영할 수 없다."); // ❌ 잘못된 구현 → ISP 위반 } } // ❌ 펭귄은 날 수 없지만 인터페이스의 Fly()를 구현해야 함 → ISP 위반 public class Penguin : IBird { public void Eat() { Console.WriteLine("펭귄이 먹이를 먹는다."); } public void Fly() { throw new NotImplementedException("펭귄은 날 수 없습니다."); // ❌ 강제 구현 → ISP 위반 } public void Swim() { Console.WriteLine("펭귄이 수영한다."); } } class Program { static void Main() { IBird sparrow = new Sparrow(); sparrow.Eat(); sparrow.Fly(); // 정상 sparrow.Swim(); // ❌ 의미 없는 동작 수행 IBird penguin = new Penguin(); penguin.Eat(); penguin.Fly(); // ❌ 런타임 오류 발생 가능 → ISP 위반 penguin.Swim(); // 정상 } } }
3. ❌ OCP를 위반한 코드 문제점 파악
- IBird 인터페이스에 너무 많은 기능 포함 → 클라이언트가 필요 없는 메서드를 구현해야 함
- 펭귄은 날 수 없음에도 Fly()를 구현해야 함 → ISP 위반
- 참새는 수영할 수 없음에도 Swim()을 구현해야 함 → ISP 위반
4. ✅ OCP가 지켜진 코드
using System; namespace ISPExample { // ✅ 기본 Bird 인터페이스 정의 (공통 기능만 정의) public interface IBird { void Eat(); } // ✅ 날 수 있는 새 인터페이스 정의 public interface IFlyable { void Fly(); } // ✅ 수영할 수 있는 새 인터페이스 정의 public interface ISwimmable { void Swim(); } // ✅ 참새는 날 수 있는 새이므로 IFlyable 구현 public class Sparrow : IBird, IFlyable { public void Eat() { Console.WriteLine("참새가 먹이를 먹는다."); } public void Fly() { Console.WriteLine("참새가 날아간다."); } } // ✅ 펭귄은 수영할 수 있는 새이므로 ISwimmable 구현 public class Penguin : IBird, ISwimmable { public void Eat() { Console.WriteLine("펭귄이 먹이를 먹는다."); } public void Swim() { Console.WriteLine("펭귄이 수영한다."); } } // ✅ 오리는 날고 수영할 수 있으므로 두 인터페이스 모두 구현 public class Duck : IBird, IFlyable, ISwimmable { public void Eat() { Console.WriteLine("오리가 먹이를 먹는다."); } public void Fly() { Console.WriteLine("오리가 날아간다."); } public void Swim() { Console.WriteLine("오리가 수영한다."); } } class Program { static void Main() { IBird sparrow = new Sparrow(); sparrow.Eat(); ((IFlyable)sparrow).Fly(); // 참새는 날 수 있음 IBird penguin = new Penguin(); penguin.Eat(); ((ISwimmable)penguin).Swim(); // 펭귄은 수영할 수 있음 IBird duck = new Duck(); duck.Eat(); ((IFlyable)duck).Fly(); // 오리는 날 수 있음 ((ISwimmable)duck).Swim(); // 오리는 수영할 수 있음 } } }
5. ✅ ISP를 준수한 코드에서 개선된 부분 파악
- 필요한 기능별로 인터페이스를 분리
- 날 수 있는 새는 IFlyable 인터페이스에서 정의
- 수영할 수 있는 새는 ISwimmable 인터페이스에서 정의
- 인터페이스를 명확하게 구분함으로써 불필요한 메서드 구현 방지

4. 과제
더보기
ISP를 준수하여, 수륙양용차를 C#으로 구현하세요.
- Car 클래스 → 육지에서만 동작
- Boat 클래스 → 물에서만 동작
- AmphibiousCar 클래스 → 육지와 물에서 모두 동작
참고 링크(Python 코드임)
댓글을 사용할 수 없습니다.