1. 안드로이드와 코틀린
1.1 운영체제와 플랫폼
안드로이드 플랫폼은 리눅스 운영체제 안에서 리눅스와 상호작용하며 동작한다. 전체 아키텍쳐 위쪽에 안드로이드가 실행되는 런타임 영역이 존재한다.
System Apps | ||
Java API Framework | ||
Native C/C++ Libraries | Android Runtime | |
Hardware Abstraction Layer(HAL) | ||
Linux Kernel |
Android
다양한 기기와 폼 팩터에 사용할 수 있도록 제작된 Linux 기반의 오픈소스 소프트웨어 스택이다. 출처: https://developer.android.com/guide/platform
소프트웨어 스택(SoftWare Stack)
솔루션 스택이라고도 불리며 소프트웨어 서브시스템, 컴토넌트 집합을 말한다. 애플리케이션 지원에 추가 소프트웨어가 필요하지 않은, 완전한 플랫폼을 만드는데 필수적인 소프트웨어 구성 요소들의 모임이다. 애플리케이션은 이렇게 만들어진 플랫폼 “위에서 실행된다”라고 표현한다. 출처: https://ko.wikipedia.org/wiki/%EC%86%94%EB%A3%A8%EC%85%98_%EC%8A%A4%ED%83%9D
리눅스 커널(Linux Kernel)
Linux 운영 체제의 주요 구성 요소로서 하드웨어와 프로세스를 잇는 핵심 인터페이스이다. 커널의 대표적인 기능은 다음과 같다.
- 메모리관리
- 프로세스 관리
- 장치 드라이버
- 시스템 호출 빛 보안
출처: https://www.redhat.com/ko/topics/linux/what-is-the-linux-kernel#:~:text=%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%EC%84%9C%20%EC%8B%A4%ED%96%89%EB%90%98%EB%8A%94%20%EC%BD%94%EB%93%9C,%EC%95%A1%EC%84%B8%EC%8A%A4%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EC%A0%9C%ED%95%9C%ED%95%A9%EB%8B%88%EB%8B%A4.
1.2 플랫폼 버전과 API 레벨
안드로이드는 사용하는 플랫폼 버전과 더불어 API 레벨이라는 것이 있다. API는 개발자에게 안드로이드 플랫폼의 기능을 사용할 수 있게 제공하는 도구로, 레벨에 따라 새로운 기능이 추가되거나 코드 전체를 변경해야 하는 경우가 있다. 따라서 API 레벨의 변경사항이 있을 때는 기존의 코드를 다시 확인해야 한다.
안드로이드 개발자 사이트는 최신 버전에 대한 정보 뿐만 아니라, 사용현황도 확인할 수 있다. 현재 시점의 점유율은 안드로이드 스튜디오에서 새로운 프로젝트를 생성할 때 나타나는 Help me choose 링크를 통해 확인할 수 있다.
짧은 업데이트 주기
안드로이드는 일년에 한 번 정도, 메이저 버전이 업데이트되고 있다(새로운 버전의 안드로이드가 출시된다). 그러나 새로운 버전으로 사용자가 옮겨 가는 데는 적어도 몇년의 시간이 소요되므로 항상 최신 버전에 맞춰 개발할 필요는 없다.
1.3 코틀린
안드로이드 플랫폼의 구조는 리눅스 커널과 자바 API 프레임워크가 결합된 형태이다. 과거에는 어플리케이션이 JVM 위에서 실행되었으나, 현재는 안드로이드 런타임(Android RunTime, ART)를 사용한다.
따라서 JVM은 없지만 가상 머신 위에서 동작한다는 점에서 자바의 동작 구조를 차용하고 있다. 기존에는 자바를 앱 개발 언어로 사용했으나, 2017년 Google I/O에서 코틀린을 공식언어로 채택 한 후부터 코틀린 사용 비율이 늘고 있다. 코틀린은 젯브레인 사가 만든 프로그래밍 언어이다.
코틀린으로 안드로이드 앱 개발하기 : https://developer.android.com/kotlin
1.4 함수형 프로그래밍 언어 코틀린
코틀린 함수형 프로그래밍을 표방하고 있기 때문에 클래스 내부에 있는 함수에서만 로직을 작성하는 객체지향 프로그래밍 언어와 달리, 제한 없이 어디에서나 로직을 작성할 수 있다.
class Hello {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
System.out.println("Hello World");
1.5 안드로이드 개발에 있어서 자바와 코틀린의 차이
안드로이드 앱을 개발할 때에는 코틀린도 객체지향 언어처럼 클래스 내에서 로직을 작성해야 한다. 코틀린은 자바와 100% 호환이 되며, 안드로이드는 자바와 코틀린을 동시에 지원하므로 자바의 형식에 맞춰서 코틀린으로도 개발해야 한다.
그래도 코틀린으로 작성하면 자바보다는 코드의 양이 훨씬 적어진다. 간단하게 버튼을 클릭하면 메시지를 보여주는 코드를 갖고 두 언어를 비교해보자.
class ButtonActivity extends Activity {
protected void onCreate(Bundle savedInstance) {
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
System.out.print("Hello World");
}
});
}
}
class ButtonActivity : Activity() {
override fun onCreate(savedInstance: Bundle?) {
button.setOnClicklistener {
print("Hello World")
}
}
}
2. 안드로이드 아키텍쳐
안드로이드 아키텍쳐는 안드로이드 플랫폼의 실제적인 동작 구조 또는 형태를 말한다. 우리가 작성한 소스 코드가 디바이스에 설치되면 이 아키텍쳐 구조 안에서 모든 동작이 실행된다.
소스 코드의 설치 파일 생성과정과 스마트폰에서 실행되기까지의 전 과정에 대해 알아볼 것이다. 이 책에서 다루는 안드로이드 플랫폼은 안드로이드 운영체제와 앱이 동작하는 소프트웨어까지만 포함되지만 더 넓게는 안드로이드 스튜디오와 플레이스토어, 안드로이드 스마트폰까지가 하나의 거대한 안드로이드 플랫폼이라고 할 수 있다.
2.1 소스 코드 작성에서 실행까지
소스 코드 작성에서 실행까지의 과정은 다음과 같다.
- 소스 코드 작성: 코틀린으로 소스 코드를 작성한다.
- 설치 파일 생성: 명령을 통해 안드로이드에서 실행될 수 있는 설치 파일의 형태로 변환한다.
- 업로드: 구글 플레이 스토어에 앱을 업로드한다.
- 앱 등록: 구글 플레이 스토어에 앱을 등록한다.
- 앱 선택/설치: 구글 플레이 스토더에 접속한 후, 설치한 앱을 선택.설치한다.
- 스마트폰에서 실행: 스마트폰에서 앱을 실행한다.
2.2 코드가 스마트폰에서 실행되는 과정
앞서 간단히 설명한 소스 코드 작성에서 실행까지의 단계가 실제 내부에서는 어떻게 진행되는지 살펴볼 것이다.
- 빌드(컴파일 + 비밀번호) : 소스 코드를 바이트 코드로 변환하여 APK 매니저에서 비밀번호를 갖고 있는 키 스토어와 조합하여 최종 설치 파일을 생성한다.
- 파일 검증 : 구글 플레이 스토어에서 앱을 검수한 후 파일을 스토어에 업로드한다. 검수할 때에는 설치 파일이 정상 동작하는지, 보안상의 문제는 없는지 등을 검사한다.
- 플랫폼 버전 체크 : 사용자가 스마트폰으로 구글 플레이 스토어에 접속하면 스마트폰의 플랫폼 버전을 확인한 다음 설치 가능한 앱의 목록만 스토어에 띄운다.
- AOT 컴파일/설치 권한 체크 : APK 파일을 설치하고 난 후, 리눅스에서 실행 가능한 파일로 안드로이드폰 내부에서 한 번 더 컴파일 한다. 이 과정을 통해 실행 속도가 빨라지며, 사용자에게
기능의 사용 권한
을 요청한다. - JIT 컴파일/실행 권한 체크 : 4 단계에서 설치할 때에는 필요한 파일만 컴파일하고 앱을 실행할 때에는 미리 컴파일되지 않은 파일을 호출하면서 리눅스 실행 파일로 컴파일한다. 그리고 권한 중
실행 시 권한
이 포함되어있으면 해당 코드가 동작해서 사용자에게 확인 요청을 한다.
바이트 코드와 APK
바이트 코드란 코틀린 코드를 ART가 이해할 수 있도록 변환한 코드이다. APK는 안드로이드 패키지의 줄임말로 안드로이드 설치 파일의 확장자명으로 사용된다. 특정 앱의 APK파일이 있다면 스마트폰에 수동으로 해당 앱을 설치할 수도 있다.
2.3 빌드
소스 코드를 변환해서 안드로이드에서의 실행 파일인 APK 파일로 만드는 것을 빌드라고 한다. 빌드는 소스 드를 기계어로 변환하고, 라이브러리와 연결해서 실제 실행 파일로 만드는 과정을 일컫는 용어이다. 안드로이드는 리눅스 커널 기반이므로 리눅스 시스템에서의 빌드를 이해하는 것이 도움이 된다.
리눅스에서의 빌드
리눅스에서 빌드란 소스 코드를 기계어로 컴파일하고 소스코드에서 사용하는 라이브러리와 연결하여 최종 실행 파일 형태로 만드는 과정을 말한다.
- 링크 빌드 = 컴파일 + 링크
- 컴파일 : 소스코드 -> 기계어
- 링크 : 기계어 -> 라이브러리와 연결
안드로이드에서의 빌드
안드로이드에서의 컴파일이 리눅스 컴파일과 비교해서 갖는 차이점은 안드로이드에는 리소스(Resource)라는 개념이 있다는 점이다.
안드로이드는 2단계로 컴파일을 다음과 같이 나눌 수 있다.
- 바이트코드 단계 : 소스 코드와 리소스(이미지 파일, 음악 파일 등), 라이브러리까지 한 번에 컴파일 해준다. 이 과정으로 만들어지는 Dex 파일은 스마트폰에서 바로 실행할 수는 없다.
- APK 파일 생성 단계 : 1단계에서 생성되는 Dex 파일을 APK 매니저라는 도구로 개발자가 생성한 패스워드와 조합해서 설치 파일인 APK 파일로 만든다.
APK와 AAB
AAB는 안드로이드가 새롭게 제안하는 APK 파일을 대체하는 빌드 파일 형태이다. 플레이 스토어에 AAB 파일 형태로 앱을 등록하면 사용자가 앱을 다운로드할 때 사용자의 디바이스에 필요한 모듈만 골라 APK 파일로 다시 생성해준다. 따라서 여러 언어를 지원하는 앱을 AAB 파일로 등록하면, 각 디바이스에서 필요한 언어파일만 모아 설치되도록 한다.
2.4 설치와 실행
안드로이드의 아키텍쳐는 앱 설치부터 실행 후 종료까지 계속 관여한다. 설치된 앱이 가장 상단에 있는 애플리케이션 영역에서 동작하고, 안드로이드는 안드로이드 런타임 영역에서 개발자가 만든 앱을 제어한다.
스마트폰에 앱을 설치하면, 설치 파일의 일부가 리눅스 운영체제에서 실행할 수 있는 파일 형태로 한번 더 컴파일 되는데, 이런 구조를 AOT(Ahead of Time)라고 한다. 플랫폼 버전 5.0 롤리팝에서는 모든 파일이 컴파일되는 형태였다가 효율성의 문제로 일부만 컴파일 하는 형태로 변경되었다.
앱을 실행하면 호출되는 파일 중에 컴파일되지 않았던 파일이 한 번 더 컴파일되는데, 이 구조를 JIT(Just-in-Time)라고 한다. 안드로이드는 AOT와 JIT라는 2개의 컴파일 형태를 같이 사용함으로써 효율성을 높인다.
두 번 컴파일 하는 이유
AOT 컴파일 시 모든 파일을 컴파일 하면 사용할 때 속도는 빠르지만, 그만큼 많은 용량을 차지하므로 많은 앱을 설치할 수 없다. JIT 컴파일을 하면 호출 시 컴파일되므로 잠시 성능에 영향을 줄 순 있어도 한 번 컴파일된 이후에는 AOT와 동일한 속도를 내며, 디스크의 용량을 적게 차지한다.
Comments