Intent에 대해 알아보자.

이윤설·2024년 12월 22일
0

안드로이드 연구소

목록 보기
16/33

Intent란?

안드로이드의 애플리케이션 구성은 4대 컴포넌트로 이루어져 있다.

4대 컴포넌트

  1. 액티비티(Activity): 화면 전환과 UI 관리, 최근 Compose에서는 단일 액티비티에서 여러 화면을 구성하는 것이 일반적.

  2. 서비스(Service): 백그라운드에서 작업을 수행, UI와 독립적으로 데이터 동기화나 긴 작업을 처리.

  3. 브로드캐스트 리시버(Broadcast Receiver): 시스템 이벤트나 다른 앱에서 발생한 메시지를 수신하고 처리, UI와 분리된 상태에서 이벤트 처리.

  4. 컨텐트 프로바이더(Content Provider): 앱 간 데이터 공유를 처리, 다른 앱에서 데이터를 가져오거나 제공하는 데 사용.

-> 이 각각의 컴포넌트간의 통신을 맡고 있는 것이 Intent(인텐트)다.


유튜브 예시

  1. 액티비티 (Activity): 앱의 진입점, 네비게이션 호스트, 권한 요청 또는 특수 작업 처리 등

  2. 서비스 (Service): 유튜브 앱에서 백그라운드 작업을 처리한다. 예를 들어, 동영상 다운로드나 푸시 알림 전송을 담당한다.

  3. 브로드캐스트 리시버 (Broadcast Receiver): 시스템 이벤트를 수신하여 앱 내 동작을 변경한다. 예를 들어, 네트워크 상태 변경이나 배터리 상태 변화에 반응하여 동작을 조정한다.

  4. 컨텐트 프로바이더 (Content Provider): 앱 간 데이터 공유를 담당한다. 예를 들어, 유튜브 동영상을 다른 앱과 공유하거나 다른 앱에서 댓글을 가져오는 데 사용된다.


Intent의 주요 종류

1. 명시적(Intent Explicit)

시작하려는 컴포넌트를 명확히 지정한다. 주로 내부 컴포넌트 간 통신에 사용된다.

예: 특정 Activity를 시작할 때.

val intent = Intent(this, TargetActivity::class.java)
startActivity(intent)

2. 암시적(Intent Implicit)

작업의 목적만 정의하고, 이를 처리할 수 있는 앱을 시스템이 선택하도록 맡긴다.
예: 웹 브라우저에서 URL 열기.

val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.google.com"))
startActivity(intent)

현대 Jetpack Compose 개발방식에서의 Intent

하지만 위 정의와는 다르게도,
Jetpack Compose에서는 전통적인 Android View 시스템에서 사용하던 Intent 기반 통신을 많이 사용하지 않는다.

앱 내부 통신은 Compose의 선언적 UI 패턴과 더 잘 맞는 State, ViewModel, Navigation 등을 사용하고, 외부 시스템이나 앱과의 통신에만 Intent를 사용하는 것이 현대적인 Android 개발 방식이다.

1. Navigation Component

// 화면 간 이동과 데이터 전달
NavHost(navController, startDestination = "home") {
    composable("home") { HomeScreen(navController) }
    composable("detail/{itemId}") { backStackEntry ->
        val itemId = backStackEntry.arguments?.getString("itemId")
        DetailScreen(itemId)
    }
}

// 화면 이동
navController.navigate("detail/${item.id}")

2. ViewModel과 State

class MainViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(MainUiState())
    val uiState = _uiState.asStateFlow()

    fun updateData() {
        _uiState.update { ... }
    }
}

@Composable
fun MainScreen(viewModel: MainViewModel) {
    val uiState by viewModel.uiState.collectAsState()
    // UI 업데이트
}

3. 공유된 ViewModel

// 여러 화면에서 동일한 ViewModel을 공유
class SharedViewModel : ViewModel() {
    private val _data = MutableStateFlow<Data>()
    val data = _data.asStateFlow()
}

@Composable
fun Screen1(sharedViewModel: SharedViewModel) {
    val data by sharedViewModel.data.collectAsState()
}

@Composable
fun Screen2(sharedViewModel: SharedViewModel) {
    val data by sharedViewModel.data.collectAsState()
}

궁금증

1. 예를 들어, 전화 걸기나 공유 같은 행위는 Intent를 사용해야 하잖아. 그럼 하나의 전화 걸때 앱에 Activitiy가 생겼다가 전화를 끊으면 없어지는걸까?

  • 새로운 Activity가 생성되긴 하지만, 이는 안드로이드 시스템이나 다른 앱(예: 전화 앱, 카카오톡 등)의 Activity다.

예를 들어 공유하기를 눌렀을 때:

우리 앱의 Activity → 시스템의 Chooser Activity(공유 대상 선택 화면) → 선택된 앱의 Activity 작업이 완료되면 다시 우리 앱의 Activity로 돌아옴

이때 우리 앱의 원래 Activity는 백그라운드로 갔다가 다시 포그라운드로 돌아오는 생명주기를 거침. 참고로 포그라운드에서 실행되는 프로세스는 사용자와 상호 작용하는 프로세스이다.
onPause() → onStop() → onRestart() → onStart() → onResume()

2. Intent란, 액티비티, 서비스, 브로드캐스트 리시버, 콘텐츠 프로바이더 각각의 통신을 담당한다고 하는데, 그럼 공유하기 기능은 누구와 누구 간의 통신일까?

공유하기 기능은 보통 우리 앱(소스 앱)과 공유 대상 앱(목적지 앱) 간의 통신이다. 이 경우, Intent는 다음 역할을 한다.

Intent의 통신 구조

  1. 소스 앱 (우리 앱):
    공유하려는 데이터를 Intent에 담아서 시스템에 요청한다.
    ex: "이 텍스트를 공유 가능한 앱에게 전달해 주세요."

  2. Android 시스템:
    Intent를 받아서, 공유 기능을 처리할 수 있는 앱들을 확인한다. (이를 Implicit Intent라고 함.)

    예: 메시지 앱, 이메일 앱, 소셜 미디어 앱 등이 공유를 처리할 수 있는 앱 목록으로 표시된다.

  3. 목적지 앱 (공유 대상 앱):
    사용자가 선택한 앱이 Intent를 받아 데이터를 처리한다.

    예: 사용자가 메시지 앱을 선택하면, Intent에 담긴 텍스트를 메시지 작성 화면에 표시한다.

3. 그럼 내부 컴포넌트 간에 Intent 통신은 거의 안했으니까 자동적으로 최근에는 명시적 인텐트는 덜 쓰고 임시적 인텐트(외부 앱과 통신하는 것은 예전과 그대로이므로)를 많이 쓰는것일까?

정확하다.

  1. 명시적 인텐트(Explicit Intent) 사용 감소
  • 이전: Activity 간 데이터 전달, Service 시작 등 내부 통신에 많이 사용
  • 현재: Jetpack Compose에서는 ViewModel, State, Navigation Component로 대체
  1. 암시적 인텐트(Implicit Intent) 사용은 유지
  • 이전/현재 모두 동일하게 사용

  • 주요 사용 사례:

    // 전화 걸기
    Intent(Intent.ACTION_DIAL, Uri.parse("tel:$phoneNumber"))
    
    // 공유하기
    Intent(Intent.ACTION_SEND)
    
    // 웹 브라우저 열기
    Intent(Intent.ACTION_VIEW, Uri.parse(url))
    
    // 갤러리에서 이미지 선택
    Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)

이러한 변화가 일어난 이유:
1. 단방향 데이터 흐름(Unidirectional Data Flow) 패턴의 보편화
2. 상태 관리의 중요성 증가
3. 컴포넌트 간 결합도를 낮추기 위한 아키텍처 진화

4. 우리 앱에서 "메시지"라는 텍스트를 Intent를 통해 카카오톡 간에 공유하려고 해. 그럼 "메시지"가 Intent야? 그럼 Intent는 택배박스 같은거야? 만약 공유 성공 후에는 우리 앱의 Activity, 카카오톡의 Activity, Intent는 소멸돼?

"메시지"가 Intent인가요?

아니요, "메시지"는 Intent가 아니 다.
"메시지"는 Intent에 담긴 데이터에 불과하다.

Intent는 우리가 공유하려는 "메시지"를 담고, Android 시스템과 다른 앱에게 전달하는 택배박스 같은 역할을 한다. 택배박스에는 데이터를 담을 수 있고, 어떤 앱(수신자)에게 전달해야 하는지 주소를 설정할 수도 있다.

val shareIntent = Intent(Intent.ACTION_SEND).apply {
    type = "text/plain" // 박스에 들어갈 데이터의 타입 (여기선 텍스트)
    putExtra(Intent.EXTRA_TEXT, "메시지") // 박스 안에 담긴 데이터
}
startActivity(Intent.createChooser(shareIntent, "앱을 선택하세요"))
  • 택배박스 = Intent
  • 박스 안에 담긴 내용물 = "메시지" 같은 데이터
  • 배송지 = 어떤 앱(카카오톡)에서 처리할지
  • Android 시스템 = 택배 회사 (어떤 앱으로 데이터를 전달할지 중개)

공유 성공 후에는 Activity와 Intent는 어떻게 되나요?

1. Intent는 소멸된다.
  • Intent는 데이터를 전달하기 위해 사용되며, 데이터를 전달한 후에는 더 이상 필요가 없어지고 메모리에서 사라진다.
  • 즉, 택배박스(Intent)는 데이터를 수신 앱(카카오톡)에게 넘겨준 뒤 소멸된다.
2. 우리 앱의 Activity는 유지됩니다.
  • 공유 과정 중, 우리 앱(MainActivity 등)은 백그라운드로 이동한다.
    • 사용자가 공유 작업을 마친 뒤, 백 버튼을 누르면 다시 돌아온다.
    • 우리 앱의 Activity는 종료되지 않는다.
3. 카카오톡의 Activity는 유지될 수도 있고 종료될 수도 있다.
  • 카카오톡 앱이 열리고, 사용자가 데이터를 확인하거나 공유 작업을 진행한다.
  • 사용자가 공유를 마치고 앱을 닫거나, 다른 작업으로 넘어가면 카카오톡의 Activity는 종료될 수 있다.
  • 하지만, 백그라운드에서 유지될 가능성도 있다. (안드로이드 시스템에 따라 결정됨)
profile
화려한 외면이 아닌 단단한 내면

0개의 댓글

관련 채용 정보