모던 라이프랩Daily Insights & Guide for Contemporary Living
👤MODERN LIFE LAB//테크>AI & 도구

Flutter와 TensorFlow Lite로 똑똑한 모바일 앱 만들기 (초보자 가이드)

6 MIN READ
HOME>테크>AI & 도구>Flutter와 TensorFlow Lite로 똑똑한 모바일 앱 만들기 (초보자 가이드)
[대가성 광고]본 콘텐츠는 쿠팡 파트너스 등의 제휴 링크를 포함하고 있으며, 이에 따른 일정액의 수수료를 지급받을 수 있습니다.

내 손으로 직접 만드는 모바일 AI! Flutter와 TensorFlow Lite를 이용해 머신러닝 모델을 앱에 통합하는 방법을 단계별로 쉽게 알려드립니다.

안녕하세요! 요즘 길을 걷다가도 문득 궁금한 꽃 이름을 사진 한 장으로 바로 알 수 있고, 외국어 메뉴판도 카메라만 비추면 바로 번역되는 신기한 앱들, 한 번쯤 써보셨죠? 이런 마법 같은 기능 뒤에는 바로 '머신러닝(Machine Learning)'이라는 기술이 숨어있습니다. "와, 저런 건 어떻게 만드는 걸까?" 하고 막연하게만 생각하셨다면, 오늘 이 글이 바로 그 궁금증을 풀어줄 열쇠가 될 거예요.

사실 '앱 개발'과 '인공지능'이라는 두 단어만 들어도 덜컥 겁부터 나기 마련입니다. 저도 그랬으니까요. 하지만 구글이 만든 매력적인 크로스플랫폼 프레임워크 '플러터(Flutter)'와 모바일 기기에 최적화된 머신러닝 라이브러리 '텐서플로우 라이트(TensorFlow Lite, TFLite)'가 있다면, 이야기는 완전히 달라집니다. 이 둘의 조합은 생각보다 훨씬 더 쉽고 재미있게 우리를 모바일 AI의 세계로 안내합니다.

오늘은 바로 이 Flutter와 TFLite를 사용해서, 머신러닝 모델을 내 모바일 앱에 직접 심어보는 과정을 차근차근 함께 해보려고 합니다. 복잡한 서버 없이, 스마트폰 자체에서 AI가 돌아가는 '온디바이스(On-device) AI'의 매력에 푹 빠질 준비, 되셨나요?

왜 'Flutter + TFLite' 조합이 특별할까요?

본격적인 실습에 앞서, 왜 수많은 개발자가 이 조합에 열광하는지 잠깐 짚고 넘어갈게요. 단순히 '요즘 뜨는 기술'이라서가 아니라, 정말 확실한 장점들이 있거든요.

첫째, 압도적인 개발 효율성입니다. Flutter는 단 하나의 코드베이스로 안드로이드와 iOS 앱을 동시에 만들 수 있게 해줍니다. UI를 그리는 것부터 비즈니스 로직을 짜는 것까지, 모든 걸 한 번에 해결할 수 있죠. 여기에 TFLite를 얹으면, 우리가 만든 AI 기능 역시 양쪽 플랫폼에서 그대로 작동합니다. 따로따로 개발할 필요가 없으니 시간과 비용이 절약되는 건 당연하겠죠?

둘째, 빠르고 프라이버시가 보장되는 사용자 경험을 제공할 수 있습니다. TFLite는 인터넷 연결이 필요한 클라우드 서버가 아니라, 사용자 스마트폰 내부에서 직접 머신러닝 모델을 실행합니다. 이걸 '온디바이스 추론'이라고 불러요. 덕분에 네트워크 지연 없이 결과를 바로바로 보여줄 수 있고, 사용자의 민감한 데이터(사진, 음성 등)가 기기 밖으로 나가지 않으니 프라이버시 측면에서도 훨씬 안전합니다. 사용자는 더 빠르고 안전한 앱을 쓸 수 있으니 만족도가 올라갈 수밖에 없죠.

여러 대의 모니터를 보며 코딩에 집중하고 있는 여성 개발자
하나의 코드로 여러 플랫폼을 정복하는 것, Flutter와 함께라면 가능합니다.Source: ThisIsEngineering / pexels

셋째, 비용 걱정이 없습니다. 보통 클라우드 기반의 AI 서비스를 이용하면 API를 호출할 때마다 비용이 발생합니다. 사용자가 많아질수록 부담이 커지는 구조죠. 하지만 온디바이스 AI는 사용자의 기기 자원을 활용하기 때문에, 서버 유지 비용이나 API 사용료에 대한 걱정에서 자유로워질 수 있습니다. 우리 같은 1인 개발자나 작은 팀에게는 정말 큰 장점 아닐까요?

1단계: 프로젝트 준비 및 모델 추가하기

자, 이제 이론은 충분하니 직접 코드를 만져볼 시간입니다. 가장 먼저 할 일은 Flutter 프로젝트를 생성하고, TFLite를 사용하기 위한 준비를 하는 것입니다. 이미 만들어 둔 이미지 분류 모델(.tflite 파일)과 모델이 분류할 항목들의 이름이 적힌 레이블 파일(labels.txt)이 있다고 가정하고 진행할게요.

먼저, Flutter 프로젝트의 pubspec.yaml 파일을 열고 dependencies 항목에 tflite_flutter 패키지를 추가해 주세요. 이 패키지가 Flutter 앱에서 TFLite 모델을 불러오고 실행하는 핵심적인 역할을 합니다.

dependencies:
  flutter:
    sdk: flutter
  tflite_flutter: ^0.10.4 # 글 작성 시점의 최신 버전이며, pub.dev에서 최신 버전을 확인하세요.
  image_picker: ^1.0.7 # 갤러리에서 이미지를 가져오기 위해 추가합니다.

그다음, 프로젝트의 루트 디렉터리에 assets라는 폴더를 만들고, 준비해 둔 model.tflite 파일과 labels.txt 파일을 그 안에 넣어주세요. 그리고 다시 pubspec.yaml 파일로 돌아와, Flutter가 이 파일들을 인식하고 앱에 포함시킬 수 있도록 다음과 같이 assets 경로를 등록해 줍니다.

flutter:
  uses-material-design: true
  assets:
    - assets/model.tflite
    - assets/labels.txt

여기까지 마쳤다면 flutter pub get 명령어를 실행해서 패키지를 설치하고 asset 설정을 적용해주세요. 이제 우리 앱은 TFLite 모델을 품을 준비를 마쳤습니다!

2단계: 모델과 레이블 불러오기

이제 코드 상에서 방금 추가한 모델과 레이블 파일을 불러올 차례입니다. TFLite 모델을 다루는 로직을 별도의 서비스 클래스로 분리하면 코드가 훨씬 깔끔해지겠죠? TfliteService 같은 이름의 Dart 파일을 만들고 다음과 같이 코드를 작성해 봅시다.

Interpreter는 TFLite 모델의 실행기 역할을 하는 객체입니다. Interpreter.fromAsset()을 통해 assets 폴더에 있는 모델 파일을 비동기적으로 불러올 수 있습니다. 레이블 파일 역시 rootBundle을 사용해 텍스트를 읽어온 뒤, 줄바꿈 문자(\n)를 기준으로 잘라 리스트로 만들어 줍니다.

import 'package:flutter/services.dart';
import 'package:tflite_flutter/tflite_flutter.dart';

class TfliteService {
  late Interpreter _interpreter;
  late List\<String> _labels;

  Future\<void> loadModel() async &#123;
    try &#123;
      // 모델 불러오기
      _interpreter = await Interpreter.fromAsset('model.tflite');
      
      // 레이블 불러오기
      final labelData = await rootBundle.loadString('assets/labels.txt');
      _labels = labelData.split('\n');

      print('모델과 레이블이 성공적으로 로드되었습니다.');
    &#125; catch (e) &#123;
      print('모델 또는 레이블 로드에 실패했습니다: $e');
    &#125;
  &#125;
  
  // 추후 추론 함수가 여기에 추가될 예정입니다.
&#125;

이 loadModel 함수를 앱이 시작될 때 호출해두면, 필요할 때 바로 모델을 사용할 수 있는 상태가 됩니다. 예를 들어, main.dart의 main 함수나 스플래시 화면에서 미리 로드해두는 것이 좋은 방법입니다.

3단계: 이미지 분류 실행 및 결과 표시하기

모델을 메모리에 올렸으니, 이제 실제로 이미지를 받아 분류를 실행해볼 시간입니다. 사용자가 갤러리에서 이미지를 선택하면, 그 이미지를 모델이 이해할 수 있는 형태로 가공(전처리)한 뒤 모델에 입력으로 넣어주어야 합니다.

머신러닝 모델, 특히 이미지 모델은 정해진 크기와 형식의 입력만 받습니다. 예를 들어, 224x224 크기의 RGB 이미지 데이터를 요구하는 식이죠. image 패키지 등을 활용하면 선택된 이미지의 크기를 조절하고, 각 픽셀의 색상 값을 정규화(보통 0~1 또는 -1~1 사이의 값으로 변환)하는 작업을 수행할 수 있습니다. 이 전처리 과정은 모델의 성능에 직접적인 영향을 미치므로 매우 중요합니다.

전처리가 완료된 이미지 데이터(보통 List\<List\<List\<double>>> 형태의 다차원 배열)를 준비하고, 모델의 출력값을 담을 빈 배열도 준비합니다. 그리고 _interpreter.run(input, output)을 호출하면 마법이 일어납니다! 모델이 이미지를 분석하고, 각 레이블에 해당할 확률을 output 배열에 채워 넣는 거죠.

// TfliteService 클래스 내부에 추가될 추론 함수 예시
Future\<String> classifyImage(File image) async &#123;
  // 1. 이미지 전처리 (image 패키지 등을 사용하여 모델 입력에 맞게 변환)
  //    - 이미지 리사이징 (예: 224x224)
  //    - 이미지를 Tensor로 변환
  //    - 정규화 (Normalization)
  var input = preprocessImage(image); // 이 함수는 직접 구현해야 합니다.

  // 2. 모델의 출력 형태에 맞게 출력 버퍼 준비
  //    예: 10개의 클래스를 분류한다면, List\<double>.filled(10, 0.0)을 원소로 갖는 리스트
  var output = List.filled(1 * _labels.length, 0).reshape([1, _labels.length]);

  // 3. 추론 실행
  _interpreter.run(input, output);

  // 4. 결과 후처리
  //    가장 높은 확률을 가진 레이블의 인덱스를 찾습니다.
  var resultIndex = 0;
  var maxProbability = 0.0;
  for (var i = 0; i \< output[0].length; i++) &#123;
    if (output[0][i] > maxProbability) &#123;
      maxProbability = output[0][i];
      resultIndex = i;
    &#125;
  &#125;

  return _labels[resultIndex];
&#125;

이제 남은 일은 Flutter UI를 만드는 것입니다. image_picker로 이미지를 선택하는 버튼, 선택된 이미지를 보여주는 위젯, 그리고 classifyImage 함수를 호출해서 얻은 결과(가장 확률이 높은 레이블 이름)를 화면에 텍스트로 표시해주면 되겠죠. FutureBuilder나 상태 관리 라이브러리를 활용하면 비동기 작업의 결과를 UI에 자연스럽게 반영할 수 있습니다.

마무리하며

어떠셨나요? 생각보다 복잡하지 않죠? 물론 오늘 다룬 내용은 가장 기본적인 이미지 분류 모델을 예시로 든 것이고, 실제로는 더 정교한 데이터 전/후처리 과정이 필요하거나 객체 탐지, 자세 추정 등 더 복잡한 모델을 다루게 될 수도 있습니다.

하지만 가장 중요한 것은 '시작이 반'이라는 점입니다. 오늘 함께한 이 과정을 통해 여러분은 이제 모바일 AI 앱 개발의 첫걸음을 성공적으로 떼셨습니다. Flutter와 TFLite라는 강력한 도구가 있으니, 이제 여러분의 상상력을 더해 세상에 없던 새로운 앱을 만들어볼 차례입니다.

처음에는 수많은 오류와 마주치고, 원하는 대로 동작하지 않아 답답할 때도 있을 겁니다. 하지만 그 과정 하나하나가 여러분을 더 뛰어난 개발자로 만들어 줄 소중한 경험이 될 거라고 확신합니다. 이 글이 여러분의 멋진 도전에 작은 불씨가 되었기를 바라며, 즐거운 코딩 여정을 응원하겠습니다

↗Share this article