**ISP(Interface Segregation Principle)**는 1996년 Robert C. Martin이 Xerox 컨설팅 중에 발견한 원칙이다. 이 원칙은 불필요한 의존성으로 인한 문제를 해결하기 위해 인터페이스를 분리해야 한다고 말한다.
ISP의 정의
“클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 한다.”
뚱뚱한 인터페이스의 문제
하나의 인터페이스에 많은 메서드가 있으면:
- 사용하지 않는 메서드에도 의존하게 됨
- 사용하지 않는 메서드의 변경에도 영향받음
- 재컴파일, 재배포 필요
OPS 예제
마틴은 OPS(Operations) 인터페이스 예제를 사용한다.
문제 상황
| |
세 명의 사용자가 있다:
- User1: op1()만 사용
- User2: op2()만 사용
- User3: op3()만 사용
flowchart TB
subgraph Problem [ISP 위반]
U1[User1 - op1만 필요]
U2[User2 - op2만 필요]
U3[User3 - op3만 필요]
OPS[OPS Interfaceop1, op2, op3]
IMPL[OPSImpl]
U1 --> OPS
U2 --> OPS
U3 --> OPS
IMPL -->|구현| OPS
end
문제점
op2()의 시그니처가 변경되면:
- User1도 재컴파일 (사용하지 않는데!)
- User3도 재컴파일 (사용하지 않는데!)
flowchart TB
Change[op2 변경]
U1[User1 - op1만 사용재컴파일 필요!]
U2[User2 - op2 사용재컴파일 필요]
U3[User3 - op3만 사용재컴파일 필요!]
Change --> U1
Change --> U2
Change --> U3
style U1 fill:#f99
style U3 fill:#f99
해결책: 인터페이스 분리
| |
flowchart TB
subgraph Solution [ISP 적용]
U1[User1]
U2[User2]
U3[User3]
I1[U1OPS - op1]
I2[U2OPS - op2]
I3[U3OPS - op3]
IMPL[OPSImpl]
U1 --> I1
U2 --> I2
U3 --> I3
IMPL -->|구현| I1
IMPL -->|구현| I2
IMPL -->|구현| I3
end
이제 op2() 변경 시:
- User1: 영향 없음
- User2: 재컴파일 필요
- User3: 영향 없음
정적 타입 언어 vs 동적 타입 언어
정적 타입 언어 (Java, C++, C#)
인터페이스 변경 시 재컴파일, 재배포 필요:
| |
ISP가 특히 중요하다.
동적 타입 언어 (Python, Ruby, JavaScript)
런타임에 메서드를 찾으므로 컴파일 의존성이 없음:
| |
그러나 개념적으로는 여전히 중요하다. 불필요한 의존성은 코드 이해와 유지보수를 어렵게 만든다.
아키텍처 수준의 ISP
ISP는 클래스 수준을 넘어 아키텍처 수준에서도 적용된다.
프레임워크 의존성
flowchart TB
subgraph System [시스템]
S[System S]
F[Framework F]
D[(Database D)]
S --> F
F --> D
end
시스템 S가 프레임워크 F에 의존하고, F가 데이터베이스 D에 의존한다면:
- D의 변경 → F 영향 → S도 영향
- S는 D를 직접 사용하지 않는데도!
불필요한 이행적 의존성
| |
해결책
필요한 것만 의존하도록 인터페이스 분리:
flowchart TB
subgraph Solution [ISP 적용]
S[System S]
I[Interface IS가 필요한 것만]
F[Framework F]
D[(Database D)]
S --> I
F -->|구현| I
F --> D
end
S는 I에만 의존. D 변경은 S에 영향 없음.
ISP 적용 전략
1. 역할 인터페이스 (Role Interface)
클라이언트의 역할에 따라 인터페이스 분리:
| |
2. 클라이언트 전용 인터페이스
각 클라이언트를 위한 전용 인터페이스:
| |
3. 인터페이스 상속
작은 인터페이스를 조합:
| |
ISP vs SRP
| 원칙 | 초점 | 기준 |
|---|---|---|
| SRP | 변경의 이유 | 액터 (누가 변경 요청) |
| ISP | 사용하는 것 | 클라이언트 (누가 사용) |
둘 다 응집도와 결합도에 관한 원칙이지만, 관점이 다르다:
- SRP: 내부 관점 - 모듈이 왜 변경되는가?
- ISP: 외부 관점 - 클라이언트가 무엇을 사용하는가?
실제 예시: Java의 인터페이스
나쁜 예: java.util.Collection
| |
모든 컬렉션이 모든 메서드를 의미 있게 구현하지는 않는다. 예: ImmutableList의 add()는 예외를 던진다.
좋은 예: 분리된 인터페이스
| |
핵심 요약
| 항목 | 내용 |
|---|---|
| 정의 | 클라이언트는 사용하지 않는 것에 의존하지 않아야 함 |
| 문제 | 불필요한 재컴파일, 재배포, 변경 영향 |
| 해결 | 인터페이스 분리, 역할 기반 인터페이스 |
| 적용 범위 | 클래스, 모듈, 아키텍처 수준 |
“필요 이상으로 많은 것을 포함하는 모듈에 의존하는 것은 해로운 일이다. 소스 코드 의존성의 경우 불필요한 재컴파일과 재배포를 강제하기 때문이다.” — Robert C. Martin
다음 장에서는
다음 장에서는 DIP: 의존성 역전 원칙을 다룬다. 이 원칙은 Clean Architecture의 핵심이며, 고수준 모듈이 저수준 모듈에 의존하지 않고 추상화에 의존해야 한다는 것을 말한다.
![Featured image of post [Clean Architecture] 18. ISP: 인터페이스 분리 원칙](/post/cleanarchitecture/18-isp-interface-segregation-principle/wordcloud_hu_cc766ec362c51cc.png)
![[Clean Architecture] 16. OCP: 개방-폐쇄 원칙](/post/cleanarchitecture/16-ocp-open-closed-principle/wordcloud_hu_a84054017b47f51d.png)
![[Clean Architecture] 17. LSP: 리스코프 치환 원칙](/post/cleanarchitecture/17-lsp-liskov-substitution-principle/wordcloud_hu_494cd6bbbdcbeefe.png)
![[Clean Architecture] 18. ISP: 인터페이스 분리 원칙](/post/cleanarchitecture/18-isp-interface-segregation-principle/wordcloud_hu_e792044eccd81103.png)
![[Clean Architecture] 19. DIP: 의존성 역전 원칙](/post/cleanarchitecture/19-dip-dependency-inversion-principle/wordcloud_hu_b2315221135160e2.png)
![[Clean Architecture] 20. 컴포넌트 원칙 서론](/post/cleanarchitecture/20-component-principles-introduction/wordcloud_hu_595e83323d4f659.png)
![[Clean Architecture] 14. SOLID 원칙 서론](/post/cleanarchitecture/14-solid-principles-introduction/wordcloud_hu_b40e2016719b5d89.png)
![[Clean Architecture] 22. 컴포넌트 응집도: REP, CCP, CRP](/post/cleanarchitecture/22-component-cohesion-rep-ccp-crp/wordcloud_hu_a50c85da11e20dd2.png)
![[Clean Architecture] 15. SRP: 단일 책임 원칙](/post/cleanarchitecture/15-srp-single-responsibility-principle/wordcloud_hu_8a6fa0e5a13a91ff.png)
![[Clean Architecture] 02. 계층형 아키텍처의 역사와 한계](/post/cleanarchitecture/02-layered-architecture-limitations-history/wordcloud_hu_e5a46ae867a907e3.png)