Featured image of post 10. ISP: 인터페이스 분리 원칙

10. ISP: 인터페이스 분리 원칙

3부 - 설계 원칙

classDiagram
    direction BT
    class User1 {
        
    }
    
    class User2 {
        
    }
    
    class User3 {
        
    }
    
    class OPS {
        op1()
        op2()
        op3()
    }

    OPS <-- User1
    OPS <-- User2
    OPS <-- User3
  • 다수의 사용자가 OPS 클래스의 오퍼레이션을 사용함
    • UserNopN
  • OPS는 정적 타입 언어로 작성된 클래스

위와 같은 경우 User1op2, op3를 전혀 사용하지 않음에도 이 두 메서드에 의존하게되고, 사용하지 않는 소스 코드가 변경되면 다시 컴파일한 후 새로 배포해야한다.

인터페이스 분리 원칙은 오퍼레이션을 인터페이스 단위로 분리하여 이러한 의존성을 제거한다.

classDiagram
    class User1 {
        
    }
    
    class User2 {
        
    }
    
    class User3 {
        
    }
    
    class U1Ops {
        << interface >>
        op1()
    }

    class U2Ops {
        << interface >>
        op2()
    }

    class U3Ops {
        << interface >>
        op3()
    }

    class OPS {
        op1()
        op2()
        op3()
    }

    OPS --|> U1Ops
    OPS --|> U2Ops
    OPS --|> U3Ops

    U1Ops <-- User1
    U2Ops <-- User2
    U3Ops <-- User3

User1의 소스 코드는 U1Opsop1에는 의존하지만 OPS에는 의존하지 않게 되어 OPS 에서 발생한 변경이 User1과 전혀 관계없는 변경이라면, User1을 다시 컴파일하고 새로 배포하는 상황은 초래되지 않는다.

ISP와 언어

정적 타입 언어는 사용자가 import, use, include와 같은 타입 선언문을 사용하도록 강제한다.

이러한 ‘포함된(included)’ 선언문으로 인해 소스 코드 의존성이 발생하고, 이로 인해 재컴파일 도는 재배포가 강제되는 상황이 무조건 초래된다.

  • 동적 타입 언어네서는 소스 코드에 이러한 선언문이 존재하지 않고 런타임에 추론이 발생한다.
    • 소스 코드 의존성이 아예 없으며, 재컴파일과 재배포가 필요없다.
    • 이러한 이유로 동적 타입 언어를 사용하면 정적 타입 언어를 사용할 때보다 유연하며 결합도가 낮은 시스템을 만들 수 있다.

ISP를 아키텍처가 아니라, 언어와 관련된 문제라고 결론내릴 여지가 있다.

ISP와 아키텍처

ISP를 사용하는 근본적인 동기를 살펴보면, 잠재되어 있는 더 깊은 우려사항을 볼 수 있다.

  • 일반적으로 필요 이상으로 많을 걸 포함하는 모듈에 의존하는 것은 해로운 일이다.
    • 소스 코드 의존성의 경우 불필요한 재컴파일과 재배포를 강제하기 때문이다.

위와 같은 문제는 물론 아키텍처 수준에서도 마찬가지의 상황이 발생한다.

flowchart LR
    a[System S]
    b[Framework F] 
    c[Database D]
    
    a --> b --> c
  • S 시스템을 구축하며 F라는 프레임워크를 도입하려고한다.
  • F 프레임워크는 D라는 특정 데이터베이스를 반드시 사용하도록 만들었다.
  • SF에 의존하고, FD에 의존하게 된다.

위와 같은 상황에서 F에서는 불필요한 기능, 즉 S와는 전혀 관계없는 기능이 D에 포함되어있다고 가정하면,

  • 불필요한 기능으로 인해 D 내부가 변경되면, F를 재배포 해야할 수도 있다.
  • D 내부의 기능 중 FS에서 불필요한 기능에 문제가 발생해도 FS에 영향을 준다.

결론

불필요한 짐을 실은 무언가에 의존하면 예상치도 못한 문제에 빠진다.