Yocto Intro
Yocto Projectx86 아키텍처는 Intel과 AMD 프로세서에서 광범위하게 사용되는 아키텍처이다. 범용성이 뛰어나 운영 체제와 소프트웨어를 폭넓게 지원하며, 수많은 개발자와 사용자들에게 매우 익숙하다. 현재 이 글을 읽고 있는 컴퓨터를 포함하여, 대부분의 개인용 컴퓨터와 서버 시장에서 주력으로 활용되고 있다. 이러한 압도적인 입지 덕분에 대다수 리눅스 배포판은 x86 아키텍처를 기반으로 개발되고, 지원되며, 최적화되어 있다.
하지만 임베디드 제품 환경에서는 상황이 다르다. 임베디드 기기에는 다양한 CPU 아키텍처가 폭넓게 채택된다. 따라서 x86 아키텍처를 주력으로 하는 범용 리눅스 배포판을 그대로 사용하기는 어렵다. 대신, 임베디드 리눅스 개발은 보통 Bottom-Up 방식으로 진행된다. 부트로더(Bootloader)와 커널(Kernel) 선택부터 필수 패키지, 사용자 애플리케이션 추가, 그리고 이 모든 것을 빌드(Build), 설치(Install), 패키징(Packaging)하는 과정까지 사용자가 세세하게 직접 관리하여 원하는 최적의 맞춤형(Customized) 리눅스 시스템을 구축하는 것이다.
리눅스 임베디드 그룹(Linux Embedded Group)은 이러한 과정을 효율적으로 통제할 수 있는 도구를 개발하기로 결정했다. 2010년 초기 버전의 Yocto Project는 OpenEmbedded와 BitBake를 완성하여 임베디드 리눅스 개발을 위한 기본 도구와 문서를 제공했다. 그 이듬해에는 완전한 리눅스 시스템 이미지를 생성하는 기능을 제공하는 Poky가 추가되면서, 오늘날 우리가 사용하는 Yocto의 기본적인 형태가 완성되었다. 이후 디버깅 기능 지원 SDK 배포, 하드웨어 아키텍처 확장, 빌드 시스템 개선 등 다양한 발전이 있었으나, Yocto Project의 핵심을 이루는 기능은 위에서 언급된 OpenEmbedded, BitBake, Poky 이 세 가지라고 할 수 있다. 이를 건축에 비유하면 다음과 같다.
Poky는 Yocto Project의 임베디드 리눅스 시스템을 구축하기 위한 기본 설정과 패키지 집합을 제공한다. Poky는 건축가가 건물을 디자인하는 도면과 설계도와 같다. 건축가가 도면을 기반으로 건물의 구조와 기능을 결정하듯, 개발자는 Recipe를 통해 만들고자 하는 시스템의 구성 요소를 정해진 양식에 따라 다양하게 정의할 수 있다.BitBake는 빌드 및 패키지 관리 도구이다. Yocto Project에서 Recipe를 읽어 이 Recipe대로 최종 산출물을 빌드하고 이미지를 생성하는 역할을 담당한다.
BitBake는 건축 현장에서 작업하는 공사 인부에 비유할 수 있다. 건축가가 설계한 도면을 바탕으로 재료를 조합하고 구조물을 건설하는 주체이다.
OpenEmbedded는 Yocto Project의 빌드 시스템으로, 리눅스 기반 시스템에 필요한 다양한 패키지와 컴포넌트를 관리한다. 이는 건축 현장의 자재 장부와 같다. 다양한 종류의 건축 자재와 도구를 보유하거나 그 정보를 관리하며, 필요한 자재(혹은 자재 정보)를 공사 인부에게 제공한다.
Yocto Project의 가장 큰 장점은 레이어(Layer) 구조를 통해 개발 환경을 모듈화하고 관리한다는 점이다.
레이어는 관련된 메타데이터(Metadata)를 논리적으로 묶어 놓은 단위이다. 기본 시스템을 위한 meta-poky 레이어부터, 특정 하드웨어 보드를 지원하는 Board Support Package (BSP) 레이어, 그리고 사용자가 직접 만든 meta-mylayer와 같은 커스텀 레이어에 이르기까지 여러 개의 레이어가 존재한다. 각 레이어는 특정 기능, 하드웨어, 또는 배포판의 차이점을 효율적으로 분리하여 관리할 수 있게 한다. 이 구조 덕분에 베이스 시스템에 영향을 주지 않으면서 특정 부분만 수정하거나 추가하는 작업이 매우 용이하다.
Yocto Project에서 시스템을 빌드하는 데 필요한 모든 정보는 메타데이터로 정의된다. 이 메타데이터는 크게 Recipe, Configuration File, Class 등으로 구성된다.Recipe: 개별 소프트웨어 패키지(예: openssl, bash 등)의 소스 코드 위치, 컴파일 방법, 의존성, 설치 위치 등을 정의하는 파일이다.Configuration File: 전역 설정 변수, 어떤 레이어를 사용할지, 어떤 이미지를 만들지 등을 설정하는 파일이다.Class: 빌드 과정에서 공통적으로 사용되는 함수나 설정(예: 패키징 방식)을 모아놓은 템플릿이다.
위에서 언급된 Recipe는 소프트웨어 패키지 추가, 의존성 관리, 커스텀 레이어 생성 등 시스템 구축에 필요한 모든 내용을 개발자가 원하는 방식으로 지원한다. 지원하는 항목이 매우 방대하여 이를 설명하는 매뉴얼의 이름조차 메가 매뉴얼일 정도이다. (https://docs.yoctoproject.org/singleindex.html)
Yocto Project의 모든 동작은 BitBake에 의해 구동된다. BitBake는 단순히 순서대로 컴파일을 진행하는 일반적인 빌드 툴이 아니라, 메타데이터를 해석하고 태스크(Task)를 실행하는 강력한 엔진이다.
BitBake가 빌드를 시작하면, 가장 먼저 설정된 모든 레이어에서 모든 Recipe와 설정 파일(Configuration File)을 읽어 들여 방대한 빌드 정보 그래프를 생성한다. 이 과정에서 각 Recipe가 의존하는 다른 Recipe나 라이브러리(Dependencies)를 파악한다. 예를 들어, 웹 서버를 빌드하려면 이전에 SSL 라이브러리가 빌드되어 있어야 한다는 의존 관계를 BitBake가 정확히 파악한다.
각 Recipe는 빌드 과정을 여러 개의 작은 태스크(Task)로 나누어 정의한다. 일반적인 주요 태스크의 흐름은 다음과 같으며 각 Recipe들은 의존성에 맞춰 병렬로 작업을 진행한다. 이는 복잡한 임베디드 시스템 빌드 시간을 획기적으로 단축시키는 핵심 요소이다.
fetch, unpack, patch, configure, compile, install, package
빌드된 모든 태스크의 결과물(예: 컴파일된 오브젝트 파일, 생성된 패키지)은 서명(Signature) 기반으로 캐시된다. 만약 Recipe, 소스 코드, 설정 등 입력에 변화가 없다면 BitBake는 이전 빌드에서 생성된 캐시를 재사용한다.
이러한 레이어 구조와 지능적인 빌드 프로세스 덕분에, Yocto Project는 수많은 하드웨어와 소프트웨어 요구 사항을 가진 임베디드 리눅스 생태계의 사실상의 표준(De facto standard)으로 자리 잡았다. 결론적으로, Yocto Project는 임베디드 리눅스 개발의 복잡성을 해결하고 재현성, 유연성, 효율성을 극대화한 강력한 프레임워크이다. Poky라는 기본 골격, OpenEmbedded라는 풍부한 재료, 그리고 BitBake라는 숙련된 엔진이 결합하여, 개발자가 원하는 맞춤형 리눅스 시스템을 구축할 수 있게 돕는다.특히 레이어 구조와 sstate 캐싱 시스템 덕분에 대규모 프로젝트의 관리와 유지 보수가 용이하며, 여러 개발자가 협업하는 환경에서도 일관된 빌드 결과를 보장한다.
물론 무조건 좋은 것은 아니고, 아래와 같은 점들도 감안을 해야 할 것이다. 단점이라고 하기는 애매하고… 실제 프로젝트를 진행할 때는 필수로 감안되어야 할 것이다.
- 프로젝트의 방대함으로 오는 관리의 어려움이 있다. Yocto는 결국 도구일 뿐이며 이를 운영하는 조직이나 사람에 따라 천차만별의 효율로 쓰일 수 있는데 레시피의 관리, 개발 프로세스의 관리 등을 상환에 따라 잘 고려해야 한다. (여기서 말하는 “잘"에 대해서는 다음에 한 번 더 고민해보자.)
- Recipe에서 각각의 개별 저장소를 다운받는 것으로부터 빌드가 시작된다. 이는 다시 말하면 각 개별 컴포넌트의 소스코드 혹은 배포 산출물을 저장할 수 있는 충분한 공간이 필요하다는 말이다. 간단한 시스템이면 모르겠지만, 다양한 컴포넌트를 다루는 빌드를 진행할 경우 어마무시한 용량을 사용하게 된다. 내가 지금 회사에서 개발하는 Yocto base 프로젝트는 50G를 훌쩍 넘는 공간 가용량을 필요로 한다.
- 먼저 말했듯 Recipe에서 각각의 개별 저장소를 다운받아야 하니 다운받는 시간이 필요하고, 컴포넌트 빌드가 필요한 경우 이를 진행되어야 한다. 이 때문에 몇 십개, 몇 백개의 Recipe에 대해 이런 과정들을 모두 진행되어야 하니 전체 빌드 시간이 오래 걸리게 된다. 개선할 수 있는 방법은 있지만 Yocto의 구조적인 부분 때문에 개선할 수 있는 부분은 한계가 있다.
- (다른 분들은 잘나서 그런지 이런 코멘트를 본 적이 없는데, 그렇다면… 나 자신 한정) 빌드에 문제가 있는 경우 가끔씩 Bitbake python코드를 디버깅 할 일이 있었는데 변수나 함수의 이름들이 너무 간략하게 정의되어 있고 너무 중복적으로 나타나서 코드를 분석하는데 어려움을 겪었다.
나는 Yocto 없는 리눅스 제품 개발을 해본적이 없어 정확한 비교를 하긴 힘들지만, 위와 같은 점들을 감안하더라고 임베디드 리눅스를 개발하는 어렵지만 가장 쉬운 길은 Yocto라고 생각한다. Yocto없이 이에 해당하는 작업들을 일일히 직접 관리하고 포팅한다고 가정하면 생각만으로 머리가 지끈하다.
다음에는 실제로 BitBake를 사용하여 간단한 Recipe를 빌드하는 실습 과정을 다뤄볼까 생각 중이다.