Study/객체지향

ISP: 인터페이스 분리 원칙

voider 2021. 7. 31. 23:28

인터페이스 분리 원칙은 사진1에서 보는 다이어그램에서 그 이름이 유래했다.

사진1에 기술된 상황에서, 다수의 사용자가 OPS 클래스의 오퍼레이션을 사용한다. User1은 오직 op1을, User2는 op2만을, User3은 op3만을 사용한다. 그리고 OPS가 정적 타입언어로 작성된 클래스라고 가정하자. 이 경우 User1에서는 op2와 op3를 전혀 사용하지 않음에도 User1의 소스코드는 이 두 메서드에 의존하게 된다. 이런 의존성으로 인해 OPS 클래스에서 op2의 소스 코드가 변경되면 User1도 다시 (사실 User1과 관련된 전혀 변경되지 않았음에도 불구하고) 컴파일한 후에 다시 배포해야 한다.

이런 문제는 그림2에서 보는 것처럼 오퍼레이션을 인터페이스 단위로 분리하여 해결할 수 있다. 이번에도 마찬가지로 정적 타입 언어로 이 다이어그램을 구현했다고 가정하면, User1의 소스 코드는 U10ps와 op1에는 의존하지만, OPS에는 의존하지 않는다. 따라서 OPS에서 발생한 변경이 User1과 전혀 관계없어진다.

ISP와 언어

앞 예제에서 본 사례는 언어 타입에 의존한다. 정적 타입 언어는 사용자가 import, use, include 같은 선언문을 쓰도록 강제한다. 이처럼 소스 코드에 포함된 선언문으로 인해 소스 코드 의존성이 발생하고, 이로 인해 재컴파일 또는 재배포가 강제된다.

Ruby나 Python 같은 동적 타입 언어에서는 소스 코드에 이런 선언문이 존재하지 않는다. 대신 런타임에 추론이 발생한다. 따라서 소스 코드 의존성이 아예 없으며 재컴파일-재배포도 필요없다. 따라서 동적 타입 언어를 사용하면 정적 타입 언어를 사용할 때보다 유연하며 결합도가 낮은 시스템을 만들 수 있다. 이 사실로 인해 ISP를 아키텍처가 아니라, 언어와 관련된 문제라고 결론내릴 여지가 있다.

ISP와 아키텍처

ISP를 사용하는 근본적인 동기를 살펴보면 잠재되어 있는 더 깊은 우려사항을 볼 수 있다. 일반적으로 필요 이상으로 많은 걸 포함하는 모듈에 의존하는 것은 해롭다. 소스 코드 의존성의 경우 이는 분명한 사실인데, 불필요한 재컴파일과 재배포를 강제하기 때문이다. 하지만 더 고수준의 아키텍처 수준에서도 마찬가지 상황이 발생한다.

예를 들어, S 시스템 구축에 참여하는 아키텍트가 있다. 아키텍트는 F 프레임워크를 시스템에 도입하려고 한다. 그리고 F 프레임워크 개발자는 특정 D 데이터베이스를 반드시 사용해야 한다. 따라서 의존도는 S --> F --> D가 된다.

 

F에서는 불필요한 기능, 따라서 S와 전혀 관계없는 기능까지 D에 포함된다. 그 기능 때문에 D가 변겨되면 F를 재배포해야 할 수도 있다. 따라서 S까지 재배포해야 할 지 모른다. 이보다 더 심각한 문제는 S, F와 관련없는 D의 기능 변경 때문에 S, F에 영향을 준다는 것이다.

결론

"사용하지 않는 것에 의존하지 말자"

'Study > 객체지향' 카테고리의 다른 글

DIP: 의존성 역전 원칙  (0) 2021.07.31
LSP: 리스코프 치환 원칙  (0) 2021.07.13
OCP: 개방 폐쇄 원칙  (0) 2021.07.10
SRP: 단일 책임 원칙  (0) 2021.07.07