juhee

27 '크고 작은 모든' 서비스들

  • 최근 유행 : 서비스 지향 아키텍처, 마이크로 서비스 아키텍처

    • 서비스를 사용하면 상호 결합이 분리되는듯, 배포 독립성을 지원하는것 처럼 보인다. -> 하지만 일부만 맞는말

서비스 아키텍처?

  • 시스템의 아키텍처는 의존성 규칙을 준수하며 고수준 정책을 저수준의 세부사항으로부터 분리하는 경계에 의해 정의

  • 결국 서비스는 프로세스나 플랫폼 경계를 가로지르는 함수 호출에 지나지 않는다.

서비스의 이점?

  • 결합 분리의 오류

    • 하나의 서비스 사이의 결합이 확실히 분리된다.

    • 서비스는 다른 서비스의 변수에 직접접근할 수 없고, 모든 서비스의 인터페이스는 반드시 잘 정의되어 있어야 한다.

  • 개발 및 배포 독립성의 오류

    • 서비스를 사용함에 따라서 예측되는 또 다른 이점은 전담팀이 서비스를 소유하고 운영한다는 것이다.

    • 대규모 엔터프라이즈 시스템은 서비스 기반 시스템외에도 MSA, CSP(컴포넌트) 구축할 수 있다는 사실은 증명되어 왔다.

    • 결합 분리의 오류에 따르면 서비스라 해서 항상 독립적으로 개발, 배포, 운영할 수 있는것은 아니다.

야옹이 문제

  • 서비스들의 존재는 이전과 달라진게 없지만, 각 서비스의 내부는 자신만의 컴포넌트 설계로 되어 있어서 파생 클래스를 만드는 방식으로 신규 기능을 추가할 수 있다. 파생 클래스들은 각자의 컴포넌트 내부에 놓인다.

횡단 관심사

  • 아키텍처 경계가 서비스 사이에 있지 않다

  • 오히려 모든 서비스를 관통하며 컴포넌트 단위로 분할한다.

  • 서비스 내부는 의존성 규칙도 준수하는 컴포넌트 아키텍처로 설계해야 한다.

결론

  • 서비스는 시스템 확장성과 개발 가능성 측면에서는 유용하지만, 그 자체로는 아키텍처적으로 그리 중요한 요소는 아니다

  • 서비스는 단 하나의 아키텍처 경계로 둘러싸인 단일 컴포넌트로 만들 수 있다.

  • 혹은 여러 아키텍처 경계로 분리된 다수의 컴포넌트로 구성할 수도 있다.

  • 드물게는 클라이언트와 서비스가 강하게 결합되어 있어 아키텍처적으로 아무런 의미가 없을 때도 있다.

28 테스트 경계

  • 테스트는 시스템의 일부이고 아키텍처에도 관여한다.

시스템 컴포넌트인 테스트

  • 어떤 종류의 테스트이든 아키텍처 관점에서는 동일하다.

  • 테스트는 태생적으로 의존성 규칙을 따른다.

  • 또한, 테스트는 독립적으로 배포 가능하다.(가장 고립되어있다)

테스트를 고려한 설계

  • 테스트가 시스템의 설계와 잘 통합되지 않으면 테스트는 깨지기가 쉬워지고 시스템은 뻣뻣해져서 변경하기가 어려워진다.

  • 문제는 결합이다. (시스템이 수정될떄 마다 변경해야한다.)

  • 깨지기 쉬운 시스템 == 시스템이 수정되게 어렵게 만든다.

테스트 API

  • 테스트가 모든 업무 규칙을 검증하는 데 사용할 수 있도록 특화된 API를 만들면 된다.

  • 사용자 인터페이스가 사용하는 인터랙터 인터페이스 어댑터 들의 상위 집합이 될것이다.

  • 단순히 테스트를 UI에서 분리하는 것만이 아닌, 테스트 구조를 애플리케이션 구조로 부터 결합을 분리하는게 목표다.

  • 구조적 결합

    • 테스트 API의 역할은 애플리케이션의 구조를 테스트로부터 숨기는 데 있다.

    • 리객토링 시에도 테스트에는 영향을 주지 않다 따로 따로 진화할 수 있다는 점이 있따.

    • 테스트 코드는 점점 구체적여 지고 상용 코드는 점점 추상적여 지지만 서로간의 영향이 없다.

  • 보안

    • 테스트 API가 지닌 힘을 운영 시스템에 배포하면 위험에 처할 수 있다.

    • 테스트 API 자체와 테스트 API중 위험한 부분의 구현부는 독립적으로 배포할 수 있는 컴포넌트로 분리해야한다.

결론

  • 테스트는 시스템의 일부다.

  • 테스트를 통해 안정성의 이점을 얻고자 하면 테스트는 잘 설계되어야 한다.

  • 그렇지 않으면 유지보수가 힘들어 결국 버려질것이다.

29 클린 임베디드 아키텍처

소프트웨어는 닳지 않지만 펌웨어와 하드웨어는 낡아 가기에 소프트웨어도 수장해야한다. - 더그 소프트웨어는 닳지 않지만 펌웨어와 하드웨어에 대한 의존성을 관리하지 않으면 안으로푸터 파괴될수 있다. 소프트웨어를 하드웨어로 부터 분리해야한다. 어떻게 해야 임베디드 SW 아키텍처를 깔끔하게 유지할 수 있는가?

앱티튜드 테스트

  • 켄트백 "먼저 동작하게 만들어라 -> 올바르게 만들어라 -> 그리고 빠르게 만들어라"

  • 앱이 동작하도록 만드는것을 개발자용 앱티튜드 테스트라 부른다. (오직 앱이 동작하게만 만든다.)

타깃 - 하드웨어 병목현상

  • 임베디드 개발자들은 제한된 메모리 공간, 실시간성 제약과 처리 완료 시간, 제한된 입출력 등.. 을 고려해야한다.

  • 임베디드 엔지니어는 특별하다

  • 클린 임베디드 아키텍처는 테스트하기 쉬운 임베디드 아키텍처다

    • 병목현상을 줄이는 방법을 알아보다

    • 계층

      • 위와 같은 3계층에서 다른모듈에 대해 어디까지 알게 할지를 신중하게 처리하지 않는 경우 아래와 같이 변화한다.

      • 이는 안티 패턴이다.

    • 하드웨어는 세부사항이다.

      • 소프트웨어와 펌웨어 사이의 경계는 하드웨어 추상화 계층이라 부른다(HAL)

    • HAL 사용자에게 하드웨어 세부사항을 드러내지 말라

      • HAL을 제대로 만들었다면 HAL은 타깃 상관없이 테스트할 수 있는 경계층 또는 일련의 대체 지점을 제공한다.

    • 프로세서는 세부사항이다.

      • 클린 임베디드 아키텍처라면 이들 장치 접근 레지스터를 직접 사용하는 코드는 소수의, 순전히 펌웨어로만 한정 시켜야한다.

      • 이러한 마이크로 컨트롤러를 사용할 떄 펌웨어가 저수준 함수들을 프로세서 추상화 계층(PAL)의 형태로 격리시켜줄 수 있다.

      • 운영체제는 세부사항이다.

        • HAL은 필수적이다.

        • 베어멘탈(OS가 없는 임베디드 시스템) 시스템이라면 HAL만으로 충분하다.

        • 하지만 실시간 운영체제(RTOS)를 사용하는 등의 일이 발생하면 힘들어 진다.

        • 작성한 코드의 수명을 늘리려면 운영체제를 세부사항으로 취급하고 운영체제에 의존하는 일을 막아야 한다.

        • 새로운 OS가 제공하는, 이전 OS와는 다른 기능과 시스템 명령어에 맞게 그 의미 자체를 조정해야 할 가능성이 높다.

        • 클린 임베디드 아키텍처는 추상화 계층을 두어 SW를 OS로 부터 격리 시킨다.

        • 또한 이를 통해 테스트 지점을 찾는것에 도움을 얻을 수 있다.

        • 클린 임베디드 아키텍처를 따른 소프트웨어는 타깃 운영체제에 관계없이 테스트할 수 있다.

        • 제대로 만든 OSAL은 타깃과는 별개로 테스트할 수 있도록 해주는 경계층 또는 일련의 대체 지점을 제공한다.

인터페이스를 통하고 대체 가능성을 높이는 방향으로 프로그래밍 하라

  • HAL을 추가하거나 때로는 OSAL 을 추가해야할 뿐만 아니라 주요 계층에 대한 원칙을 정의해야할 수 있다.

  • 이들 원칙은 관심사를 분리 시키고 인터페이스를 활용하며 대체 가능성을 높이는 방향을 프로그래밍하도록 유도한다.

  • 구현 세부사항의 가시성을 제한하라.

DRY 원칙 : 조건부 컴파일 지시자를 반복하지 마라.

  • 코드를 반복하는 일은 반복하지 마라

  • 만약 추상화 계층이 있다면 어떨까? HAL조건부 컴파일 대신 사용할 수 있는 일련의 인터페이스를 제공한다면 우리는 링커 또는 어떤 형태의 실시간 바인딩을 사용해서 소프트웨어를 하드웨어와 연결할 수 있다.

결론

  • 모든 코드가 펌웨어가 되도록 내버려두면 제품이 오래 살아남을 수 없게 된다.

  • 오직 타깃 하드웨어에서만 테스트할 수 있는 제품도 마찬가지다.

  • 클린 임베디드 아키텍처는 제품이 장기간 생명력을 유지하는 데 도움을 준다.

Last updated