유튜브로 부분부분 공부하는 건 한계가 있는 거 같아서 결국 책 구입..
이론부터 잡고 가야겠다고 결심함
1. 앱 개발 워크플로

💡 딥러닝 모델 개발 프로세스
- 파이썬과 텐서플로를 이용하여 모델를 설계하고 훈련
- 모델이 개발되면 모바일에서 사용 가능하도록 텐서플로 라이트 모델로 변환하여 저장
👉 딥러닝 모델 개발 단계의 최종 산출물은 텐서플로 라이트 모델을 파일로 저장한 tflite 파일
💡 안드로이드 앱 개발 프로세스
tflite 파일이 생성되면 안드로이드 앱 개발 환경에서 안드로이드 앱의 UI와 비즈니스 로직을 개발
- UI 개발 단계에서는 사용자에게 보여줄 화면을 개발하고 화면에서 발생하는 이벤트를 비즈니스 로직과 연결
- 비즈니스 로직 개발 단계에서는 UI로부터 전달받은 이벤트를 처리하고, 딥러닝 모델을 불러와 데이터 입력 및 추론 결과 처리 로직을 구현
👉 앱 개발 단계의 최종 산출물은 안드로이드 기기에 직접 설치되는 앱의 설치 파일인 apk 파일
💡 이렇게 개발된 앱은 사용자로부터 데이터를 입력받아 딥러닝 모델로 추론하여 결과를 활용하는 서비스를 제공
💡 각 개발 프로세스는 일정 수준까지 병행하여 진행 가능
- ex) 안드로이드 앱의 UI 개발과 데이터 생성 로직 개발은 딥러닝 모델 개발 프로세스와 병행 가능
👉 앱에서 모델을 불러와 추론하는 부분을 구현하기 전까지만 딥러닝 모델을 완성하면 됨
2. 모바일 환경에서의 딥러닝
- 딥러닝 모델은 강력한 컴퓨팅 자원을 필요로 하지만, 안드로이드는 주로 모바일 환경에서 동작하기 때문에 디바이스에서 가용한 컴퓨팅 자원이 제한적
👉 서버 기반 아키텍처 사용 : 딥러닝 추론 결과를 안드로이드 앱에서 이용하기 위해 서버에 데이터를 보내고 추론 결과를 받아서 활용

- but, 최근 안드로이드는 서버를 통하지 않고 기기에서 직접 모델을 동작시키는 온디바이스 AI를 위한 아키텍처와 컴퓨팅 파워를 갖춰가고 있음

- 또한, 텐서플로는 모바일과 IoT에 특화된 딥러닝 프레임워크인 텐서플로 라이트를 공개하여 안드로이드의
On-Device AI 개발 환경을 더욱 개선해나가고 있음
3. 안드로이드의 구성 요소
- 4대 구성 요소 : 액티비티(Activity), 서비스(Service), 콘텐트 프로바이더(Content Provider, CP), 브로드캐스트 리시버(Broadcast Receiver, BR)
- 이 네 가지 구성 요소는 인텐트(Intent)를 이용하여 상호 작용
3-1. 액티비티
- 안드로이드에서 가장 중요한 구성 요소
- 사용자에게 보이는 화면 UI를 담당
- 모든 안드로이드 앱은 적어도 하나의 액티비티를 가지고 있으며, 앱을 실행하면 지정된 액티비티의 코드가 생명주기에 맞추어 호출
👉 안드로이드 앱을 개발할 때에는 액티비티의 생명주기를 알고 그에 맞게 코드를 작성하는 것이 중요!!
- 6단계의 생명주기
: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy() => 콜백 함수

- 액티비티가 시작되면 맨 먼저 onCreate() 함수가 호출
- 콜백 함수는 필요할 때만 오버라이딩하여 구현하면 되지만, onCreate() 함수를 구현하지 않는 경우는 거의 없음
- onCreate()는 처음 한 번만 호출되므로 여기에는 일반적으로 액티비티와 UI 구성 요소를 연결하고 초기화하는 로직을 구현
- onCreate()가 완료되면 다음으로 onStart()가 호출되고 액티비티가 기기 화면에 나타남
- 이때 앱은 액티비티를 화면에 띄우고 상호 작용을 준비
- onStart()는 onCreate()가 종료되었을 때뿐만 아니라, onStop() 상태에서 onRestart()가 호출되었을 때, 즉 액티비티가 멈춘 뒤 다시 시작할 때도 호출됨
- onStart()가 완료되면 시스템은 onResume()을 호출하며, onResume() 상태에서는 사용자와 앱의 상호 작용이 가능
- onResume()에서는 앱이 전면에 표시되어 동작하는 동안 실행할 기능을 활성화
- onResume() 상태에서 전화가 오거나 다른 액티비티를 실행하는 등 액티비티가 포커스를 잃은 경우 또는 기기의 화면을 끄는 경우 onPause()가 호출
- onPause()는 onResume()과 짝꿍!
- onPause()에서는 onResume()로 활성화한 동작을 중지할 수 있음
- onPause() 상태에서 앱이 다시 포커스를 받으면 onResume() 상태로 돌아감
- 액티비티가 더 이상 화면에 표시되지 않으면 onPause()를 거쳐 onStop() 호출
- onStop()은 onStart()와 짝꿍!
- onStart()에서 할당했던 리소스를 초기화하거나 파일, DB, 네트워크 등에 데이터를 저장하는 동작을 구현
- onDestroy() 호출
- onStop()이 호출되어도 액티비티는 메모리에서 즉각 해제되지 않고 여전히 남아있음
- 사용자가 액티비티를 완전히 종료하거나 액티비티의 finish() 함수를 호출한 경우 또는 시스템이 액티비티를 소멸시킨 경우 액티비티가 소멸되면서 onDestroy()를 호출
- 액티비티 생명주기의 마지막 단계인 onDestroy()에서는 아직 해제되지 않은 모든 객체나 리소스를 해체하고 정리
3-2. 서비스
- 기기의 화면에 표시되지 않고 백그라운드에서 실행되는 작업을 처리하는 구성 요소
👉 네트워크를 이용한 데이터 송수신, 음원 재생, 대용량 파일 입출력 등 시간이 오래 걸리는 것들
- 이러한 작업이 백그라운드에서 처리되지 않으면, 안드로이드 운영체제는 ANR(Application Not Responding) 오류를 발생시키고, 시스템은 사용자에게 애플리케이션이 응답하지 않는다는 메시지를 보여줌
- 서비스는 기본적으로 메인 스레드에서 동작하며, 앱의 실행 여부와 관계없이 동작 가능
- 유형
-> 백그라운드(background), 포그라운드(foreground), 바인드(bind)
1. 백그라운드 서비스 : 사용자에게 보이지 않는 서비스로, UI와 상관없는 작업을 처리할 때 사용
2. 포그라운드 서비스 : UI를 표시할 필요가 있을 때 사용, 상태 바 처리나 알림 등 서비스에서 동작하더라도 UI가 필요한 작업
3. 바인드 : 클라이언트-서버 아키텍처를 제공하는 서비스, 서비스가 서버 역할을 하고 서비스를 바인딩한 구성 요소가 클라이언트 역할을 함
👉 바인드 서비스를 이용하면 서로 다른 프로세스 간에도 데이터를 주고받을 수 있어 프로세스 간 통신(Inter Process Communication, IPC)의 수단으로도 쓰임

💡 startService() 호출
- 처음 한 번은 서비스가 생성되면서 onCreate() 호출
- onCreate()가 완료되었거나 두 번째로 startService()를 호출하면 onStartCommand()가 호출
- 서비스가 종료되면 onDestroy()가 호출
💡 bindService() 호출
- 서비스 바인딩이 완료되면 onStartCommand() 대신 onBind() 호출
- 모든 클라이언트의 연결이 해제되면 onUnbind() 호출
- 서비스의 시작과 종료 시에 각각 onCreate(), onDestroy()가 호출되는 것은 일반 서비스와 동일
3-3. 콘텐트 프로바이더
- CP라고도 일컫는 콘텐트 프로바이더는 외부에 데이터를 제공하는 역할을 함
- 주로 앱 내에서 생성하거나 관리하는 데이터를 다른 앱에 제공하는 기능을 표준화
SQLite처럼 구조화된 관계형 데이터베이스를 공유하거나 이미지, 음악 파일처럼 비구조화된 데이터를 공유
- 콘텐트 프로바이더를 구현하면 앱 내부 데이터를 외부에 공유할 수 있고, 다른 앱의 콘텐트 프로바이더를 호출하여 해당 앱의 데이터에 접근하거나 읽고 쓸 수 있음
- ex) 연락처의 콘텐트 프로바이더를 통해 앱의 저장된 연락처 받아오기
미디어 콘텐트 프로바이더를 통해 저장된 사진이나 비디오 등 얻어오기
- 콘텐트 프로바이더를 이용하면 데이터 접근 권한을 상세히 관리할 수 있어 보안과 데이터 관리에도 유용
- 내/외부 저장소에 따라 권한을 달리 부여할 수도 있고, 읽기/쓰기 등 접근 수준을 다르게 설정할 수도 있음
- 쿼리를 기반으로 하기 때문에 데이터의 유형이나 세부 구현에 의존적이지 않도록 비동기식으로 데이터에 접근할 수 있음
3-4. 브로드캐스트 리시버
- 브로드캐스팅된 메시지를 받는 수신자
- 브로드캐스팅은 이벤트 기반 아키텍처(EDA)인 발행-구독 패턴과 유사
- 발행-구독 패턴은 발행자(publisher)와 구독자(subscriber), 이벤트 관리자(event broker)로 구성
- 발행자는 정보를 담은 이벤트를 발행하고, 구독자는 원하는 이벤트를 받아서 처리하며, 이벤트 관리자는 중간에서 이벤트를 수신 및 전달하는 메시지 큐 역할을 함
- 발행-구독 패턴은 발행자와 구독자가 느슨하게 결합되며(loosely-coupled) 비동기로 동작하기 때문에 널리 사용되고 있음
- 브로드캐스트 리시버는 구독자 역할을 하고, 인텐트는 메시지가 되며, 이벤트 관리자는 안드로이드 운영체제가 담당
- 브로드캐스팅을 이용하면 발행자는 알리고 싶은 이벤트가 발생했을 때 원하는 정보를 인텐트에 담아 불특정 다수 또는 특정 패키지를 지정하여 보낼 수 있음
- 구독자는 원하는 메시지 필터를 미리 등록하여 브로드캐스팅된 메시지 가운데 원하는 것을 골라서 수신할 수 있음
- 대상 패키지의 지정 여부에 따라 명시적 브로드캐스팅, 암시적 브로드캐스팅으로 구분
- 명시적 브로드캐스팅 : 발행자가 브로드캐스트를 요청할 때부터 어떤 패키지에 브로드캐스팅할지를 지정하며, 발행자가 지정하지 않은 패키지는 인텐트 받을 수 없음
- 암시적 브로드캐스팅 : 모든 패키지를 대상으로 브로드캐스팅하므로 발행자가 패키지를 지정하지 않고 모든 패키지가 인텐트 받을 수 있음
- 안드로이드 매니페스트를 이용하는 정적인 방법
- 안드로이드 매니페스트는 앱에서 사용할 권한, 서비스, 액티비티 등을 선언하는
xml로 작성된 설정 파일
- 코드상에서 컨텍스트에 수신하고자 하는 인텐트를 등록하는 방식
3-5. 인텐트
- 구성 요소 간의 정보 전달을 위한 메시지 역할
- 액티비티에서 다른 액티비티로 전환하거나, 서비스를 구동하거나, 브로드캐스팅을 통해 다른 앱에 메시지를 전달하는 등 다양한 역할을 함
- 인텐트는 컴포넌트 이름, 액션, 데이터, 카테고리, 엑스트라, 플래그로 이루어져 있음
| 구성 요소 | 역할 |
|---|
| 컴포넌트 이름 | 인텐트를 전달할 대상 지정(컨텍스트 + 대상 클래스) |
| 액션 | 인텐트를 통해 어떤 작업을 수행할지 전달(String) |
| 데이터 | 인텐트가 가지고 있는 데이터(Uri) |
| 카테고리 | 인텐트의 종류 구분(String) |
| 엑스트라 | 인텐트 처리에 필요한 데이터(key-value) |
| 플래그 | 인텐트의 메타 데이터(int) |
- 인텐트를 사용하는 데 이러한 여섯 가지 정보가 모두 필요한 것은 아님!
- 용도에 맞게 필요한 정보만 채워서 사용하면 됨
💡 출처
텐서플로 라이트를 활용한 안드로이드 딥러닝, 임태규, 한빛미디어
