29. 클린 임베디드 아키텍처
소프트웨어는 닳지 않지만, 펌웨어와 하드웨어는 낡아가므로 결국 소프트웨어도 수정해야 한다.
→ 소프트웨어는 닳지 않지만, 펌웨어와 하드웨어에 대한 의존성을 관리하지 않으면 안으로부터 파괴될 수 있다.
펌웨어 정의
- 펌웨어는 ROM, EPROM 혹은 플래시 메모리 같은 비휘발성 메모리에 유지된다.
- 펌웨어는 하드웨어 장치에 프로그래밍된 소프트웨어 프로그램 혹은 명령어 집합이다.
- 펌웨어는 개별 하드웨어에 내장되는 소프트웨어다.
- 펌웨어는 읽기 전용 메모리에 쓰여진 소프트웨어다.
ROM에 상주하는 코드만이 펌웨어는 아니다.
저장되는 위치가 펌웨어를 정의하지는 않는다.
이보다는 무엇에 의존하는지, 그리고 하드웨어 발전에 맞춰 수정하기가 얼마나 어려운지에 따라 정의된다.
앱 개발자 역시 업무 로직을 안드로이드 API로부터 분리하지 않는다면 펌웨어를 작성하는 셈이다.
통신 관련 서브시스템을 재설계 할 때 했던 경험
- 기존 구현에서는 TDM과 전화를 거는 업무 로직이 전혀 분리되어있지 않았음.
- 전체 제품은 가장 윗단부터 밑바닥까지 모두 하드웨어 기술/의존적이었고, 엉킨 것을 풀 수 없었음.
엔지니어와 프로그래머에게 전하는 메시지는 분명하다. 펌웨어를 수없이 양산하는 일을 멈추고, 코드에게 유효 수명을 길게 늘릴 수 있는 기회를 주어라.
앱-티튜드 테스트
켄트 백은 소프트웨어를 구축하는 세 가지 활동을 다음과 같이 기술했다.
- 먼저 동작하게 만들어라.
- 소프트웨어가 동작하지 않는다면 사업은 망한다.
- 그리고 올바르게 만들어라.
- 코드를 리팩터링해서 당신을 포함한 나머지 사람들이 이해할 수 있게 만들고, 요구가 변경되거나 요구를 더 잘 이해하게 되었을 때 코드를 개선할 수 있게 만들어라.
- 그리고 빠르게 만들어라.
- 코드를 리팩터링해서 요구되는 성능을 만족시켜라.
빠르게 만들어라 → 같은 목표는 아주 세세한 최적화를 틈만 나면 수행해야 달성되는 목표다.
동작하는 것을 배워라. 그러고 나서 더 나은 해결책을 만들어라.
대다수의 앱들도 코드를 올바르게 작성해서 유효 수명을 길게 늘리는 데는 거의 관심 없이, 그저 동작하도록 만들어진다.
- 앱티튜드 테스트를 통과하기 위해 작성된 코드의 예에서 발견한 사실
- 코드를 이해하는 데 방해가 되는 장애물이 많다
- 이 코드는 특정 임베디드 장치에서만 테스트할 수 있음을 암시하는 파일 구조를 포함하고 있다.
타깃-하드웨어 병목현상
임베디드 개발자들은 임베디드가 아니었다면 다루지 않아도 될 특수한 관심사를 많이 가지고 있다.
제한된 메모리 공간, 실시간성 제약과 처리완료 시간, 제한된 입출력, 특이한 사용자 인터페이스, 여러 센서와 실제 세상과의 상호작용 등이다.
임베디드가 지닌 특수한 문제 중 하나는 타깃-하드웨어 병목현상이다.
타깃이 테스트가 가능한 유일한 장소라면 타깃-하드웨어 병목현상이 발생하여 진척이 느려질 것이다.
- 클린 임베디드 아키텍처는 테스트하기 쉬운 아키텍처다
- 몇가지 아키텍처 원칙을 임베디드 소프트웨어와 펌웨어에 적용하여 타깃-하드웨어 병목현상을 줄이는 방법을 살펴보자.
- 계층
- 계층에는 여러가지가 있다.
- 하드웨어는 기술의 발전과 무어의 법칙에 따라 변할 것이다.
- 하드웨어가 정의되었다면 나머지 시스템 사이의 분리는 주어진다.
- 하드웨어 관련 정보가 코드 전체를 오염시키지 못하게 막을 방법이 전혀 없다.
- 소프트웨어와 펌웨어가 서로 섞이는 일은 안티패턴이다.
- 가벼운 변경에도 시스템 전체를 대상으로 희귀 테스트를 전부 실행해야 한다.
- 하드웨어는 세부사항이다
- 소프트웨어와 펌웨어 사이의 경계는 코드와 하드웨어 사이의 경계와는 달리 잘 정의하기가 대체로 힘들다.
- 임베디드 소프트웨어 개발자가 해야 할 일 하나는 이 경계를 분명하게 만드는 것이다.
- 소프트웨어와 펌웨어 사이의 경계는 하드웨어 추상화 계층이라고 부른다.
- HAL(Hardware Abstraction Layer)
- HAL의 API는 소프트웨어의 필요에 맞게 만들어져야 한다.
- 펌웨어는 바이트 또는 바이트의 배열을 플래시 메모리에 저장할 수 있다. 반대로 애플리케이션에서는 이름/값과 같이 쌍으로 된 데이터를 영속성 장치에 저장하거나 읽을 수 있어야 한다.
- HAL 사용자에게 하드웨어 세부사항을 드러내지 말라
- HAL은 타깃에 상관없이 테스트할 수 있는 경계층 또는 일련의 대체 지점을 제공한다.
- 프로세서는 세부사항이다.
- 클린 임베디드 아키텍처라면 이들 장치 접은 레지스터를 직접 사용하는 코드는 소수의, 순전히 펌웨어로만 한정시켜야 한다.
- 운영체제는 세부사항이다
- 작성한 코드의 수명을 늘리려면, 무조건 운영체제를 세부사항으로 취급하고 운영체제에 의존하는 일을 막아야 한다.
- 소프트웨어는 운영체제를 통해 운영 환경이 제공하는 서비스에 접근한다.
- OS는 소프트웨어를 펌웨어로부터 분리하는 계층이다.
- 클린 임베디드 아키텍처는 운영체제 추상화 계층을 통해 소프트웨어를 운영체제로부터 격리시킨다.
- 이제 코드 비대화 문제가 염려되기 시작할 수도 있다.
- OSAL은 OS를 사용하는 데 따른 수많은 중복이 격리되어 있는 장소다.
- OSAL을 정의하는 일은 결국 애플리케이션에서도 공통 구조를 가지도록 힘쓰는 일이기도 하다.
- 인터페이스를 통하고 대체 가능성을 높이는 방향으로 프로그래밍하라.
- 계층형 아키텍처는 인터페이스를 통해 프로그래밍하자는 발상을 기반으로 한다.
- 오직 구현체에서만 필요한 데이터 구조, 상수, 타입 정의들로 인터페이스 헤더 파일을 어지럽히지 말라.
결론
임베디드 소프트웨어를 개발하는 사람들은 임베디드 소프트웨어 바깥의 경험에서 많은 것을 배울 수 있다.
이 책을 선택한 당신이 임베디드 개발자라면 소프트웨어 개발에 대한 풍부한 지혜의 말과 생각들을 얻을 수 있을 것이다.
모든 코드가 펌웨어가 되도록 내버려두면 제품이 오래 살아남을 수 없게 된다. 오직 타깃 하드웨어에서만 테스트할 수 있는 제품도 마찬가지이다. 클린 임베디드 아키텍처는 제품이 장기간 생명력을 유지하는 데 도움을 준다.