안드로이드 프레임워크·시스템 학습 노트 목차

4대 컴포넌트 — Intent·Service·BroadcastReceiver·ContentProvider

OS가 알아보는 빌딩 블록

보통의 프로그램은 main() 하나로 시작해 내가 흐름을 통제한다. 안드로이드 앱은 다르다 — 진입점이 여럿이고, 그 진입점을 OS가 부른다. 사용자가 런처에서 아이콘을 누르면 OS가 Activity를 띄우고, 알림을 누르면 다른 Activity가 열리고, 다른 앱이 "이 데이터 좀 줘" 하면 내 ContentProvider가 불린다. 즉 안드로이드 앱은 *"OS가 필요할 때 부를 수 있는 부품들의 모음"*이다.

그 부품이 4대 컴포넌트Activity·Service·BroadcastReceiver·ContentProvider다. 이들의 공통점은 — 모두 AndroidManifest.xml에 등록되어 OS가 그 존재를 알고, Intent라는 메시지로 서로(그리고 다른 앱과) 통신한다는 것이다. 이 모델 덕에 앱끼리 기능을 공유(공유 시트로 사진을 다른 앱에 보내기)하고 OS가 앱을 깨운다(부팅 완료를 알려 알람 앱을 깨우기). (출처: Android — Application fundamentals / Intents.)

다이어그램 로딩 중…

Intent — 컴포넌트를 잇는 메시지

컴포넌트끼리 직접 함수를 부르는 대신, 안드로이드는 Intent라는 "무엇을 해달라"는 메시지 객체로 통신한다. Intent에는 두 종류가 있고, 이 구분이 핵심이다.

명시적(explicit) Intent대상 컴포넌트를 클래스로 직접 지정한다 — 내 앱 안에서 화면을 이동할 때다. 암시적(implicit) Intent대상을 지정하지 않고 "동작(action)"만 선언해 — 그 동작을 처리할 수 있는 앱을 OS가 찾아 준다(URL 열기, 사진 공유, 지도 보기). 암시적 Intent가 바로 앱끼리 기능을 빌려 쓰는 통로다.

// 명시적 — 내 앱의 특정 화면을 직접 지목
startActivity(Intent(this, DetailActivity::class.java).apply { putExtra("id", 42) })

// 암시적 — "이 URL을 열 수 있는 앱"을 OS가 찾아 띄움 (브라우저든 뭐든)
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com")))

데이터는 putExtra로 Bundle에 실어 보낸다. 한 가지 진화 — 예전엔 다른 화면의 결과를 onActivityResult 받았지만, 현대엔 *Activity Result API(registerForActivityResult)*로 타입 안전하게 받는다(사진 선택·권한 요청 결과 등).

Activity — 화면 하나

Activity사용자와 상호작용하는 화면 하나다([01 생명주기]에서 그 일생을 다뤘다). 앱의 진입점이 되며, 열린 Activity들은 백스택에 쌓여 뒤로 가기로 하나씩 닫힌다. 같은 화면이 중복으로 쌓이거나(알림을 여러 번 눌러 상세 화면이 여러 개) 로그인 후 로그인 화면이 백스택에 남는 문제가 생기면 — launchMode(standard/singleTop/singleTask/singleInstance)나 Intent flags로 스택 동작을 조절한다. 예를 들어 singleTop대상이 이미 스택 맨 위면 새로 만들지 않고 재사용해 중복을 막는다.

Service — 화면 없는 백그라운드, 그러나 제한된다

ServiceUI 없이 백그라운드에서 도는 컴포넌트다. 그런데 현대 안드로이드의 가장 큰 변화가 여기 있다 — 배터리를 지키려고 백그라운드 실행을 강하게 제한한 것이다. 그래서 "그냥 Service를 띄워 백그라운드 스레드를 계속 돌리는" 옛 방식은 OS가 곧 죽인다. 현대엔 백그라운드 작업을 성격에 따라 셋으로 나눠 처리한다.

다이어그램 로딩 중…
  • 포그라운드 서비스(foreground service)사용자가 인지하는 지속 작업(음악 재생·내비게이션·운동 추적). 지속 알림 표시가 필수이고, Android 14+는 서비스 타입 선언도 요구한다 — "사용자가 보는 앞에서 도는 일"임을 OS에 알리는 것이다.
  • 지연 가능·보장 작업은 Service가 아니라 WorkManager([07])를 쓴다 — Doze·백그라운드 제한을 알아서 다루고 앱이 죽거나 재부팅돼도 실행을 보장한다.
  • bound service — 다른 컴포넌트가 바인딩해 직접 메서드를 호출(IPC, AIDL로 프로세스 간).

핵심 정리 — *"백그라운드에서 오래 돌리고 싶다"*는 욕구는 거의 항상 WorkManager(지연 가능·보장)·포그라운드 서비스(즉시·사용자 인지)·코루틴(화면 동안만) 중 하나로 풀린다.

BroadcastReceiver — 시스템·앱 이벤트를 받는다

BroadcastReceiver시스템이나 앱이 뿌리는 방송(broadcast)을 받는 컴포넌트다 — 부팅 완료, 충전 시작, 네트워크 변경, 배터리 부족 같은 전역 이벤트에 반응한다. 두 가지 주의가 있다. 첫째, onReceive는 아주 짧아야 한다 — 메인 스레드에서 잠깐 불리는 것이라 여기서 오래 일하면 ANR이 난다(긴 작업은 WorkManager로 넘긴다). 둘째, 배터리 보호를 위해 매니페스트 등록 방식의 암시적 방송 수신이 크게 제한되어, 현대엔 *런타임 등록(context-registered)*이나 명시적 방송을 주로 쓴다.

val receiver = object : BroadcastReceiver() {
    override fun onReceive(c: Context, i: Intent) {
        // ★ 아주 짧게. 긴 일은 WorkManager로 넘긴다 (여기서 오래 끌면 ANR)
    }
}
registerReceiver(receiver, IntentFilter(Intent.ACTION_BATTERY_LOW))   // 런타임 등록
// 안 쓸 땐 unregisterReceiver — 누수 방지

ContentProvider — 앱 경계 너머 데이터 공유

ContentProvider구조화된 데이터를 앱의 경계 너머로 공유하는 표준 인터페이스다(content:// URI로 접근). 안드로이드의 연락처·미디어·캘린더가 모두 ContentProvider로 노출되어 — 다른 앱이 권한만 있으면 통일된 방식으로 질의할 수 있다. 한 가지 흔한 오해 — 내 앱 내부 데이터엔 ContentProvider가 필요 없다. 내부 저장은 Room을 직접 쓰는 게 간단하고, ContentProvider는 다른 앱과 데이터를 주고받거나(연락처 읽기) 시스템과 통합(검색·위젯·자동완성)할 때 쓴다.

정리 — OS가 부를 수 있는 부품들

4대 컴포넌트는 *"OS가 필요할 때 부르는 진입점들"*이다. Activity(화면, 백스택·launchMode), Service(백그라운드 — 현대엔 포그라운드 서비스/WorkManager로 갈린다), BroadcastReceiver(전역 이벤트 — 짧게, 긴 일은 WorkManager), ContentProvider(앱 간 데이터 공유 — 내부엔 Room). 이들을 잇는 게 Intent(명시=대상 지정, 암시=동작으로 OS가 앱 탐색)다. 모두 매니페스트에 등록되어야 OS가 알아본다. 백그라운드 제한이 강해진 게 현대 안드로이드의 핵심 변화이고, 그래서 *"어떤 백그라운드 작업이냐"*를 먼저 분류하는 사고가 중요하다.

한 줄 요약 — 4대 컴포넌트(매니페스트 등록·OS가 부르는 진입점): Activity(화면·백스택·launchMode)·Service(백그라운드→포그라운드 서비스(알림)/WorkManager(지연·보장)/코루틴(화면 동안))·BroadcastReceiver(전역 이벤트·onReceive 짧게)·ContentProvider(앱 간 데이터, 내부엔 Room). 통신은 Intent(명시=대상 지정, 암시=action으로 OS 탐색)·putExtra·Activity Result API.

(출처: Android — App fundamentals / Intents & filters / Services / Broadcasts / Content providers / Background work overview.)

생명주기 — Activity·Fragment·생명주기 인지Jetpack Compose 기초 — 선언형·recomposition