Android - 구성요소(컴포넌트)

Posted by RoadtoS7 on December 29, 2020 · 8 mins read

앱 컴포넌트 4가지

  • 여기서 앱 컴포넌트는 앱을 구성하는 주요 요소들을 말한다.
  • 각 컴포넌트는 사용자나 시스템이 앱에 들어갈 수 있는 진입점이 된다.
  • 컴포넌트들은 고유한 역할을 가지고 있다.
  • 또한 생성 및 소멸 방식을 정의하는 자신만의 생명주기를 가지고 있다.


:one: Activity

  • 액티비티는 사용자와 상호작용하기 위한 진입점이다.

  • 유저 인터페이스를 가진 하나의 화면을 나타낸다.

  • 액티비티는 서로 독립적이다.

  • 따라서 특정 앱의 여러 액티비티 중 하나를 해당 앱에서 허용한다면, 다른 앱에서 실행시킬 수 있다.

  • 액티비티는 다음과 같은 시스템과 사용자간의 상호작용을 돕는다.
    1. 사용자가 현재 관심을 가지고 있는 것(화면에 나타난 것)을 추적하여, 해당 액티비티를 호스팅하고 있는 프로세스를 시스템이 계속 실행하도록 한다.
    2. 이전에 사용한 프로세스에 사용자가 다시 찾을 만한 액티비티(중단된 액티비티, stopped acitivity)가 있다는 것을 알고, 해당 프로세스를 유지하는데 더 높은 우선순위를 부여한다.
    3. 앱이 프로세스를 종료하는 것을 도와서 이전 상태를 그대로 가지고 있는 액티비티로 사용자가 돌아갈 수 있도록 한다.
    4. 앱에게 여러 앱들을 오가는 사용자 플로우를 구현할 방법을 제공하고, 시스템에게 이런 사용자 플로우를 조정할 방법을 제공한다.
  • 액티비티는 Activity클래스를 상속받아서 만들어진다.


:two: Service

  • 서비스는 백그라운드에서 앱을 계속해서 실행시키기 위한 앱의 다목적 진입점

  • 역할: 서비스는 백그라운드에서 실행되는 구성요소로, 오래 실행되는 작업을 수행하거나 원격 프로세스를 위한 작업을 수행한다.

  • 특징:
    1. 서비스는 유저 인터페이스를 제공하지 않는다.
      • 예를 들어서 서비스는 사용자가 다른 앱에 있는 동안 백그라운드에서 음악을 재생하거나,
        사용자아 액티비티간의 상호작용을 차단하지 않고 네트워크를 통해 데이터를 가져올 수 있다.
    2. 다른 구성요소가 서비스를 시작한 다음, 서비스가 계속해서 실행되도록 두거나
      서비스와 바인딩하여 상호작용할 수 있다.
  • 서비스에는 크게 2가지 종류가 있으며, 시스템에서 자신이 포함된 앱 어떤 방식으로 관리되도록 만드는지에 따라서 달라진다.
  1. 시작된 서비스
    • 시작된 서비스는 자신의 작업이 끝날 때까지 해당 서비스를 계속 실행하라고 시스템에 지시한다.
    • 예로는 백그라운드에서 일부 데이터를 동기화하거나, 음악을 재생하는 서비스 있다.
    • 시작된 서비스는 시스템이 해당 서비스를 어떻게 다루는지에 따라서, 다시 2가지 종류로 나뉜다.
      1. 포그라운드 서비스
      • 음악을 재생하는 서비스가 포그라운드 서비스에 해당된다.
      • 음악 재생은 사용자가 확실하게 인식할 수 있는 작업이다.
        따라서 앱은 사용자에게 이와 관련된 알림을 보내면서 이 서비스를 포그라운드로 옮기라고 시스템에게 전달한다.
      • 이 경우 시스템은 이 서비스가 사라지면 사용자가 불만을 느낄 것이기에 시스템은 해당 서비스가 속한 프로세스가 계속 실행되도록 노력한다. 2. 백그라운드 서비스
      • 백그라운드에서 일부 데이터를 동기화하는 경우가 백그라운드 서비스에 해당된다.
      • 백그라운드 서비스는 사용자가 실행되고 있다고 직접적으로 인식할 수 없는 작업을 수행하는 서비스
      • 따라서 시스템은 이 서비스가 속한 프로세스를 좀 더 자유롭게 관리할 수 있다.
      • 즉, 사용자와 현재 더 직접적인 관련있는 작업에 RAM공간이 필요할 때, 시스템은 백그라운드 서비스를 종료시킬 수 있다.(그리고 나중에 다시 실행시킬 수 있다.)
  2. 바인딩된 서비스
    • 바인딩된 서비스 다른 앱 혹은 시스템에서 해당 서비스를 사용하고 싶다고 요청할 때 실행된다.
    • 즉, 바인딩된 서비스는 기본적으로 다른 프로세스에 API를 제공하는 서비스이다.
    • 만약 프로세스 A가 프로세스 B의 서비스에 바인딩되어 있다면, 시스템은 이 두 프로세스간에 종속성이 있음을 알고 있다.
    • 시스템은 프로세스 A를 실행하기 위해서 프로세스 B(와 A가 바인딩하고 있는 서비스)를 실행해야 한다는 것을 알고 있다.
    • 따라서 프로세스 A가 현재 사용자의 관심을 받고 있다면, 시스템은 프로세스 B도 사용자가 관심을 가지고 있는 것으로 취급해야한 한다는 것을 알고 있다.
    • 시스템에서 이런 유연성(융통성)을 가지고 있기 때문에 고차원적인 시스템 개념의 매우 유용한 구성요소로 사용되고 있다.
      • 라이브 배경화면, 알림 리스너, 입력 메서드, 화면 보호기, 접근성 서비스 및 여러가지 기타 핵심 시스템 기능이 애플리케이션이 구현하는 서비스로 구축되고, 해당 서비스가 실행되어야 할 때, 시스템이 바인딩한다.
  • 서비스 구현 방법: 서비스는 Service클래스를 상속받아서 만든다.

  • 참고할 점: 만약 만들려는 앱이 API 레벨 21(Android 5.0)이상을 타겟으로 한다면, JobScehduler를 상요해서 작업을 예약하는 것이 좋다.
    JobScheduler는 작업 일정을 최적으로 조정하여 전력 소모량을 줄이고, Doze API와 함께 동작하여 배터리를 절약해주는 장점이 있다.


:three: Broadcast Reciever

  • 브로드캐스트 리시버는 시스템이 앱에게 이벤트를 전달할 수 있도록 하고, 앱으로 하여금 시스템 전역 브로드 캐스트 알림에 응답할 수 있도록 한다.

  • 브로드캐스트 리시버는 앱으로 들어갈 수 있는 있는 진입점이기 때문에, 현재 실행되지 않은 앱에도 브로드 캐스트를 전달할 수 있다.

  • 예를 들어서 앱이 사용자에게 예정된 일정을 알려주기 위한 알람을 예약할 경우,
    알람이 울릴 때까지 앱을 실행시켜둘 필요 없이, 알람을 해당 앱의 브로드 캐스트리시버에게 전달하기만 하면 된다.

  • 대다수의 브로드 캐스트는 시스템에서 발생한다.

  • 예를 들어서, 배터리가 부족하거나 사진을 캡쳐했다는 브로드 캐스트가 대표적이다.

  • 앱도 브로드 캐스트를 만들 수 있다.

  • 예를 들어서, 다른 앱에게 기기에 데이터가 다운되었고, 그 데이터를 사용할 수 있도록 하기 위해 브로드 캐스트를 만들 수 있다.

  • 브로드캐스트 리시버는 UI를 표시하지 않지만, 하지만 브로드캐스트 알림이 왔다는 것을 사용자에게 알리기 위해 상태바 알림을 만들 수 있다.

  • 하지만 일반적으로 브로드캐스트 리시버는 다른 구성요소로 가는 문인 경우가 많고,
    아주 적은 양의 작업을 수행하도록 많들어진 경우가 많다.

  • 예를 들어서 JobScheduler의 이벤트를 기반으로 어떤 작업을 수행하도록 JobService를 예약할 수 있다.

  • Broadcast Receiver는 BroadCastReciever의 자식 클래스로 구현된다.
  • 각 브로드캐스트는 Intent로서 전달된다.

:four: Contents Provider

  • 콘텐츠 프로바이더는 파일 시스템, SQLite Database, 웹, 혹은 앱에서 접근할 수 있는 모든 영구 저장소에 저장할 수 있는 앱 데이터의 공유 집합을 관리한다.

  • 다른 앱은 콘텐츠 프로바이더를 통해서 데이터를 얻어오거나, 콘텐츠 프로바이더가 허용할 경우에는 데이터를 수정할 수 있다.

  • 예를 들어서 안드로이드 시스템은 사용자의 연락처 정보를 관리하는 콘텐츠 프로바이더를 제공한다.

    • 따라서 적절할 권한을 가진 앱이라면, 콘텐츠 프로바이더에게 질의하여(ContactsContract.Data 이용함),
      특정 연락처를 읽거나 쓸 수 있다.
  • 콘텐츠 프로바이더를 데이터베이스에 대한 추상화로 생각하기 쉽다. 콘텐츠 프로바이더에는 이런 일반적인 용도로 만들어진 지원 및 API가 많기 때문이다.
    하지만 시스템 설계 관점에서 볼 때, 콘텐츠 프로바이더와 데이터베이스는 핵심 목적이 다르다.
    • 시스템에게 콘텐츠 프로바이더는 URI 구성표(Scheme)로 식별되면서 이름이 지정된 데이터를 얻어올 목적으로 앱에 진입할 입구이다.
    • 따라서 앱이 자신의 데이터와 URI 네임스페이스를 어떤 방식으로 서로 맵핑할지를 결정할 수 있다.
      그리고 이 URI를 다른 엔티티로 전달할 수 있다. URI를 전달받은 엔티티는 URI를 이용하여 데이터에 해당 데이터에 접근한다.
  • 시스템이 이렇게 할 수 있는 데에는 앱을 관리하는데 특별한 점이 있기 때문이다.
    1. URI를 할당하는데 앱을 계속 시켜둘 필요가 없다.
      따라서 URI를 소유한 앱이 종료된 이후에도 URI는 계속 살아있을 수 있다. 시스템은 URI를 통해서 데이터를 불러올 때만, 해당 URI를 소유한 앱이 실행되도록 하면 된다.

    2. URI는 중요하고 세분화된 보안모델을 제공한다.
      예를 들어서 앱은 클립보드에 있는 이미지에 URI를 할당할 수 있지만, 콘텐츠 프로바이더가 이 URI를 잠금 상태로 만들어서,
      다른 앱이 해당 이미지를 접근하지 못하도록 만들 수 있다.
      만약 두번재 앱이 클립보드에서 해당 URI에 접근하려고 할 때, 시스템은 임시적인 URI 사용권한을 부여하여, 그 앱이 해당 데이터를 접근하도록 할 수 있다.
      하지만 해당 URI의 데이터 외에는 접근할 수 없다.

  • 콘텐츠 프로바이더는 특정 앱에서만 사용하고 공유하지 않을 데이터를 접근할 때도 유용하다.

  • 콘텐츠 프로바이더는 ContentsProvider의 자식 클래스로 구현된다.
    이때 다른 앱이 트랜잭션을 수행할 수 있도록 만드는 API 집합을 구현해야 한다.
    자세한 내용은 콘텐츠 프로바이더 개발 가이드 에서 확인할 수 있다.