Interface Segregation Principle
인터페이스 분리 원칙 (ISP, Interface Segregation Principle) 은 SOLID 설계 원칙 중 하나로, 클라이언트가 자신이 사용하지 않는 메서드에 의존하지 않도록 인터페이스를 작고 특정 목적에 맞게 분리하는 것을 강조한다. 하나의 커다란 인터페이스를 여러 개의 구체적이고 목적에 맞는 작은 인터페이스로 분리함으로써 클라이언트가 불필요한 의존성을 갖지 않도록 하는 객체지향 설계 원칙이다.
ISP 를 적용하면 불필요한 의존성과 구현을 방지하고, 시스템의 모듈화, 유지보수성, 테스트 용이성, 유연성이 크게 향상된다. ISP 는 대규모 시스템, 마이크로서비스, 프론트엔드 컴포넌트 뿐만 아니라 실무의 API 설계, 모듈화, 리팩토링 과정에서 널리 적용된다.
핵심 개념
클라이언트 (사용자, 구현 클래스) 가 사용하지 않는 메서드에 의존하거나 구현을 강요받지 않도록, 인터페이스를 작고 구체적으로 분리하는 설계 원칙이다.
기본 개념
- 인터페이스 분리: 큰 인터페이스를 작고 구체적인 역할별 인터페이스로 나누는 것
- 클라이언트 특화: 각 클라이언트가 실제로 사용하는 메서드만 포함하는 인터페이스 제공
- 의존성 최소화: 불필요한 메서드에 대한 의존성을 제거하여 결합도 감소
심화 개념
- 역할 인터페이스 (Role Interface): 분리된 작은 단위의 인터페이스
- 컴포지션을 통한 통합: 여러 작은 인터페이스를 조합하여 복합 기능 제공
- 어댑터 패턴 연계: 레거시 인터페이스 적용 시 ISP 위반 해결 방안
배경 및 목적
배경:
- Robert C. Martin 이 1996 년 C++ Report 에서 최초 제시
- Xerox 프린터 소프트웨어 개발 과정에서 발견된 문제 해결을 위해 고안
- 대규모 소프트웨어 시스템에서 인터페이스 비대화 문제 해결 필요성 대두
목적 및 필요성:
- 클라이언트의 불필요한 의존성 제거
- 시스템의 결합도 감소 및 응집도 향상
- 인터페이스 변경 시 영향 범위 최소화
- 코드의 재사용성 및 테스트 용이성 향상
주요 기능 및 역할
핵심 기능:
- 인터페이스의 역할별 분리
- 클라이언트별 최적화된 인터페이스 제공
- 필요 없는 메서드 구현 강요 방지
- 시스템 간 느슨한 결합 구현
- 변경 영향도 격리
주요 역할:
- 시스템 복잡도 관리
- 코드 유지보수성 향상
- 개발 생산성 증대
- 시스템 확장성 보장
특징
- 결합도 감소: 불필요한 의존성 제거.
- 모듈화: 각 역할별로 인터페이스 분리.
- 유지보수성·확장성·테스트 용이성: 코드 변경/확장/테스트가 쉬움.
작동 원리
graph TD A[큰 인터페이스] --> B[인터페이스 분석] B --> C[역할별 분류] C --> D[작은 인터페이스들] D --> E[클라이언트별 구현] F[클라이언트 A] --> G[인터페이스 A] H[클라이언트 B] --> I[인터페이스 B] J[클라이언트 C] --> K[인터페이스 C] G --> L[구현체] I --> L K --> L
핵심 원칙:
- 분리의 원칙: " 하나의 일반적인 인터페이스보다 여러 개의 구체적인 인터페이스가 낫다 "
- 최소 의존성 원칙: 클라이언트는 사용하지 않는 메서드에 의존하지 않아야 함
- 역할 기반 설계: 각 인터페이스는 명확한 역할과 책임을 가져야 함
작동 과정:
4. 기존 큰 인터페이스의 메서드들을 역할별로 분석
5. 클라이언트의 사용 패턴에 따라 인터페이스 분류
6. 각 역할에 맞는 작은 인터페이스 생성
7. 클라이언트는 필요한 인터페이스만 의존
8. 구현체에서 여러 인터페이스를 조합하여 구현
다이어그램
- Fat Interface: 여러 역할을 한 인터페이스에 몰아넣으면, 불필요한 메서드 구현, 예외 처리, 결합도 증가, 코드 복잡성 유발.
- 역할별 인터페이스 분리: 각 역할 (프린트, 스캔, 팩스 등) 별로 인터페이스를 분리하여, 필요한 기능만 구현하도록 설계.
classDiagram class LargeInterface { +method1() +method2() +method3() +method4() } class RoleInterfaceA { +method1() +method2() } class RoleInterfaceB { +method3() +method4() } class Implementation { +method1() +method2() +method3() +method4() } class ClientA { } class ClientB { } ClientA --> RoleInterfaceA ClientB --> RoleInterfaceB Implementation ..|> RoleInterfaceA Implementation ..|> RoleInterfaceB
구성요소 정리 (Interface Segregation Principle 관점)
구분 | 구성요소 | 기능 | 역할 |
---|---|---|---|
필수 | 역할 인터페이스 (Role Interface) | 특정 역할에 특화된 작은 인터페이스 | 불필요한 의존 제거, 인터페이스 분리 원칙 (ISP) 실현 |
클라이언트 (Client) | 인터페이스 소비자 | 필요한 기능만 의존, 느슨한 결합 유지 | |
구현체 (Implementation) | 인터페이스 구현 | 역할별 기능 구현, 다형성 실현 | |
선택 | 통합 인터페이스 (Composite Interface) | 여러 역할 인터페이스를 상속 | 복합 기능 인터페이스 구성 |
어댑터 (Adapter) | 기존/외부 인터페이스를 변환 | 레거시 시스템 통합, 재사용성 향상 | |
조합 클래스 (Composition Class) | 다중 역할 인터페이스 구현 | 유연한 기능 조합 및 구조 설계 실현 |
구현 기법
기법 | 정의 | 구성 | 목적 | 예시 |
---|---|---|---|---|
인터페이스 분리 | 여러 개의 작은 인터페이스로 분리 | 인터페이스, 클라이언트, 구현체 | 책임 최소화 | IReadable, IWritable |
역할 기반 인터페이스 | 역할별로 나눈 추상화 | 클래스 다중 상속 | 역할 유연성 확보 | IAuthenticatable, IAuditable |
어댑터 패턴 | 여러 인터페이스를 하나로 연결 | Wrapper 클래스 | ISP 위배된 구조 개선 | DBAdapter 구현 |
인터페이스 분리 기법
정의: 큰 인터페이스를 역할별로 나누는 기법
구성: 기존 인터페이스 분석 → 역할 분류 → 작은 인터페이스 생성
목적: 클라이언트별 최적화된 인터페이스 제공
|
|
역할 기반 인터페이스 설계
정의: 각 인터페이스가 명확한 역할을 갖도록 설계
구성: 역할 정의 → 책임 할당 → 인터페이스 명세
목적: 높은 응집도와 낮은 결합도 달성
컴포지션 패턴 적용
정의: 여러 작은 인터페이스를 조합하여 복합 기능 제공
구성: 기본 인터페이스들 → 조합 로직 → 통합 인터페이스
목적: 유연한 기능 확장 및 재사용성 향상
장점과 단점
구분 | 항목 | 설명 |
---|---|---|
✅ 장점 | 낮은 결합도 | 클라이언트가 필요한 인터페이스만 의존하여 시스템 결합도 감소 |
높은 응집도 | 각 인터페이스가 명확한 역할을 가져 기능적 응집도 향상 | |
유지보수성 | 인터페이스 변경 시 영향 범위가 제한되어 유지보수 용이 | |
재사용성 | 작은 인터페이스들을 다양한 조합으로 재사용 가능 | |
테스트 용이성 | 작은 단위로 분리되어 단위 테스트 작성이 쉬움 | |
⚠ 단점 | 복잡성 증가 | 인터페이스 수 증가로 인한 설계 복잡도 상승 |
설계 비용 | 초기 설계 단계에서 더 많은 시간과 노력 필요 | |
파일 증가 | 분리된 인터페이스로 인한 소스 파일 수 증가 | |
성능 오버헤드 | 다중 인터페이스 구현으로 인한 경미한 성능 영향 |
단점 해결 방법
- 자동화 도구 활용: IDE 의 리팩토링 기능을 활용한 인터페이스 분리 자동화
- 점진적 적용: 기존 시스템에 단계적으로 ISP 적용
- 문서화 강화: 인터페이스 간 관계와 역할을 명확히 문서화
- 패키지 구조화: 관련 인터페이스들을 논리적으로 그룹화
도전 과제
도전 과제 | 설명 | 해결책 |
---|---|---|
적절한 분리 수준 결정 | 인터페이스를 얼마나 세분화할지 판단이 어려움 | 도메인 지식과 클라이언트 사용 패턴 기반 의미 있는 분리 기준 수립 |
Fat Interface 유혹 | 빠른 개발을 위해 많은 기능을 하나의 인터페이스에 몰아넣는 경우 | 설계 표준화, 정기 코드 리뷰로 감시 |
인터페이스 남발 | 역할 기준이 모호할 경우 인터페이스 수가 지나치게 많아짐 | 역할 명확화, 네이밍 규칙과 문서화를 통한 관리 |
설계 복잡성 증가 | 과도한 분리로 전체 구조가 복잡해지고 유지보수가 어려워짐 | 인터페이스 조합 설계 (Composite Interface), 설계 표준 적용 |
코드 중복 발생 | 여러 인터페이스에 유사한 메서드 반복 정의 | 공통 기능은 default method(Java), mixin(Python) 활용 |
레거시 시스템 적용 어려움 | 기존 시스템이 큰 인터페이스를 사용하고 있어 변경이 어려움 | 어댑터 패턴 적용, 점진적 마이그레이션 전략 병행 적용 |
인터페이스 간 일관성 부족 | 분리된 인터페이스 간 명명 규칙이나 설계 철학이 달라 일관성이 떨어짐 | 코딩 가이드라인 수립 및 리뷰 프로세스 정립 |
ㄴ설계 난이도 상승 | 경험 부족한 개발자에게는 의미 기반 분리가 어려워 설계 자체가 난이도 상승 | 도메인 중심 설계 (DDD) 병행 도입으로 역할 중심 분리 유도 |
분류 기준에 따른 종류 및 유형
분류 기준 | 유형 | 설명 | 특징 |
---|---|---|---|
역할별 | 기능 인터페이스 | 특정 기능만 제공하는 인터페이스 | 단일 책임, 높은 응집도 |
이벤트 인터페이스 | 이벤트 처리 전용 인터페이스 | 비동기 처리, 옵저버 패턴 | |
데이터 인터페이스 | 데이터 접근 전용 인터페이스 | CRUD 분리, 읽기/쓰기 분리 | |
범위별 | 세분화 인터페이스 | 매우 작은 단위로 분리된 인터페이스 | 최대 유연성, 복잡도 증가 |
그룹 인터페이스 | 관련 기능을 묶은 중간 크기 인터페이스 | 균형잡힌 설계 | |
클라이언트별 | 사용자 인터페이스 | 최종 사용자 중심의 인터페이스 | 사용성 중심 |
시스템 인터페이스 | 시스템 간 연동을 위한 인터페이스 | 안정성 중심 |
실무 적용 예시
분야/시스템 | 적용 사례 | 분리 방법 및 설명 | 효과 |
---|---|---|---|
웹 개발 | REST API 리소스 설계 | 리소스별 엔드포인트 분리 및 역할별 요청 분리 | 클라이언트 요구에 맞춘 최적화 |
데이터베이스 | DAO (Data Access Object) 패턴 | CRUD 작업을 Read, Write, Delete 등으로 분리 | 데이터 접근 계층 명확화 및 테스트 용이 |
UI 개발 | 컴포넌트 설계 | 역할별 컴포넌트 (예: Button, Input 등) 에 필요한 props 만 정의 | 재사용성, 유지보수성 향상 |
마이크로서비스 | 도메인 중심 서비스 인터페이스 분리 | 인증, 인가, 통계 등 기능별로 API 계약 분리 | 서비스 독립성 확보 및 배포 유연화 |
게임 개발 | 플레이어 액션 분리 | 이동, 공격, 스킬 등 동작별 인터페이스 구분 | 모듈별 개발 독립성 확보 |
프린터 시스템 | 다기능 장치 인터페이스 분리 | Printable , Scannable , Faxable 등 필요 기능만 구현 | 의존성 최소화, 불필요 구현 방지 |
백엔드 서비스 | 리소스 조작 역할별 인터페이스 분리 | Reader , Writer , Deleter 등 역할별 인터페이스 설계 | 명확한 역할 분리, SRP(단일 책임 원칙) 적용 |
CMS 시스템 | 편집자 vs 뷰어 기능 분리 | Editor , Viewer 인터페이스 구분 | 역할 단위 권한 제어 및 기능 분리 |
POS 시스템 | 결제 처리 vs 할인 정책 구분 | 결제 기능과 할인 처리 로직을 별도 인터페이스로 분리 | 테스트 및 유지보수 유리 |
IoT 디바이스 제어 | 센서와 제어기 구분 | 입력 장치 (Sensor) 와 출력 장치 (Actuator) 용 인터페이스 분리 | 하드웨어 독립성 및 확장성 확보 |
ISP 위반 예제
문제점:
- Light 클래스는 set_temperature() 를 구현해야 하지만 실제로는 해당 기능이 없음
- 이는 ISP 위반. 필요하지 않은 기능에 대한 강제 의존 발생
ISP 를 적용한 개선
항목 | 전 | 후 |
---|---|---|
인터페이스 수 | 하나 | 두 개 이상 (역할 기반 분리) |
구현 강제성 | 모든 기능 구현 필요 | 필요한 기능만 구현 |
유지보수 | NotImplementedError 발생 가능 | 역할별로 안전하게 구현 |
SRP 와 결합 | 낮음 | 높음 (기능별 책임 분리) |
테스트 용이성 | 낮음 | 높음 (Mock 주입 쉬움) |
역할별 인터페이스 분리
인터페이스 정의
구현 클래스
사용 예 (main.py)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# main.py from light import Light from boiler import Boiler def activate_device(device): device.turn_on() def heat_device(heater): heater.set_temperature(60) light = Light() boiler = Boiler() activate_device(light) # OK activate_device(boiler) # OK heat_device(boiler) # OK # heat_device(light) # 타입 검사 시 오류 가능 (정적 타입 도구에서)
활용 사례
사례 1: 스마트 홈 시스템
시나리오: 다양한 기기 (조명, 보일러, 도어락 등) 를 제어해야 하며, 각 기기는 기능이 상이함
문제: ISmartDevice
에 모든 기능을 넣으면, 불필요한 기능도 구현해야 함
시스템 구성도:
classDiagram class IControllable { +turnOn() +turnOff() } class IHeatable { +setTemperature(temp) } class Light { } class Boiler { } Light ..|> IControllable Boiler ..|> IControllable Boiler ..|> IHeatable
효과:
Light
는 온/오프만 구현Boiler
는 온/오프와 온도 설정 기능 모두 구현
Workflow:
- 사용자가 스마트폰 앱에서
turnOn
클릭 - 각 기기 인터페이스에 맞게 명령 분기
- 클라이언트는 필요한 기능만 호출
사례 2: 복합기와 단일 프린터
시나리오: 복합기 (프린터, 스캐너, 팩스 기능) 와 단일 프린터가 공존하는 시스템
구성: Printable, Scannable, Faxable 인터페이스 분리, 각 장치가 필요한 인터페이스만 구현
시스템 다이어그램:
classDiagram class Printable { +print() } class Scannable { +scan() } class Faxable { +fax() } class SimplePrinter { +print() } class MultiFunctionPrinter { +print() +scan() +fax() } SimplePrinter --|> Printable MultiFunctionPrinter --|> Printable MultiFunctionPrinter --|> Scannable MultiFunctionPrinter --|> Faxable
Workflow:
- SimplePrinter 는 Printable 만 구현
- MultiFunctionPrinter 는 Printable, Scannable, Faxable 모두 구현
- 각 장치는 필요한 기능만 구현하며, 불필요한 메서드 구현 없음
사례 3: 전자상거래 플랫폼
시나리오: 대규모 전자상거래 플랫폼에서 주문 관리 시스템 구축
시스템 구성
- 주문 생성 서비스
- 결제 처리 서비스
- 재고 관리 서비스
- 배송 관리 서비스
- 고객 알림 서비스
graph LR A[주문 관리 시스템] --> B[주문 생성 인터페이스] A --> C[결제 처리 인터페이스] A --> D[재고 관리 인터페이스] A --> E[배송 관리 인터페이스] A --> F[알림 인터페이스] B --> G[주문 생성 서비스] C --> H[결제 처리 서비스] D --> I[재고 관리 서비스] E --> J[배송 관리 서비스] F --> K[고객 알림 서비스]
Workflow
- 고객이 주문 요청
- 주문 생성 인터페이스를 통해 주문 정보 생성
- 결제 처리 인터페이스로 결제 진행
- 재고 관리 인터페이스로 재고 차감
- 배송 관리 인터페이스로 배송 준비
- 알림 인터페이스로 고객에게 상태 알림
ISP 역할:
- 각 서비스가 자신의 책임에만 집중
- 다른 서비스의 변경이 영향을 주지 않음
- 새로운 기능 추가 시 해당 인터페이스만 확장
실무 적용 고려사항 및 주의점
구분 | 항목 | 설명 | 권장사항 |
---|---|---|---|
설계 | 분리 수준 결정 | 과도한 세분화는 오히려 설계 복잡도를 높일 수 있음 | 도메인 지식과 실제 클라이언트 사용 패턴을 기반으로 적절한 수준 결정 |
명명 규칙 및 명확성 | 역할에 맞지 않거나 중복된 이름 사용은 혼란 초래 | 역할 기반 명명 규칙 수립, 의미 단위 기준으로 분리 | |
인터페이스 설계 기준 | 기능 중심보다 책임 중심으로 나눌 필요 | SRP (단일 책임 원칙) 과 도메인 기반 역할 분리 적용 | |
구현 | 레거시 처리 | 기존 대형 인터페이스가 존재하는 시스템에 적용 어려움 | 어댑터 패턴 (Wrapper) 또는 점진적 마이그레이션 전략 사용 |
성능 고려 | 다중 인터페이스 호출 시 불필요한 오버헤드 발생 가능 | 성능 요구사항과 설계 유연성 간 균형 유지 | |
테스트 | 역할별 테스트 구성 | 하위 인터페이스별로 Mock/Stub 필요 | 각 인터페이스 단위로 테스트 작성, 단위 테스트 및 시나리오 테스트 병행 |
유지보수 | 인터페이스 수 증가에 따른 복잡성 | 너무 많은 인터페이스는 유지보수 비용 증가 | 명확한 문서화, 코드 리뷰 절차 강화, 아키텍처 다이어그램 작성 |
변경 시 호환성 관리 | 인터페이스 변경이 클라이언트 코드에 영향을 줄 수 있음 | 시맨틱 버저닝 (Semantic Versioning) 적용 및 변경 영향도 분석 | |
문서화 체계 | 역할별 인터페이스가 많아질수록 관계 추적이 어려움 | 도메인 기반 명세화, 공통 계약 문서, 시각화된 구조 다이어그램 병행 운영 | |
전략 | 리팩토링 시점 | 너무 이른 분리는 오히려 과설계를 유발할 수 있음 | 기능 변화나 역할 확장 시점에 맞춰 인터페이스 분리, 점진적 리팩토링 적용 |
클라이언트별 인터페이스 설계 | 다양한 클라이언트가 동일한 인터페이스를 사용하는 경우 불필요한 의존성 발생 가능 | 클라이언트 사용 패턴 분석 후 전용 인터페이스 설계 적용 (Interface per Consumer) |
최적화하기 위한 고려사항 및 주의할 점
구분 | 항목 | 설명 | 권장사항 |
---|---|---|---|
설계 최적화 | 공통 기능 추상화 | 여러 인터페이스 간 중복 메서드 발생 가능성 있음 | 공통 기능은 상위 기본 인터페이스로 분리하여 재사용 유도 |
역할 분리 기준 명확화 | 기준이 불명확하면 인터페이스 수 증가로 복잡도 증가 | 도메인 역할 기반으로 분리하고 명확한 명명 규칙 및 문서화 적용 | |
인터페이스 조합 구조 | 다중 인터페이스 조합 시 역할 중복, 결합도 증가 우려 | IReader + IWriter = IStream 식의 목적 기반 조합 설계 | |
Interface + Mixin 사용 | 공통 기능을 코드 중복 없이 재사용 | 언어가 지원하면 Mixin/Default Method 패턴으로 구현 | |
성능 및 자원 | 인터페이스 수 증가 | 과도한 분리로 인해 런타임 비용이나 관리 비용 증가 가능 | 실제 사용량 기반 성능 프로파일링 후 분리 수준 조정 |
메모리 사용량 | 다중 인터페이스 구현 시 메모리/오브젝트 증가 가능성 | 플라이웨이트 (Flyweight) 패턴, 메모리 풀, 의존성 최소화 적용 | |
확장성 | 인터페이스 진화 | 새로운 기능 추가 시 인터페이스 변경 필요 | 인터페이스 버전 관리 (V1, V2…), Open-Closed Principle 설계 적용 |
하위 호환성 | 클라이언트 변경 없이 새 기능 반영 어려움 | 시맨틱 버저닝 적용 및 버전별 분리 설계 | |
테스트 전략 | 단위 테스트 | 인터페이스별로 독립된 기능 검증 필요 | 역할별 Mock/Stub 기반 테스트 구성 |
통합 테스트 | 여러 인터페이스 간 연동 시 치환 가능성 검증 필요 | 계약 기반 테스트 (Contract Test), 시나리오 기반 통합 테스트 병행 | |
API/외부 시스템 | 외부 인터페이스 설계 반영 | API/외부 연동 시 Fat Interface 생성 위험 | 외부 시스템도 역할 단위로 분리된 계약 기반 인터페이스 설계 |
유지보수 | 변경 최소화 | 인터페이스 변경 시 클라이언트 영향 최소화 필요 | 역할 단위로 독립적 변경이 가능하도록 구성, 변경 이력/문서화 관리 강화 |
ISP 관련 문제점 및 해결 방안
문제 | 원인 | 영향 | 탐지/진단 | 예방/해결 방법 |
---|---|---|---|---|
Fat Interface | 책임 분리 실패, 메서드 과다 포함 | 클라이언트가 불필요한 메서드 구현, 결합도 증가 | 인터페이스 당 메서드 수 분석 | 단일 책임 원칙 (SRP), 인터페이스 분리 원칙 (ISP) 준수 |
인터페이스 일관성 부족 | 팀별 설계 기준 불일치 | 유지보수 난이도 상승, 코드 이해도 저하 | 코드 리뷰, 정적 분석 | 설계 가이드 문서화, 네이밍 및 역할 기준 명확화 |
순환 의존성 | 의존 방향 위반, 레이어 간 부적절한 참조 | 컴파일/런타임 오류, 빌드 실패 | 의존성 시각화 도구, import 트리 분석 | DIP(의존 역전 원칙), 중재자 (Mediator) 패턴 도입 |
타입/인터페이스 폭발 | 도메인 경계 과도한 분리, 남용된 상속 | 유지보수 어려움, 도메인 객체 혼란 | 역할 유사 인터페이스 수 파악 | 유사 인터페이스 통합, 공통 메서드 추출 |
구현 누락 | 설계 미비, 인터페이스 누락 | 기능 미제공, 버그 발생 | 도메인 기반 유스케이스 검토 | DDD 기반 인터페이스 식별 및 자동 테스트 확보 |
Fat Interface
문제 코드 예시:
모든 동물이
fly()
,swim()
을 구현해야 하는 문제 발생
개선 코드 (ISP 적용):
|
|
해결 전략:
- 인터페이스를 능력 (역할) 단위로 분리
- ISP (인터페이스 분리 원칙) 준수
순환 의존성
문제 코드 예시 (모듈 A ⇄ B 순환):
해결 코드 (DIP + 중재자 패턴):
|
|
해결 전략:
- DIP (Dependency Inversion Principle)
- Mediator 패턴을 통한 간접 참조
인터페이스 일관성 부족
문제 예시:
메서드 네이밍 불일치로 혼란 초래
개선 예시 (일관된 네이밍):
해결 전략:
- 네이밍 컨벤션 (snake_case, PascalCase 등) 팀 표준화
- 코드 리뷰 프로세스 강화
타입/인터페이스 폭발
문제 예시:
개선 코드:
|
|
해결 전략:
- 전략 (Strategy) 패턴 또는 공통 베이스 클래스로 통합
- 역할 기반 처리 로직으로 단순화
주제와 관련하여 주목할 내용
분류 | 항목 | 설명 |
---|---|---|
설계 원칙 | ISP (인터페이스 분리 원칙) | 클라이언트가 사용하지 않는 메서드에 의존하지 않도록 인터페이스를 최소화 |
구현 전략 | 역할별 인터페이스 분리 | 역할 단위로 인터페이스를 분리해 응집도 향상 및 결합도 감소 |
Extract Interface 리팩토링 | Fat Interface 를 역할별로 분리하여 단순화 | |
Mixin / Trait | 다중 역할 기능을 분리하고 조합 가능한 방식으로 구현 | |
테스트 전략 | Mock 객체, 단위 테스트 기반 테스트 설계 | 테스트 가능한 인터페이스 분리로 테스트 용이성 향상 |
설계 패턴 | 어댑터 패턴 (Adapter Pattern) | 레거시 인터페이스를 현대 구조로 감싸 ISP 위반 방지 |
퍼사드 패턴 (Facade Pattern) | 복잡한 인터페이스 집합을 단순한 진입점으로 추상화 | |
전략 패턴 (Strategy Pattern) | 알고리즘을 캡슐화해 인터페이스 기반으로 동작 분리 | |
아키텍처 | 클린 아키텍처 (Clean Architecture) | 계층별 인터페이스 분리를 통해 독립성과 테스트 용이성 확보 |
헥사고널 아키텍처 (Hexagonal Architecture) | 포트와 어댑터를 통해 외부 인터페이스와 도메인 분리 | |
마이크로서비스 아키텍처 | 서비스 단위로 독립된 API 및 인터페이스 구성 | |
개발 방법론 | 도메인 주도 설계 (DDD) | 바운디드 컨텍스트별 명확한 인터페이스 경계 설정 |
테스트 주도 개발 (TDD) | 인터페이스를 먼저 정의하고 테스트를 기반으로 구현 | |
기술 전략 | API 우선 설계 (API First Design) | 역할 기반으로 API 인터페이스를 명확히 정의 |
컴포넌트 기반 개발 (Component-Based Development) | 재사용 가능한 컴포넌트 단위 인터페이스 설계 |
추가 학습 내용
분류 | 주제 | 설명 |
---|---|---|
설계 원칙 | ISP (인터페이스 분리 원칙) | 클라이언트가 사용하지 않는 메서드에 의존하지 않도록 설계 |
SRP (단일 책임 원칙) | 각 인터페이스가 하나의 책임만 가지도록 분리 | |
DIP (의존성 역전 원칙) | 인터페이스와 구현을 분리하여 유연한 구조 구성 | |
OCP/LSP 연계 | 확장 가능하고 대체 가능한 인터페이스 설계 유도 | |
객체지향 설계 | 역할 기반 인터페이스 설계 | 객체의 역할 단위로 인터페이스 정의 |
역할 조합형 인터페이스 | 여러 역할을 조합해 재사용 가능한 구조 구성 | |
디자인 패턴 | 어댑터, 전략, 브릿지, 커맨드 패턴 | 인터페이스 분리를 위한 구조적/행위적 패턴 적용 |
Mixin / Trait | 기능 단위 인터페이스를 유연하게 조합 | |
아키텍처 | 클린 아키텍처 | 계층 간 명확한 인터페이스 분리 구조 |
헥사고널 아키텍처 | 포트 - 어댑터 기반 외부 의존성 분리 | |
마이크로서비스 아키텍처 | 서비스별 독립적인 인터페이스 및 API 설계 | |
레이어드 아키텍처 | 표현, 비즈니스, 데이터 계층 간 인터페이스 명확화 | |
이벤트 드리븐 아키텍처 | 이벤트 기반 모듈 간 인터페이스 정의 | |
API 설계 | REST Role Segregation | API 리소스 및 역할 기반 인터페이스 분리 |
API First Design | 설계 우선 접근 방식으로 ISP 내재화 | |
테스트 전략 | Mock 객체, 단위 테스트 기반 테스트 전략 | 역할별 인터페이스 단위 테스트 가능 |
테스트 주도 개발 (TDD) | 인터페이스 중심의 테스트 가능한 구조 설계 | |
리팩토링 | Fat Interface 제거 | 불필요하게 비대한 인터페이스 분리/축소 |
인터페이스 추출/통합 리팩토링 | 역할 기반 재구성 | |
개발 도구 | 정적 분석 도구 | 인터페이스 복잡도, 결합도 분석 (예: pylint , SonarQube ) |
리팩토링 도구 | 자동화된 인터페이스 추출 및 개선 (예: PyCharm , IntelliJ ) | |
프레임워크 적용 | Spring,.NET, React 등 프레임워크별 ISP 적용 | 프레임워크 컨벤션에 맞춘 인터페이스 분리 설계 방법 |
품질 관리 | 인터페이스 품질 메트릭 | 결합도, 응집도, 인터페이스 당 메서드 수 등 정량적 측정 |
도메인 모델링 | DDD (도메인 주도 설계) | Aggregate 기준 인터페이스 설계 및 바운디드 컨텍스트 구분 |
소프트웨어 공학 | 모듈화 설계 | 시스템을 모듈 단위로 나누고 각 모듈의 인터페이스 정의 |
데이터 계층 | DAO (Data Access Object) 패턴 | 데이터 접근 인터페이스 분리 및 확장 가능 설계 |
분산 시스템 | SOA (서비스 지향 아키텍처) | 서비스별 계약 (인터페이스) 정의 및 느슨한 결합 구현 |
웹 개발 | 프론트엔드 컴포넌트 인터페이스 분리 | 역할별 UI 컴포넌트 책임 분리 (React, Vue 등) |
백엔드 API 설계 | 엔드포인트별 역할 기반 인터페이스 정의 |
용어 정리
카테고리 | 용어 | 설명 |
---|---|---|
설계 원칙 | SOLID 원칙 | 객체지향 설계의 다섯 가지 원칙: SRP, OCP, LSP, ISP, DIP |
ISP (Interface Segregation Principle) | 클라이언트가 사용하지 않는 메서드에 의존하지 않도록 인터페이스를 분리하라는 원칙 | |
SRP (Single Responsibility Principle) | 하나의 클래스는 하나의 책임만 가져야 한다는 원칙 | |
DIP (Dependency Inversion Principle) | 상위 모듈이 하위 모듈에 의존하지 않도록 인터페이스를 통해 의존성 역전 | |
결합도 (Coupling) | 모듈 간 상호 의존성의 정도 | |
응집도 (Cohesion) | 모듈 내부 구성 요소 간 관련성 정도 | |
역할 인터페이스 (Role Interface) | 특정 클라이언트 역할에 특화된 작은 인터페이스 | |
인터페이스 설계 | Fat Interface | 너무 많은 메서드를 가진 비대한 인터페이스 |
Interface Pollution | 불필요한 메서드가 추가되어 오염된 인터페이스 | |
역할별 인터페이스 | 클라이언트 역할에 따라 구체적으로 분리된 인터페이스 | |
복합 인터페이스 | 여러 역할 인터페이스를 조합하여 구성된 인터페이스 | |
구현 기법/패턴 | Mixin | 다중 기능을 조합형 클래스로 재사용하기 위한 설계 방식 |
컴포지션 (Composition) | 여러 객체를 조합하여 기능을 구성하는 설계 기법 | |
의존성 주입 (Dependency Injection) | 외부에서 객체의 의존성을 주입하여 결합도 감소 | |
어댑터 패턴 (Adapter Pattern) | 호환되지 않는 인터페이스를 변환하여 연결하는 디자인 패턴 | |
브릿지 패턴 (Bridge Pattern) | 구현과 추상화를 분리하여 독립적으로 확장 가능하게 하는 패턴 | |
전략 패턴 (Strategy Pattern) | 알고리즘을 인터페이스로 분리하여 런타임에 교체 가능한 구조 | |
커맨드 패턴 (Command Pattern) | 요청을 객체로 캡슐화하여 매개변수화하고 큐잉, 로깅, 취소 처리 등을 가능하게 함 | |
아키텍처 | 클린 아키텍처 (Clean Architecture) | 계층 간 독립성과 테스트 용이성을 위한 아키텍처 구조 |
헥사고널 아키텍처 (Hexagonal Architecture) | 포트와 어댑터를 사용하여 외부 시스템과 내부 도메인 분리 | |
포트와 어댑터 (Ports and Adapters) | 헥사고널 아키텍처에서 인터페이스를 명확히 구분하는 핵심 구성요소 | |
레이어드 아키텍처 | 프레젠테이션, 도메인, 인프라 계층 간 책임 분리 구조 | |
이벤트 드리븐 아키텍처 | 이벤트를 기반으로 서비스 간 통신 및 인터페이스 정의 | |
API 게이트웨이 (API Gateway) | 마이크로서비스 진입점으로 요청을 적절한 서비스로 라우팅 | |
바운디드 컨텍스트 (Bounded Context) | DDD 에서 모델이 적용되는 경계를 명확히 구분한 설계 단위 | |
리팩토링/도구 | Extract Interface | 공통 메서드를 별도 인터페이스로 추출하는 리팩토링 기법 |
Default Method | Java 8 이상에서 인터페이스에 메서드 기본 구현을 제공하는 기능 | |
정적 분석 도구 | 코드 품질 분석 도구 (예: SonarQube , pylint , flake8 ) | |
리팩토링 도구 | IDE 기반 자동 인터페이스 추출/통합 도구 (예: IntelliJ, PyCharm) | |
테스트 전략 | Mock 객체 | 실제 객체 대신 테스트용으로 사용하는 가짜 객체 |
단위 테스트 (Unit Test) | 기능 단위로 독립적인 테스트 수행 방식 | |
테스트 주도 개발 (TDD) | 테스트를 먼저 작성하고 구현을 진행하는 개발 방식 |
참고 및 출처
공식 문서 & 저명한 참고서
- Martin Fowler - Interface Segregation Principle
- Robert C. Martin - SOLID Principles Explained
- Clean Architecture by Uncle Bob
- Effective Java - Joshua Bloch
백과사전 및 대형 커뮤니티
- Interface segregation principle - Wikipedia
- 인터페이스 분리 원칙 - 위키백과 (한국어)
- SOLID Principles - GeeksforGeeks
- Refactoring Guru - Interface Segregation Principle
실무 블로그 및 커뮤니티 글
- SOLID: I - Interface Segregation Principle (DEV)
- Unleashing the Power of Interface Segregation (DEV)
- SOLID - 인터페이스 분리 원칙 - 더블에스 Devlog
- Interface Segregation Principle 설명 - ITCode Dev Blog
- 인터페이스 분리의 원칙 - IT 위키
- Interface Segregation Principle - blog.ramoo.net
- 파이썬 인터페이스 분리 원칙 - Velog
기술 문서 & 튜토리얼
- SOLID: The First 5 Principles of Object Oriented Design - DigitalOcean
- What is Interface Segregation Principle - Startup House
- Interface Segregation with Code Examples - Stackify
- Interface Segregation Principle in Java - Baeldung
- Interface Segregation Principle (ISP) – SOLID Principles in Java - LinkedIn
- SOLID Design Principles Explained: Interface Segregation - DZone
- The Interface Segregation Principle - TheServerSide
국내 추가 자료
- SOLID 원칙 - Interface Segregation Principle - Joonas.io
- 객체지향 개발 5대 원리: SOLID - Nextree
- 마이크로서비스 아키텍처 국내 도입 사례 - Channy’s Blog