사전 인텐트
용어함정

인텐트

gabury1고친 사람 github-actions[bot]

인텐트는 안드로이드 앱이 다른 화면이나 기능을 열어 달라고 운영체제에 보내는 부탁입니다. 앱은 상대 앱의 코드를 직접 부르지 않고 이 부탁만 건넵니다. 받을 곳은 운영체제가 찾아서 이어 줍니다. 챗봇 분야에서는 사용자의 말이 원하는 목적을 같은 이름으로 부릅니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 안드로이드 앱이 「이 일을 해 줄 곳을 찾아 달라」고 운영체제에 건네는 쪽지입니다. 메모 앱에서 공유 버튼을 누르면 「이 글을 보내고 싶다」는 인텐트가 나갑니다. 챗봇에서는 「내일 비 와?」라는 말을 「날씨 묻기」로 분류한 이름을 인텐트라고 부릅니다.

왜 이렇게 하나 — 안드로이드 앱은 서로 벽으로 막혀 있어서 남의 앱 코드를 부를 수 없습니다. 게다가 폰마다 깔린 앱이 달라서 보내는 쪽은 누가 받을지 미리 모릅니다. 그래서 하고 싶은 일만 적어 보냅니다. 받을 앱은 운영체제가 고릅니다.

어떻게 도나

  1. 보내는 앱이 하고 싶은 일과 넘길 값을 인텐트에 담아 운영체제에 건넵니다
  2. 운영체제가 그 일을 받겠다고 미리 신고해 둔 앱을 찾습니다. 받을 곳을 이름으로 집어 보냈으면 찾지 않고 그곳을 바로 띄웁니다. 내 앱 안에서 화면을 넘길 때는 대개 이쪽입니다
  3. 찾은 앱의 화면이나 기능을 띄우고 인텐트를 넘겨줍니다

대가 — 받을 앱이 하나도 없으면 보낸 앱이 죽을 수 있습니다. 값을 문자열 이름표로 넘기므로 이름표를 틀려도 빌드할 때 안 잡힙니다.

상세

이 절은 「인텐트」의 두 뜻을 먼저 표로 가릅니다. 그다음 안드로이드의 인텐트를 코드 몇 줄과 흐름 그림 하나로 펼칩니다. 챗봇의 인텐트는 끝에서 짧게 짚습니다.

인텐트가 가리키는 두 가지

「인텐트」는 영어 intent, 곧 「의도」를 옮긴 이름입니다. 두 분야가 이 낱말을 따로 가져다 써서 뜻이 둘로 갈립니다.

맥락 인텐트 하나가 가리키는 것 예
안드로이드 앱 다른 화면이나 기능을 열어 달라는 요청 객체 메모를 공유하겠다는 요청
챗봇 · 음성 비서 사용자의 말이 원하는 목적에 붙인 분류 이름 「내일 비 와?」 → 날씨 묻기

두 뜻은 쓰이는 분야가 다르고 기술로도 이어지지 않습니다. 안드로이드 앱의 구조를 다루는 글에서 만나는 것은 첫째 뜻입니다.

안드로이드의 인텐트

인텐트는 앱의 부품을 깨울 때 운영체제에 건네는 요청입니다. 「이 부품을 시작해 달라」가 요청의 뼈대입니다. 이 소절은 인텐트가 깨우는 그 부품부터 봅니다.

안드로이드 앱은 운영체제가 알아보고 직접 띄우는 부품 몇 가지로 조립됩니다. 이 부품을 앱 컴포넌트라고 부릅니다. 부품 객체는 앱이 아니라 운영체제가 만듭니다. 그래서 앱은 new 로 부품을 만들지 않고 인텐트를 보냅니다.

화면 한 장을 맡는 액티비티가 대표적인 앱 컴포넌트입니다. 메일 목록 화면과 메일 읽기 화면이 각각 액티비티 하나입니다. 화면이 없는 나머지 부품 둘은 뒤의 「인텐트를 보내는 세 호출」에서 봅니다.

인텐트가 필요한 까닭

백엔드 서버에서는 다른 모듈의 기능이 필요하면 그 클래스를 가져와 메서드를 부르면 됩니다. 같은 프로세스 안이라 가능한 일입니다.

안드로이드에서는 앱마다 따로 된 프로세스에서 돕니다. 게다가 샌드박스가 앱들을 서로 떼어 놓습니다. 남의 앱 메모리나 파일에 손댈 수 없으니 카메라 앱의 코드를 내 앱이 직접 부를 길이 없습니다.

그래서 운영체제가 가운데 섭니다. 앱은 운영체제에 인텐트를 건넵니다. 운영체제는 받을 앱을 깨워 그 인텐트를 넘겨줍니다.

서로 다른 프로세스끼리 이렇게 데이터를 주고받는 일을 IPC(Inter-Process Communication, 프로세스 간 통신)라고 부릅니다. 앱이 운영체제에 인텐트를 건네는 일도 IPC 입니다.

까닭이 하나 더 있습니다. 폰마다 깔린 앱이 다릅니다. 글을 메신저로 보내고 싶어도, 이 폰에 어느 메신저가 깔려 있는지 보내는 앱은 모릅니다. 뒤에 나올 암시적 인텐트가 이 문제를 풉니다.

인텐트에 담기는 것

인텐트는 요청 한 건을 담는 객체입니다. 담을 수 있는 칸은 다섯입니다. 어느 칸을 채우느냐에 따라 받을 곳이 정해지는 방식이 달라집니다.

칸 담는 것 예
대상 컴포넌트(클래스) 깨울 클래스 이름 MailActivity
액션 하고 싶은 일 보기 ACTION_VIEW · 보내기 ACTION_SEND
데이터 일의 대상이 되는 주소와 그 종류 웹 주소 · text/plain
카테고리 받을 곳의 성격을 좁히는 꼬리표 웹 링크로 열려도 되는 화면 CATEGORY_BROWSABLE
엑스트라 함께 넘길 값. 이름표를 붙인 키-값 쌍 이름표 mailId 에 값 42

데이터 칸의 주소는 URI(Uniform Resource Identifier, 자원 식별자) 꼴로 적습니다. 웹 주소나 tel: 로 시작하는 전화번호가 그런 주소입니다.

데이터의 종류는 MIME 타입(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장)으로 적습니다. MIME 타입은 text/plain 이나 image/png 처럼 데이터 형식을 가리키는 이름표입니다. 원래 이메일 첨부를 구분하려고 만든 표기라서 이런 이름이 붙었습니다.

카테고리는 받을 곳을 가르는 조건을 하나 더 겁니다. 인텐트에 붙은 카테고리는 받는 쪽이 신고해 둔 목록에도 전부 들어 있어야 합니다. CATEGORY_BROWSABLE 이 붙은 인텐트라면 웹 링크로 열려도 된다고 신고한 화면만 받습니다.

표의 첫 칸이 인텐트를 둘로 가릅니다. 대상 클래스를 채우면 명시적 인텐트입니다. 비워 두고 액션으로 부탁하면 암시적 인텐트입니다.

명시적 인텐트

명시적 인텐트는 대상 클래스를 이름으로 못 박은 인텐트입니다. 받을 곳이 이미 정해져 있으니 운영체제는 찾을 일 없이 그 클래스를 띄웁니다. 주로 내 앱 안에서 화면을 넘길 때 씁니다.

아래는 코틀린으로 쓴 코드입니다. 메일 목록 화면에서 메일 읽기 화면을 여는 장면입니다.

Kotlin
val intent = Intent(this, MailActivity::class.java)
intent.putExtra("mailId", 42L)
startActivity(intent)

첫 줄이 대상 클래스 칸에 MailActivity 를 적습니다. this 는 인텐트를 보내는 지금 화면입니다. 둘째 줄은 엑스트라 칸에 "mailId" 라는 이름표로 값 42 를 넣습니다. 셋째 줄의 startActivity 가 이 인텐트를 운영체제에 넘깁니다.

받는 화면은 자기를 띄운 인텐트를 intent 로 꺼내 봅니다. 값은 넣을 때 쓴 이름표로 찾습니다. 둘째 인자 -1L 은 그 이름표가 없을 때 돌려받을 기본값입니다.

Kotlin
intent.getLongExtra("mailId", -1L) // 42
intent.getLongExtra("mailid", -1L) // -1

둘째 줄은 이름표의 대문자 하나를 소문자로 틀렸습니다. 그래도 빌드는 통과합니다. 실행하면 기본값 -1 이 나옵니다. 이름표가 그냥 문자열이라 컴파일러가 틀린 것을 알아채지 못합니다.

암시적 인텐트

암시적 인텐트는 대상 클래스를 비워 두고 하고 싶은 일만 적은 인텐트입니다. 「이 글을 보내고 싶다」처럼 액션과 데이터를 채웁니다. 넘길 값은 엑스트라에 담습니다. 누가 받을지는 운영체제가 고릅니다.

Kotlin
val send = Intent(Intent.ACTION_SEND)
send.type = "text/plain"
send.putExtra(Intent.EXTRA_TEXT, "안녕")
startActivity(send)

메모 앱에서 공유 버튼을 누르면 이런 인텐트가 나갑니다. 액션은 보내기입니다. 데이터 종류는 평범한 글(text/plain)입니다. 대상 클래스는 어디에도 없습니다.

엑스트라에는 보낼 글 「안녕」을 담았습니다. 이름표 Intent.EXTRA_TEXT 는 받는 앱도 알아보도록 안드로이드가 미리 정해 둔 공용 이름표입니다. 앞의 "mailId" 처럼 이름표를 지어 붙이면 남의 앱은 그 이름을 모릅니다.

인텐트 필터

암시적 인텐트를 받으려는 부품은 자기가 받을 수 있는 일을 미리 신고해 둡니다. 신고는 매니페스트에 적습니다. 매니페스트는 앱 꾸러미에 든 설정 파일입니다. 앱이 가진 부품 목록을 여기에 담습니다.

부품마다 「이런 인텐트라면 받겠다」를 적은 선언을 인텐트 필터라고 부릅니다. 아래는 메신저 앱이 글쓰기 화면에 단 인텐트 필터입니다.

XML
<intent-filter>
    <action android:name="android.intent.action.SEND" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
</intent-filter>

보내기 액션이고 평범한 글이면 받겠다는 뜻입니다. startActivity 는 암시적 인텐트에 DEFAULT 카테고리를 저절로 붙여 보냅니다. 그래서 화면이 이 인텐트를 받으려면 필터에 DEFAULT 카테고리 줄을 함께 적어야 합니다.

받을 곳을 고르는 순서

운영체제는 암시적 인텐트를 받으면 깔린 앱들의 인텐트 필터를 훑습니다. 액션 · 카테고리 · 데이터가 모두 맞는 부품만 후보로 남깁니다. 그 뒤로는 후보 수에 따라 갈립니다.

flowchart TD
    B{"대상 클래스가 적혀 있나"}
    B -->|예| C["그 클래스를 띄운다"]
    B -->|아니오| D["인텐트 필터를 훑어 후보를 추린다"]
    D --> E{"후보가 몇인가"}
    E -->|하나| F["그 부품을 띄운다"]
    E -->|여럿| G["사용자에게 고르게 한다"]
    E -->|없음| H["예외가 난다"]

메신저가 셋 깔린 폰에서 공유를 누르면 셋 중 하나를 고르라는 창이 뜹니다. 그림의 「여럿」 갈래가 이 경우입니다.

후보가 없으면 startActivity 가 ActivityNotFoundException 이라는 예외를 던집니다. 보낸 앱이 이 예외를 안 잡으면 앱이 죽습니다. 암시적 인텐트를 보내는 코드가 예외 처리를 함께 두는 까닭입니다.

받는 쪽에서 보는 인텐트

메신저의 글쓰기 화면이 뜨면 자기를 띄운 인텐트를 꺼내 봅니다. 보낸 쪽이 담은 값이 그대로 들어 있습니다.

Kotlin
intent.type // "text/plain"
intent.getStringExtra(EXTRA_TEXT) // "안녕"

EXTRA_TEXT 는 앞에서 본 공용 이름표 Intent.EXTRA_TEXT 입니다. 이름표가 같아야 값이 꺼내집니다.

인텐트 필터를 달면 폰에 깔린 어느 앱이든 그 부품을 깨울 수 있습니다. 받는 쪽은 인텐트에 든 값을 밖에서 들어온 웹 요청의 파라미터처럼 다룹니다. 누가 보냈는지 모르니 검사한 뒤에 씁니다.

인텐트를 보내는 세 호출

지금까지 본 인텐트는 전부 화면, 곧 액티비티를 깨웠습니다. 앱 컴포넌트에는 화면이 없는 부품이 둘 더 있습니다. 인텐트는 어느 호출로 보내느냐에 따라 이 셋 가운데 깨우는 부품이 달라집니다.

호출 깨우는 부품 그 부품이 하는 일
startActivity 액티비티 화면 한 장을 맡는다
startService 서비스 (Android) 화면 없이 뒤에서 작업을 돈다
sendBroadcast 브로드캐스트 리시버 충전기 연결 같은 기기 전체의 알림을 받는다

앞의 둘은 한 부품을 깨웁니다. 셋째는 결이 다릅니다. 인텐트 필터가 맞는 리시버 전부에 같은 인텐트가 갑니다.

그래서 브로드캐스트는 백엔드의 발행-구독과 닮았습니다. 보내는 쪽은 받는 쪽이 누구인지 모릅니다. 관심을 신고해 둔 쪽이 모두 받습니다.

챗봇의 인텐트

챗봇과 음성 비서에서 인텐트는 사용자의 말 한마디가 원하는 목적에 붙인 이름입니다. 「내일 비 와?」와 「우산 챙겨야 해?」는 말은 달라도 둘 다 「날씨 묻기」 인텐트로 묶입니다. 봇은 말을 인텐트로 분류한 뒤, 인텐트마다 정해 둔 응답이나 동작을 돌립니다.

말을 인텐트로 가르는 일은 자연어 이해에 속합니다. 자연어 이해는 사람이 쓴 문장의 뜻을 기계가 알아내는 분야입니다.

이 일은 문장 하나를 미리 정해 둔 인텐트 목록 가운데 하나로 고르는 문제입니다. 그래서 텍스트 분류로 풉니다. 스팸 메일 거르기처럼 글 한 덩이에 정해 둔 이름표 하나를 붙이는 문제가 텍스트 분류입니다.

말 속의 세부 값은 따로 뽑습니다. 「내일 서울 비 와?」라면 인텐트는 날씨 묻기입니다. 「내일」과 「서울」은 그 인텐트에 딸린 값입니다. 이런 값을 엔티티나 슬롯이라고 부릅니다.

두 뜻이 담는 것은 닮았습니다. 둘 다 「무엇을 하고 싶은가」를 담습니다. 안드로이드에서는 앱이 그것을 적어 운영체제에 보냅니다. 챗봇에서는 기계가 사람의 말에서 그것을 읽어 냅니다.

관련 항목

인텐트가 깨우는 안드로이드 부품

앱 컴포넌트 · 액티비티 · 서비스 (Android) · 브로드캐스트 리시버

인텐트를 전하는 안드로이드의 구조

Android · 운영체제 · 매니페스트 · 샌드박스 · 프로세스 · IPC · Binder · 권한

인텐트의 하위 종류

명시적 인텐트 · 암시적 인텐트 · 펜딩 인텐트

인텐트가 받을 부품을 찾는 데 쓰는 요소

인텐트 필터 · URI · MIME 타입 · 딥 링크

인텐트가 값을 싣는 방식

엑스트라 · Bundle · Parcelable · 직렬화

인텐트를 보내는 호출

startActivity · startService · sendBroadcast · bindService

인텐트에서 자주 나는 오류·보안 문제

ActivityNotFoundException · 예외 · 인텐트 가로채기 · 인텐트 스푸핑

인텐트와 발상이 닮은 백엔드 기법

발행-구독 · 메시지 브로커 · 서비스 디스커버리 · 결합도

챗봇 인텐트를 다루는 자연어 처리 개념

자연어 이해 · 텍스트 분류 · 개체명 인식 · 슬롯 채우기 · 챗봇 · 음성 비서

인텐트와 이름이 겹치는 헷갈리는 이웃

렌더링 인텐트 · 의도 기반 네트워킹 · PaymentIntent

다른 이름: intent · Intent · 안드로이드 인텐트 · Android Intent