본문으로 바로가기
728x90

계층과 경계

UI, 업무 규칙 그리고 데이터베이스 뿐만 아니라 사실 컴포넌트는 이보다 복잡하다. 예를 들어 동일한 업무 규칙을 갖는 영어와 한국어와 같은 언어 UI가 변경되기를 원할 수도 있고 때로는 로컬 스토리지나 클라우드 스토리지와 같은 데이터베이스를 원할 수 있다.

이를 감춰 클린 아키텍처를 구성하기 위해 앞서 계속해서 이야기했던 Language 나 Data Storage 와 같은 API를 정의하는 추상 컴포넌트를 만들고 추상 컴포넌트가 English, Spanish 와 같은 컴포넌트에서 구현할 수 있다.

아주 작은 프로그램도 아키텍처간 경계는 존재한다. 경계를 제대로 구현하려면 비용이 많이 들지만 경계가 무시된 이후에 나중에 추가하는 비용도 크다. 하지만 오버 엔지니어링이 언더 엔지니어링보다 훨씬 나쁜 때가 많기에 프로젝트 초반에는 알 수 없지만 항상 주의를 기울여 경계가 필요하다면 그 경계를 구현하는 비용과 무시할 때의 비용을 가늠해봐야한다.

 

메인 컴포넌트

시스템에는 하나의 메인 컴포넌트가 존재하고, 나머지 컴포넌트를 생성, 조정 그리고 관리한다. 메인 컴포넌트는 가장 낮은 수준의 정책이자 초기 진입점이고 외부 자원을 모두 수집한 후 제어권을 어플리케이션의 고수준 정책으로 넘기는 플러그인이다. 메인 컴포넌트가 의존성 주입 프레임워크등을 포함하여 가장 지저분해졌다면 정상이다.

 

‘크고 작은 모든’ 서비스들

서비스 지향 아키텍처 그리고 마이크로 서비스 아키텍처 모두 최근에 인기를 끌고 있지만 사실 아키텍처적으로 중요한 서비스가 있는 반면 어떤 서비스는 단순히 플랫폼의 경계를 가로지르는 함수 호출 정도의 중요하지 않은 서비스도 있다. 서비스를 분리한다면 다음과 같은 장점을 갖게 된다고 기대할 수 있는데,

  • 각 서비스는 서로 다른 프로세서에서 실행되어 다른 서비스에 변수에 접근할 수 없고 인터페이스는 잘 정의되어있게 된다. 하지만 네트워크 상 공유자원 때문에 결합될 가능성은 여전히 존재하기에 서비스 인터페이스가 함수 인터페이스보다 더 엄밀하게 잘 정의된다는것은 환상이다.
  • 개발과 배포 독립성을 갖게 되고 확장 가능성을 갖게되어 대규모 엔터프라이즈 시스템에 용이하다. 하지만, 모노리틱 시스템, 컴포넌트 시스템도 역사적으로 잘 구축되어 왔고 데이터가 결합되어 있다면 독립성을 갖지 못할 수 도 있다.

서비스는 시스템의 확장성과 개발 가능성 측면에서 용이하지만, 실제로 횡단 관심사 문제는 서비스 지향이든 아니든 경계와 경계를 넘나드는 의존성 규칙을 준수하는 컴포넌트 아키텍처로 설계하는게 더 중요하다.

 

테스트 경계

테스트 또한 시스템의 일부이며 태생적으로 의존성 규칙을 따른다. 테스트는 세부적이며 구체적인것으로 가장 바깥쪽 원에 속하며 독립적이다. 테스트 또한 설계할 때 고려 되어야 하는데, ****************************************‘변동성이 있는 것에 의존하지 말라’ 가 첫 번째이다. GUI와 같이 변동성이 큰 요소가 테스트와 결합되어 있다면 GUI가 변동될 때마다 1000개의 테스트 코드가 실패했다고 가정하면 지옥이다. 따라서 업무 규칙이 테스트 되도록 해야한다.

이를 위해 값 비싼 데이터베이스와 같은 자원은 건너뛰고, 모든 업무 규칙을 검증할 수 있는 어플리케이션 구조와 테스트 구조를 분리시킬 수 있는 API를 만들면 된다.

 

클린 임베디드 아키텍처

소프트웨어는 닳지 않는다. 하드웨어는 발전할 수 밖에 없고, 이러한 현실을 염두해두고 임베디드 코드를 구조화 할 수 있어야한다. 펌웨어를 최소한으로 만들고 소프트웨어를 더 많이 만드는걸 목표로 해야한다.

켄트 백은 소프트웨어를 구축하는 세가지 활동을 다음과 같이 기술했다.

  • “먼저 동작하게 만들어라.”
  • “그리고 올바르게 만들어라.”
  • “그리고 빠르게 만들어라.”

임베디드 개발자들은 하드웨어의 결함등의 이유로 소프트웨어 개발과 테스트가 훨씬 느리게 진척되는 ‘타깃-하드웨어 병목현상’을 겪는다. 하드웨어는 새로운 부품과 기술의 발전으로 불가피하게 변경됨을 고려하여 임베디드 엔지니어라면 필요 이상의 작업을 하지 않도록 하드웨어 관련 정보가 코드 전체를 오염시키지 못하도록 계층을 분리해야한다.

임베디드라해서 크게 다르지 않다, 프로세서와 OS는 세부사항이다. 펌웨어와 OS 사이는 HAL 추상화 계층을 통해, OS와 소프트웨어 사이에는 OSAL 이라는 추상화 계층을 만들어 인터페이스를 통해 대체 가능성이 높이는 방법으로 프로그래밍 하자는 것이다.