서론: 익숙한 Flutter, 낯선 가능성의 발견
Flutter(플러터). 많은 개발자에게 이 이름은 아름답고 빠른 모바일 앱을 만들기 위한 구글의 UI 툴킷으로 익숙합니다. iOS와 안드로이드에서 동일한 코드베이스로 네이티브에 가까운 성능을 내는 앱을 만들 수 있다는 점은 개발 생태계에 큰 혁신을 가져왔습니다. 하지만 만약 Flutter의 무대가 스마트폰과 웹 브라우저를 넘어, 우리가 매일 사용하는 자동차의 대시보드, 공장의 산업용 제어판, 심지어는 작은 라즈베리파이 위에서 직접 구동되는 하나의 'OS'가 될 수 있다면 어떨까요?
이 이야기는 더 이상 먼 미래의 상상이 아닙니다. 세계적인 자동차 제조사 Toyota는 차세대 차량의 인포테인먼트 시스템을 구동하기 위해 Flutter를 채택했습니다. BMW 역시 그들의 iDrive 시스템에 Flutter를 도입하며 그 가능성을 증명하고 있습니다. 이들이 수많은 검증된 기술들을 뒤로하고 Flutter를 선택한 이유는 무엇일까요? 바로 Flutter가 가진 압도적인 UI 표현력과 개발 생산성, 그리고 뛰어난 성능이 임베디드 시스템이라는 새로운 영역에서 폭발적인 잠재력을 발휘하기 때문입니다.
이 글에서는 모바일과 웹의 경계를 넘어 임베디드와 IoT 시장의 '숨은 강자'로 떠오르고 있는 'Flutter Embedded'의 세계를 탐험합니다. Toyota와 같은 거대 기업들이 왜 Flutter에 주목하는지 그 이유를 심도 있게 분석하고, 더 나아가 당신의 책상 위에 있는 작은 라즈베리파이를 이용해 직접 Flutter로 구동되는 커스텀 UI(OS)를 만들어보는 실용적인 과정까지 함께 안내할 것입니다. 이제 Flutter의 진정한 활동 무대가 '스크린이 있는 모든 곳'임을 직접 확인해볼 시간입니다.
1부: 왜 임베디드 시스템은 Flutter를 선택하는가?
전통적인 임베디드 UI 개발의 한계
임베디드 시스템의 UI를 개발하는 것은 전통적으로 많은 어려움이 따르는 일이었습니다. 저사양 하드웨어 위에서 부드럽게 동작해야 한다는 제약 때문에 C/C++와 같은 저수준 언어와 Qt, Embedded Wizard 같은 전문 프레임워크가 주로 사용되었습니다.
- 높은 복잡성과 느린 개발 속도: C++과 Qt를 이용한 개발은 UI의 작은 수정에도 많은 시간과 노력이 필요합니다. 현대적인 모바일 앱 개발 환경에서 당연하게 여겨지는 'Hot Reload' 같은 기능은 상상하기 어려웠고, 이는 개발 사이클을 매우 길게 만들었습니다.
- 부족한 UI/UX 유연성: 전통적인 방식으로는 오늘날 사용자들이 기대하는 화려하고 동적인 애니메이션, 부드러운 터치 반응을 구현하기가 매우 까다롭습니다. 결과적으로 투박하고 제한적인 UI가 만들어지기 쉬웠습니다.
- 파편화된 기술 스택과 높은 인력 비용: 특정 하드웨어나 플랫폼에 종속적인 기술 스택은 개발자 풀을 제한하고, 이는 곧 높은 인건비와 유지보수의 어려움으로 이어졌습니다.
이러한 문제점들은 특히 자동차 인포테인먼트 시스템(IVI), 스마트 홈 기기, 산업용 키오스크처럼 사용자 경험이 중요해진 시장에서 큰 걸림돌이 되었습니다.
Flutter가 제시하는 혁신적인 해결책
Flutter는 이러한 임베디드 UI 개발의 고질적인 문제들을 해결할 수 있는 강력한 대안으로 부상했습니다. 그 핵심적인 이유는 다음과 같습니다.
1. 압도적인 성능과 미려한 그래픽
Flutter는 운영체제의 네이티브 UI 위젯을 사용하는 대신, 자체적인 그래픽 엔진인 'Skia'를 통해 UI의 모든 픽셀을 직접 화면에 그립니다. 이는 임베디드 시스템에서 엄청난 이점을 가집니다. 운영체제의 UI 렌더링 파이프라인에 의존하지 않고 GPU에 직접 접근하여 UI를 그리기 때문에, 저사양 하드웨어에서도 60fps, 심지어 120fps의 부드러운 애니메이션을 구현할 수 있습니다. Toyota가 차량용 시스템에서 스마트폰과 같은 부드러운 사용자 경험을 제공할 수 있는 비결이 바로 여기에 있습니다.
2. 비교 불가능한 개발 생산성
Flutter의 'Hot Reload' 기능은 임베디드 개발 환경에 혁명을 가져왔습니다. 코드를 수정한 후 수 초 내에 변경 사항이 실제 기기 화면에 반영되는 것을 보며 UI를 개발하는 경험은 기존의 컴파일-배포-재부팅 사이클에 비하면 상상할 수 없는 속도입니다. 또한, 선언형 UI(Declarative UI) 구조는 복잡한 UI 상태 관리를 단순화하여 개발자가 비즈니스 로직에 더 집중할 수 있게 해줍니다. 이는 제품의 출시 시기(Time-to-Market)를 획기적으로 단축시키는 요인이 됩니다.
3. 단일 코드베이스의 확장성
Flutter는 본질적으로 크로스플랫폼 프레임워크입니다. 이는 모바일 앱을 위해 작성된 UI 코드와 로직의 상당 부분을 거의 수정 없이 임베디드 기기에서도 재사용할 수 있다는 의미입니다. 예를 들어, 스마트폰 앱으로 제어하는 스마트 홈 기기를 만든다고 상상해보세요. 스마트폰 앱과 기기 자체의 디스플레이 UI를 동일한 Flutter 코드베이스로 관리할 수 있습니다. 이는 개발 리소스와 유지보수 비용을 극적으로 절감시킵니다.
4. 거대한 생태계와 낮은 진입 장벽
Dart 언어는 Java, C#, JavaScript 등에 익숙한 개발자라면 누구나 쉽게 배울 수 있습니다. 또한, pub.dev를 통해 수많은 오픈소스 패키지를 활용할 수 있어 개발 속도를 더욱 높일 수 있습니다. 특정 벤더에 종속된 고가의 임베디드 UI 툴과 달리, Flutter는 완전히 오픈소스이며 거대한 커뮤니티의 지원을 받고 있습니다. 이는 곧 문제 해결이 용이하고, 유능한 개발자를 찾기도 훨씬 수월하다는 것을 의미합니다.
결론적으로, Toyota와 BMW 같은 기업들은 Flutter를 통해 '더 빠르게, 더 아름답게, 더 저렴하게' 고품질의 임베디드 UI를 만들 수 있다는 사실을 발견한 것입니다. 이는 단순한 기술 채택을 넘어, 제품 개발 철학의 변화를 의미합니다.
2부: 실전! 라즈베리파이로 나만의 Flutter OS 만들기
이제 이론을 넘어 직접 라즈베리파이에서 Flutter UI를 부팅하는 과정을 체험해 보겠습니다. 여기서 'OS를 만든다'는 것은 전통적인 의미의 커널부터 개발하는 것이 아니라, 리눅스 부팅 후 데스크톱 환경(GUI)을 거치지 않고 곧바로 우리가 만든 Flutter 앱이 전체 화면으로 실행되도록 하여 마치 하나의 독립된 OS처럼 보이게 만드는 '키오스크 모드'를 의미합니다. 이는 산업용 기기나 특정 목적의 장비에서 가장 흔하게 사용되는 방식입니다.
사전 준비물
- 하드웨어:
- 라즈베리파이 4 Model B (2GB 이상 권장)
- 고속 MicroSD 카드 (32GB 이상, A2 등급 권장)
- 전원 어댑터 및 디스플레이, 키보드/마우스 (초기 설정용)
- 소프트웨어:
- Flutter SDK가 설치된 개발용 PC (Linux/macOS/Windows)
- Raspberry Pi Imager
- SSH 클라이언트 (예: PuTTY, Terminal)
전체 프로세스 개요
우리가 진행할 작업은 크게 4단계로 나뉩니다.
- 라즈베리파이 준비: 가벼운 버전의 Raspberry Pi OS를 설치하고 기본 설정을 합니다.
- Flutter Engine 빌드: 개발 PC에서 라즈베리파이의 ARM 아키텍처에 맞는 Flutter Engine을 크로스 컴파일합니다. 이 과정이 가장 중요하고 시간이 많이 소요됩니다.
- Flutter 앱 빌드 및 배포: 간단한 Flutter 앱을 만들고, 라즈베리파이에서 실행 가능한 형태로 빌드하여 전송합니다.
- 자동 실행 설정: 라즈베리파이가 부팅될 때 Flutter 앱이 자동으로 실행되도록 systemd 서비스를 등록합니다.
1단계: 라즈베리파이 준비하기
데스크톱 환경은 필요 없으므로, 가장 가벼운 'Raspberry Pi OS Lite (64-bit)' 버전을 사용합니다. Raspberry Pi Imager를 사용하여 SD카드에 OS를 구워주세요. 이 과정에서 톱니바퀴 아이콘을 눌러 SSH 활성화, Wi-Fi 설정, 사용자 계정 설정을 미리 해두면 매우 편리합니다.
OS 설치 후 라즈베리파이를 부팅하고, 동일 네트워크에 있는 개발 PC에서 SSH로 접속합니다.
ssh [사용자명]@[라즈베리파이_IP_주소]
접속 후, 시스템을 최신 상태로 업데이트하고 필수 라이브러리를 설치합니다.
sudo apt update
sudo apt upgrade -y
sudo apt install -y build-essential libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdrm-dev libgbm-dev ttf-mscorefonts-installer fontconfig libsystemd-dev libinput-dev libudev-dev libxkbcommon-dev
sudo fc-cache -f -v
위 라이브러리들은 Flutter가 그래픽 하드웨어(GPU)에 직접 접근하고, 입력장치(키보드, 마우스)를 인식하며, 폰트를 렌더링하는 데 필수적입니다.
2단계: 라즈베리파이용 Flutter Engine 빌드하기 (크로스 컴파일)
이 단계는 개발 PC(리눅스 환경 권장, VM 사용 가능)에서 진행됩니다. Flutter 앱은 Dart 코드로 작성되지만, 이를 실행하는 것은 각 플랫폼에 맞게 컴파일된 C++ 코드인 Flutter Engine입니다. 우리는 라즈베리파이의 ARM 64bit 아키텍처에서 DRM/GBM 백엔드(X11 같은 윈도우 시스템 없이 직접 그래픽 장치를 제어하는 방식)를 사용하도록 Engine을 빌드해야 합니다.
먼저, 구글의 빌드 도구인 depot_tools
를 설치합니다.
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
다음으로 Flutter Engine 소스코드를 다운로드합니다. (시간이 매우 오래 걸립니다)
git clone https://github.com/flutter/engine.git
cd engine
라즈베리파이용 빌드 환경을 설정합니다. 우리는 --arm64
, --unopt
(디버깅 용이), 그리고 DRM/GBM 백엔드를 사용하도록 지정할 것입니다.
./flutter/tools/gn --target-os linux --linux-cpu arm64 --runtime-mode release --no-goma --embedder-for-target --use-gbm
# 또는 디버그 모드
# ./flutter/tools/gn --target-os linux --linux-cpu arm64 --unoptimized --no-goma --embedder-for-target --use-gbm
설정이 완료되면, out/linux_release_arm64
(또는 `out/linux_debug_unopt_arm64`) 디렉토리에 빌드 파일이 생성됩니다. 이제 실제 빌드를 시작합니다. 이 과정은 PC 사양에 따라 수십 분에서 수 시간까지 걸릴 수 있습니다.
ninja -C out/linux_release_arm64 flutter_embedder.so
빌드가 성공적으로 완료되면, out/linux_release_arm64
디렉토리 안에 flutter_embedder.so
파일과 icudtl.dat
파일이 생성됩니다. 이 두 파일이 우리가 라즈베리파이에서 Flutter를 구동하는 데 필요한 핵심 결과물입니다.
3단계: Flutter 앱 빌드 및 배포
이제 라즈베리파이에서 실행할 간단한 Flutter 앱을 만들어 보겠습니다. 개발 PC에서 새로운 Flutter 프로젝트를 생성합니다.
flutter create rpi_custom_os
cd rpi_custom_os
lib/main.dart
파일을 열어 원하는 UI로 수정합니다. 예를 들어, 간단한 시계와 메시지를 표시하는 화면을 만들어 봅니다.
다음으로, 이 앱을 라즈베리파이에서 실행할 수 있는 AOT(Ahead-Of-Time) 번들 형태로 빌드해야 합니다. 이 번들은 플랫폼에 독립적인 에셋과 컴파일된 Dart 코드를 포함합니다.
flutter build bundle
빌드가 완료되면 build/flutter_assets
디렉토리가 생성됩니다. 이제 이 디렉토리와 앞서 2단계에서 빌드한 Engine 파일들을 라즈베리파이로 전송해야 합니다.
라즈베리파이에 적당한 디렉토리(예: /home/pi/flutter_app
)를 만들고, scp
명령어를 사용해 파일들을 전송합니다.
# 개발 PC에서 실행
# Engine 파일 전송
scp path/to/engine/out/linux_release_arm64/flutter_embedder.so [사용자명]@[라즈베리파이_IP]:/home/pi/flutter_app/
scp path/to/engine/out/linux_release_arm64/icudtl.dat [사용자명]@[라즈베리파이_IP]:/home/pi/flutter_app/
# 앱 번들 전송
scp -r path/to/rpi_custom_os/build/flutter_assets [사용자명]@[라즈베리파이_IP]:/home/pi/flutter_app/
이제 모든 준비가 끝났습니다. 라즈베리파이에서 앱을 실행해볼 차례입니다. 이를 위해 flutter-pi
와 같은 경량 임베디드 Flutter 실행기가 필요합니다. flutter-pi
는 라즈베리파이에 최적화된 오픈소스 프로젝트입니다.
라즈베리파이에서 flutter-pi
를 빌드하고 설치합니다.
# 라즈베리파이에서 실행
git clone https://github.com/ardera/flutter-pi.git
cd flutter-pi
make -j`nproc`
sudo make install
이제 드디어 Flutter 앱을 실행할 수 있습니다. SSH 세션을 종료하고 라즈베리파이에 직접 연결된 디스플레이를 보면서 실행하는 것이 좋습니다. 만약 SSH로 실행한다면, 현재 사용자를 render
그룹에 추가해야 할 수 있습니다.
# 라즈베리파이에서 실행
flutter-pi --release /home/pi/flutter_app/
이 명령을 실행하면, 라즈베리파이의 검은 터미널 화면이 사라지고 우리가 만든 Flutter UI가 전체 화면으로 나타나는 것을 볼 수 있습니다! 이것이 바로 Flutter Embedded의 시작입니다.
4단계: 부팅 시 자동 실행 설정
마지막으로, 라즈베리파이가 켜질 때마다 자동으로 Flutter 앱이 실행되도록 설정하여 진정한 '커스텀 OS'처럼 만들겠습니다. 이를 위해 systemd
서비스를 이용합니다.
/etc/systemd/system/flutter-app.service
경로에 서비스 파일을 생성합니다.
sudo nano /etc/systemd/system/flutter-app.service
그리고 아래 내용을 붙여넣습니다. User
와 ExecStart
의 경로는 자신의 환경에 맞게 수정해야 합니다.
[Unit]
Description=Flutter Custom OS App
After=graphical.target
[Service]
User=pi
Type=simple
ExecStart=/usr/local/bin/flutter-pi --release /home/pi/flutter_app
Restart=on-failure
RestartSec=5
[Install]
WantedBy=graphical.target
파일을 저장하고, 새로 만든 서비스를 활성화하고 시작합니다.
sudo systemctl enable flutter-app.service
sudo systemctl start flutter-app.service
이제 라즈베리파이를 재부팅하면, 부팅 과정이 끝난 후 바로 Flutter 앱이 화면 전체를 채우며 실행될 것입니다. 축하합니다! 당신은 라즈베리파이를 위한 커스텀 Flutter OS(UI)를 성공적으로 만들었습니다.
3부: Flutter Embedded의 미래와 기회
라즈베리파이에서의 성공은 시작에 불과합니다. Flutter Embedded의 생태계는 빠르게 성장하고 있으며, 그 가능성은 무궁무진합니다.
- 다양한 하드웨어 지원: 라즈베리파이뿐만 아니라 NXP의 i.MX 8 시리즈, STMicroelectronics의 STM32MP1과 같은 산업용 임베디드 보드에서도 Flutter를 구동하려는 시도가 활발히 이루어지고 있습니다. 이는 Flutter가 취미 수준을 넘어 실제 산업 현장에 적용될 수 있음을 보여줍니다.
- 네이티브 기능과의 통합: Flutter에서 Dart FFI(Foreign Function Interface)를 사용하면 C/C++로 작성된 기존 하드웨어 제어 라이브러리(GPIO, I2C, SPI 통신 등)를 직접 호출할 수 있습니다. 이는 Flutter UI와 저수준 하드웨어 제어 로직을 자연스럽게 결합할 수 있게 해줍니다.
- 새로운 시장의 기회: Flutter 개발자에게 임베디드 시장은 새로운 기회의 땅입니다. 모바일 앱 시장의 치열한 경쟁에서 벗어나, 스마트 가전, 디지털 사이니지, 의료 기기, 공장 자동화 등 다양한 분야에서 자신의 기술을 발휘할 수 있습니다. 기업 입장에서는 더 적은 비용으로 더 빠르게 고품질의 제품을 만들 수 있는 강력한 무기를 얻게 됩니다.
결론: 스크린이 있는 모든 곳에, Flutter
우리는 Flutter가 단순히 모바일 앱을 위한 도구가 아님을 확인했습니다. Toyota의 자동차에서부터 우리가 직접 만든 라즈베리파이 키오스크에 이르기까지, Flutter는 스크린이 있는 모든 기기에서 일관되고 아름다운 사용자 경험을 제공할 수 있는 강력한 잠재력을 지니고 있습니다.
개발 생산성과 성능, 두 마리 토끼를 모두 잡은 Flutter는 임베디드 시스템 개발의 패러다임을 바꾸고 있습니다. 과거에는 상상하기 어려웠던 풍부한 그래픽과 부드러운 인터랙션을 이제는 저사양 하드웨어에서도 합리적인 비용과 시간으로 구현할 수 있게 되었습니다. 지금 당장 당신의 서랍 속에 잠자고 있는 라즈베리파이를 꺼내보세요. Flutter와 함께라면, 그 작은 보드가 당신의 아이디어를 세상에 보여줄 멋진 캔버스가 될 수 있을 것입니다. Flutter의 여정은 이제 막 새로운 챕터를 시작했습니다.