hexdrinker

정책과 수준

-2 min read

소프트웨어 시스템이란 정책을 기술한 것이다. 핵심은 이게 전부다.

대다수의 주요 시스템에서 하나의 정책은 이 정책을 서술하는 여러 개의 작은 정책들로 쪼갤 수 있다.

아키텍처를 개발하는 기술에는 정책을 신중하게 분리하고, 정책의 변경 양상에 따라 재편성하는 일도 포함된다. 동일한 이유로 동일한 시점에 변경되는 정책은 동일한 수준에 위치하며, 동일한 컴포넌트에 속해야 한다. 서로 다른 이유로, 또는 다른 시점에 변경되는 정책은 다른 수준에 위치하며, 반드시 다른 컴포넌트로 분리해야 한다.

좋은 아키텍처라면 각 컴포넌트를 연결할 때 의존성 방향이 컴포넌트의 수준 기반으로 연결되도록 만들어야 한다. 즉, 저수준의 컴포넌트가 고수준의 컴포넌트에 의존하도록 설계되어야 한다.

수준

수준(level)을 엄밀하게 정의하자면 '입력과 출력까지의 거리'이다. 입출력 모두와 멀어질수록 정책의 수준은 높아진다. 입출력을 다루는 정책이라면 시스템에서 최하위 수준에 위치한다.

간단한 암호화 프로그램
간단한 암호화 프로그램

이 다이어그램에서 주목할 점은 데이터의 흐름과 소스 코드의 의존성이 같은 방향이 아니란 사실이다. 소스 코드 의존성은 그 수준에 따라 결합되어야하며, 데이터 흐름을 기준으로 결합되어선 안 된다.

function encrypt() {
  while(true) {
    writeChar(translate(readChar()));
  }
}

이는 잘못된 아키텍처다. 고수준의 encrypt 함수가 저수준의 readCharwriteChar 함수에 의존하기 때문이다.

더 나은 아키텍처
더 나은 아키텍처

이는 위 아키텍처를 개선한 것이다. 경계를 횡단하는 의존성은 모두 고수준의 경계 안쪽을 향한다.

정책을 컴포넌트로 묶는 기준은 정책이 변경되는 방식에 달려있다. 단일 책임 원칙(SRP)과 공통 폐쇄 원칙(CCP)에 따라서 동일한 시점에 변경되는 정책은 함께 묶인다. 입출력과 멀리 떨어진 고수준 정책은 저수준 정책에 비해 변경될 가능성이 낮으며 그것도 중요한 이유로 변경될 것이다.

만약 암호화 알고리즘을 변경해야 한다면, 입출력 장치 변경의 이유와는 다른 실질적이고 근본적인 이유로 변경될 가능성이 높다. 이처럼 소스 코드 의존성 방향을 고수준 정책을 향하도록 분리했다면 변경의 영향도를 줄일 수 있다. 그리고 이것은 저수준 컴포넌트가 고수준 컴포넌트에 플러그인 되는 관점에서 볼 수도 있을 것이다.

결론

정책에 대한 논의는 단일 책임 원칙(SRP), 개방 폐쇄 원칙(OCP), 공통 폐쇄 원칙(CCP), 의존성 역전 원칙(DIP), 안정된 의존성 원칙(SDP), 안정된 추상화 원칙(SAP)을 모두 포함한다.