운영체제
- Operating System is a program running at all times on the computer to provide system servieces to application programs to manage "processes", resources, user interfaces, and so on.
우리가 사용하는 컴퓨터에는 O/S가 설치되어있다. Windows, Mac, 대표적으로 사용하는 운영체제이다. 이 운영체제라는 녀석은 컴퓨터가 부팅되는 순간부터 동작한다. 그리고, 컴퓨터가 종료되기 직전의 순간까지 동작한다. 왜일까?
현재 대부분의 컴퓨터는 폰노이만 아키텍쳐로 구성되어 있다. 모든 프로그램을 메인 메모리에 항상 올려두고 사용할 수가 없고, 하드(SSD, HDD)속에 잠들어있다. 당신이 롤 클라이언트 프로그램을 클릭하면 쁌하고 클라이언트가 구동된다. 사실 'Loader라는 녀석이 롤 클라이언트 프로그램을 메인 메모리 상에 적재하고, 프로세스가 된 해당 프로그램은 다른 프로세스들과 번갈아가며 CPU를 점유하여 프로그램이 실행된다'
이러한 일련의 과정은 당신이 롤 클라이언트 프로그램 아이콘을 누른 시점부터 순식간에 일어난다. 이러한 과정이 있어야 프로그램을 사용할 수 있게 되는 것이다. 우리는 지금 스마트폰을 사용하던, 컴퓨터를 사용해서 이 글을 보고 있던 당신 또한 운영체제의 도움을 받고 있다. 운영체제는 "컴퓨터의 전원이 켜져있는 모든 순간" "하드웨어들을 운영함으로서" "사용자가 쉽게 컴퓨터를 사용할 수 있게" 해준다.
이제 android 운영체제에 대해 알아보자. 안드로이드 문서 - Platform Architecture를 참고했다.
Android는 Linux 기반의 오픈소스 소프트웨어 스택이라고 한다. 안드로이드 플랫폼 아키텍처를 살펴보니 계층적으로 구성되어 있다는 것을 알 수 있다. 가장 아래층부터 살펴보자. 아 그리고 계층 시스템을 공부하기에 앞서 알아두고 가면 좋을 포인트가 있다. 바로 계층 시스템은 하위 계층은 상위 계층에게 서비스를 제공하고, 상위 계층은 하위 계층의 서비스를 사용한다는 것이다.
Layer System
위의 Android Platform Architecture를 봐도 그렇다. 생각해보자. 우리는 최상위 계층인 System Apps Layer의 Dialer, Email, Camera, 카카오톡 등의 앱을 사용한다. 그리고 우리는 최상위 계층의 App을 사용하면서, 최하위 계층인 Linux Kernel의 기능을 활용하여 하드웨어를 제어 및 활용하고 있다. 계층 시스템의 원리가 그러하다. 하위 계층의 서비스를 상위 계층에게 제공함으로써, 시스템을 구축해나간다. "따라서 최상위 계층의 서비스를 활용하는 우리는 모든 계층의 서비스를 손 쉽게 사용할 수 있게 되는 것" 이다. 또한 하위 계층의 기능 구현 사항은 상위 계층이 모르는 것이 좋다. 상위 계층이 하위 계층의 서비스를 손 쉽게 사용할 수 있도록, 잘 만들어진 인터페이스를 제공한다는 것이다. 이 점을 알고 Android Platform Architecture를 살펴보자.
Kernel은 운영체제의 핵심이 되는 컴퓨터 프로그램의 하나이다. 시스템의 모든 것을 완전히 통제한다. 운영체제의 다른 부분 및 응용 프로그램 수행이 필요한 여러 가지 서비스를 제공한다. ART(Android RunTime)는 스레딩-하위 수준의 메모리 관리 등의 기본 기능에 Linux Kernel을 사용한다.
1층인 Linux Kernel은 Kernel이라는 말 그대로 운영체제의 핵심을 담당하며 하드웨어의 직접적인 접근에 대한 사항이었다. 앞서 언급한 계층 시스템의 원리에 따라, 계층이 올라갈수록 실제 사용자들과 가까워질 것이다. HAL은 상위 계층인 "Java API 프레임워크에 하드웨어 기능을 제공"하는 표준 인터페이스를 제공한다.
Android Runtime(ART) 은 Linux Kernel과 HAL의 상위 계층에 위치하여 운영체제를 활용해 Java 애플리케이션 실행에 대한 중추 역할을 수행하는 Virtual Machine이다. Android Runtime이 어떠한 역할을 하는지 알기 위해선 Java의 JVM에 대해서부터 알아 볼 필요가 있다.
Android Runtime(ART)의 등장 배경 및 역할
Java와 같은 고급 프로그래밍 언어 코드를 컴퓨터가 이해할 수 있도록 기계어로 변환하는 과정(.java -> .class)을 컴파일이라고 한다. C와 같은 일반적인 컴파일 언어는 고급 프로그래밍 언어 코드를 기계어로 변환하지만,
자 Java는 일반 고급 프로그래밍 언어와 다르게 기계어 대신 Java byte code로 변환 후 JVM을 통해 프로그램을 실행한다. 안드로이드는 기본 언어로 Java을 채택했기 때문에 JVM이 필수적이었는데, 오라클과의 라이센스 문제 해결과 안드로이드 운영체제 구조에 맞춰 구동할 수 있는 JVM을 만들어야했다. 이러한 과정을 통해 만들어진 안드로이드용 JVM이 Dalvik VM과 ART이다. 이 둘의 차이는 아래와 같다.
따라서 달빅VM/ART를 사용함에 따라 동작하는 형태도 달라지게 된다. ART가 JIT보다 나중에 등장했다. JIT의 경우 안드로이드 2.2부터 달빅VM에 추가되었으며, 이전까지는 애플리케이션 구동 시 실시간으로 CPU에 맞추어 자바코드를 변환했다. 하지만 JIT을 도입하고 난 뒤로는 최초 앱 실행 시 한꺼번에 자바 코드의 일정 부분을 변환하고 RAM 상에 올려두고 작업하게 된다. 이를 통해 비약적인 성능 향상이 일어났지만, 다음과 같은 문제가 발생하게 된다.
해당 문제를 해결하기 위해 AOT 컴파일러를 기반으로 만들어진 VM이 ART이다. JIT과 달리 애플리케이션 설치 시 한 번에 (미리) 컴파일하여 바이트 코드로 변환해두고 있다가 프로그램 실행 시 변환된 코드를 읽어들인다. 이를 통해 ART는 달빅VM에 비해 압도적인 성능 향상이 이루어졌고, 네이티브 언어와 동급의 성능을 체감할 수 있게 되었다. 하지만 ART에도 분명한 단점이 존재한다.
이러한 이유로 안드로이드 7.0 버전부터는 앱 설치시간을 단축하기 위해 최초 설치 시에는 일단 JIT 컴파일러를 사용하고, 기기를 사용하지 않는 시간에 일부분 컴파일 작업을 실시하여 점진적으로 AOT 컴파일 방식으로 바꿔 나가도록 돼있다. 달빅VM과 ART의 장점을 합치고 단점을 해결하려는 시도가 이루어진 것이다. 이렇게 ART의 등장 배경, 역할 등에 대해 이해했고, "Linux Kernel과 HAL의 상위 계층에 위치하여 운영체제를 활용해 Java 애플리케이션을 실행하는 중추 역할을 수행하는 것이 Virtual Machine이 ART라는 것을 알 수 있다." 안드로이드 문서를 통해 ART의 주요 기능 중 몇 가지를 살펴보자면 다음과 같다.
- AOT(Ahead-Of-Time) 및 JIT(Just-In-Time) 컴파일
- 최적화된 가비지 컬렉션(GC)
- Android 9(API 레벨 28) 이상에서 앱 패키지의 DEX(Dalvik Executable) 형식 파일이 더욱 간소한 기계 코드로 변환됨
- 전용 샘플링 프로파일러, 상세 진단 예외 및 크래시 보고, watchpoint를 설정하여 특정 필드를 모니터링할 수 있는 기능을 비롯한 향상된 디버깅 지원 기능
- Android 버전 5.0(API 레벨 21) 이전 버전에서는 Dalvik이 Android 런타임이었습니다. 앱이 ART에서 제대로 실행되면 Dalvik에서도 제대로 실행되지만, 그 반대의 경우 제대로 실행된다는 보장은 없습니다.
- Android에는 Java API 프레임워크가 사용하는 몇 가지 Java 8 언어 기능을 포함하여 대부분의 Java 프로그래밍 언어 기능을 제공하는 일련의 핵심 런타임 라이브러리도 포함되어 있습니다.
우선 안드로이드 문서에 소개돼있는 설명을 보고 가자.
- "ART 및 HAL 등의 많은 핵심 Android 시스템 구성 요소 및 서비스"가 (C/C++로 작성된 네이티브 라이브러리를 필요로 하는) C/C++ 네이티브 코드로 빌드" 되었습니다.
- Android 플랫폼은 Java 프레임워크 API를 제공하여 이러한 일부 네이티브 라이브러리의 기능을 앱에 제공합니다.
- 하위 계층은 상위 계층에게 서비스를 제공한다는 말이다. Native C/C++ Libraries의 기능을 상위 계층인 Java Framework API에게 제공한다는 것이다.
- 예를 들어, Android 프레임워크의 Java OpenGL API를 통해 OpenGL ES에 액세스하여 앱에서 2D 및 3D 그래픽을 그리고 조작할 수 있는 지원 기능을 추가할 수 있습니다.
- C 또는 C++ 코드가 필요한 앱을 개발하는 경우에는 Android NDK를 사용하여 네이티브 코드에서 직접 이러한 몇몇 네이티브 플랫폼 라이브러리에 액세스할 수 있습니다.
Java API Framework에 오면서, 안드로이드 개발을 해 본 이들이 자주 접해봤을 키워드들이 보인다. 그만큼 사용자와 개발자에 가까워졌다는것이다. 이것 또한 안드로이드 문서를 보며 얘기해보자.
- Android OS의 전체 기능 세트는 Java 언어로 작성된 API를 통해 액세스할 수 있습니다. 이러한 API는 핵심 모듈식 시스템 구성 요소 및 서비스 재활용을 단순화하여 Android 앱을 제작하는 데 필요한 빌딩 블록을 구성하며, 이러한 빌딩 블록에는 다음이 포함됩니다.
- 기능이 풍부하며 확장 가능한 뷰 시스템 - 목록, 그리드, 텍스트 상자, 버튼 및 삽입 가능한 웹브라우저를 포함하여 앱의 UI를 빌드하는 데 사용 가능
Java API Framework가 제공하는 대표적인 서비스
위의 사진을 보니 안드로이드 앱을 구성하기 위해 필요한 서비스들이 나와있다. Activity, Location, Package, Notification, Resource, Telephony, Window.. 중요한 것은 Application을 구성하기 위해 필수적인 low level 기능들을 잘 몰라도 "아주 잘 만들어진 Java API들을 사용함으로써" 손쉽게 활용할 수 있다는 것이다.
- View System - List/Grid/TextView/Button/WebView 등 다양한 View System의 기능을 제공하며 확장성을 제공한다. 해당 기능들을 활용하여 Application의 UI(User Interface)를 빌드하는데 사용한다.
- Resource Manager - 현지화된 문자열, 그래픽 및 레이아웃 파일과 같은 코드가 아닌 리소스에 대한 액세스 제공
- Notification Manager - 모든 앱이 상태 표시줄에 사용자 지정 알림을 표시할 수 있도록 지원
- Activity Manager - 앱의 수명 주기를 관리하고 공통 탐색 백 스택 제공
콘텐츠 제공자 - 앱이 주소록 앱과 같은 다른 앱의 데이터에 액세스하거나 자신의 데이터를 공유할 수 있도록 지원
- 개발자는 Android 시스템 앱이 사용하는 것과 동일한 프레임워크 API에 대한 전체 액세스 권한을 가집니다.
드디어 최상위 계층인 System Apps에 도착했다. 여기는 공부할 필요가 없다. 우리가 매일매일 사용하는 Application이기 때문이다.
우리는 App을 사용한다.
이 모든 건 "계층적으로 잘~ 만들어진 Linux Kernel 기반의 Android O/S가 지금 이 순간에도 열심히 일하고 있기 때문" 이다!