목차
앱 구성 파일 분석
이번 장에선 앱을 구성하는 파일을 분석해 볼 것이다.
프로젝트의 폴더 구성
안드로이드 앱 프로젝트 생성시 만들어지는 폴더는 대부분은 빌드 도구와 관련된 것
개발자가 관심을 둬야 할 파일은 프로젝트 폴더에서 [모듈명 → src → main]
안에 있음
즉 윈도우의 파일 탐색기에서 본 폴더 구조는 아래와 같다.
그런데 안드로이드 스튜디오의 프로젝트 탐색 창은 윈도우 파일 탐색기처럼 모든 폴더와 파일을 보여 주지 않는
개발자가 분석하거나 작성해야 하는 폴더와 파일만 보여줌
[app 모듈]
- 프로젝트를 만들면 app이라는 모듈이 자동으로 생성된다.
- 모듈 하나가 앱 하나이며 프로젝트는 여러 모듈을 묶어서 관리하는 개념이다.
- 하나의 프로젝트에는 자동으로 만들어지는 app 모듈 이외에 여러 모듈을 추가 가능
- 모듈은 앱 단위이므로 새로운 모듈을 추가한 다는 것은 새로운 앱을 개발한다는 것과 같음
- 모듈을 추가하는 방법은 이후에 자세하게 다루겠음
모듈의 폴더 구성 알아보기
모듈은 어떤 폴더와 파일로 구성되는지 알아보겠다.
[모듈을 구성하는 폴더와 파일]
build.gradle
빌드 설정 파일AndroidManifest.xml
앱의 메인 환경 파일res
리소스 폴더activity_main.xml
레이아웃 XML 파일MainActivity.kt
메인 액티비티 파일
그래들 빌드 설정 파일
[그래들 gradle]
- 안드로이드 앱의 빌드 도구
- 그래들의 설정 파일은
build.gradle
임 - 앱을 빌드하는 데 필요한 설정을 이 파일에 등록함
- 그래들 파일은 안드로이드 스튜디오의 탐색 창에서 코끼리 모양의 아이콘이 있는 [Gradle Scripts]에서 찾을 수있음
그런데 탐색 창을 보면 build.gradle 파일이 2개 있음
- 하나는 프로젝트 수준의
build.gradle (Project: AndroidLab)
- 또 하나는 모듈 수준의
build.gradle (Module:AndroidLab.app)
- 모듈은 앱을 의미하므로 대부분의 빌드 설정은 모듈 수준의 그래들 파일에 작성함
- 모듈 수준의 그래들 파일을 열어 보면 몇 가지 설정이 자동으로 등록되어 있음
- 이 값을 수정하거나 새로 추가하면서 빌드 환경을 설정가능
- 중요한 설정 몇 가지만 살펴보겠다
[플러그인 선언]
플러그인을 선언한 것
기본적으로 com.android.application
과 kotlinandroid
플러그인이 선언되어 있으며 필요에 따라 추가할 수 있음
plugins {
id ‘com.android.application’
id ‘kotlin-android’
}
[컴파일 버전 설정]
앱을 컴파일하거나 빌드할 때 적용할 버전을 설정
compileSdk 31
로 지정되어 있으면 안드로이드 SDK 31 버전을 적용해서 컴파일하라는 의미임
compileSdk 31
[앱의 식별자 설정]
applicationId
는 앱의 식별자를 설정함
이곳에 지정한 문자열은 앱의 식별자가 되므로 고유한 문자열로 지정함
만약 구글 플레이 스토어에 등록된 어떤 앱이 똑같은 식별 자를 이미 사용하고 있다면 이 앱은 플레이 스토어에 등록되지 않음
스마트폰에 식별자가 똑같은 앱이 설치되어 있다면 이 앱은 설치되지 않음
applicationId “com.example.androidlab”
[SDK 버전 설정]
targetSdk
는 개발할 때 적용되는 SDK 버전임
➡ 31로 지정하면 31 버전의 SDK로 개발한 다는 의미
minSdk
는 이 앱을 설치할 수 있는 기기의 최소 SDK 버전을 의미
➡ 만약 21로 지정하면 21 버전까지 지원한다는 의미이며 그 아래 버전의 기기에는 설치 되지 않음
➡ SDK 버전 설정은 뒤에서 API 레벨 호환성을 다룰 때 더 자세하게 소개함
minSdk 21
targetSdk 31
[앱의 버전 설정]
앱의 버전을 설정함
초깃값은 1이지만 앱이 사용자의 스마트폰에 설치되어 이용되다가 업데이트 될 때 이 버전을 올려 다시 배포함
versionCode 1
versionName “1.0”
[컴파일 옵션]
다음 코드는 개발 언어의 버전을 설정
참고로 자바 버전 선언을 생략하면 기본으로 1.6이 적용됨
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = ‘1.8’
}
[라이브러리 설정]
앱에서 이용하는 라이브러리의 버전을 설정
targetSdk에 명시한 안드로이드 SDK는 기본으로 적용되지만 그 외에 개발자가 추가하는 오픈소스 라이브러리나 구글의 androidx 라이브러리 등 SDK 라이브러리가 아닌 것들은 모두 dependencies에 선언해야 함
실제 개발할 때는 dependencies에 많은 라이브러리를 선언함
즉, 안드로이드 앱은 보통 안드로이드 SDK 라이브러리만으로 개발하지는 않습니다.
dependencies { implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
메인 환경 파일
AndroidManifest.xml
즉, ‘매니페스트 파일’ 은 안드로이드 앱의 메인 환경 파일임.
- 개발을 진행하면서 매니페스트 파일을 분석하고 수정하는 일이 많은데 안드로이드 시스템은이 파일에 설정한 대로 사용자의 폰에서 앱을 실행함.
- 즉, 매니페스트 파일은 개발부터 실행까지 중요한 역할을 함
- 매니페스트 파일에서 중요한 부분만 설명해 보겠음
[네임스페이스 선언: manifest]
<manifest>
: 매니페스트 파일의 루트 태그
xmlns
: XML의 네임스페이스 선언
➡ URL이 http://schemas.android.com/apk/res/android로 선언되었다면 안드로이드 표준 네임스페이스임
package
: 매니페스트 파일에 선언한 컴포넌트 클래스의 기본 패키지명
➡ 이후 매니페스트 파일에 선언되는 액티비티, 서비스 클래스 등의 경로는 이패키지명 이후부터 작성하면 됨
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.androidlab”>
[네임스페이스 선언: application]
<application>
: 태그는 앱 전체를 대상으로 하는 설정
icon
: <application>
태그에 있는 앱의 아이콘을 설정하는 속성
➡ 이곳에 지정한 이미지가 앱을 설치한 사용자의 폰에 보이는 실행 아이콘
➡ 예에서 icon
속성에 지정한 @mipmap/ic_launcher
는 res/mip map/ic_launcher.png
파일을 의미함
➡ XML의 속성값이 @
으로 시작하면 리소스를 의미함
label
속성
➡ 앱의 이름을 등록하는데 @string/app_name
으로 지정했으므로 res/values/ strings.xml
파일에 app_name
으로 등록된 문자열 리소스를 가리킴
theme
속성
➡ 설정 앱에 적용해야 하는 테마를 설정하는 것
➡ res/values/themes.xml
파일에 Theme.AndroidLab
이름으로 선언한 테마를 적용하겠다는 의미임
앞에서 살펴본 바와 같이 안드로이드 컴포넌트는 시스템에서 생명주기를 관리함.
그리고 시스템은 매니페스트 파일에 있는 대로 앱을 실행함
결국 컴포넌트는 매니페스트 파일에 등록해야 시스템이 인지함.
<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:roundIcon=”@mipmap/ic_launcher_round”
android:supportsRtl=”true”
android:theme=”@style/Theme.AndroidLab”>
(... 생략 ...)
</application>
[액티비티 선언]
액티비티는 <activity>
태그로, 서비스는 <service>
태그로, 브로드캐스트 리시버는 <receiver>
태그로, 그리고 콘텐츠 프로바이더는 <provider>
태그로 등록합니다.
컴포넌트 하나당 태그 하나로 등록하며 만약 액티비티가 10개라면 <activity>
태그를 10개 선언해야함.
name
속성
➡ 액티비티를 등록할 때 필수 속성
➡ name 속성에는 클래스 이름을 등록
➡ 예를 들어 name=”.MainActivity”
라고 했다면 MainActivity
클래스를 액티비티로 등록하겠다는 의미
➡ 클래스 이름 앞에 있는 점(.): 해당 클래스가 <manifest>
태그에 등록한 package 경로에 있다는 의미
<activity android:name=”.MainActivity”>
<android:exported="true">
<intent-filter>
<action android:name=”android.intent.action.MAIN” />
<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
리소스 폴더
res
폴더
- 앱의 리소스를 등록하는 목적으로 사용
- 모듈이 만들어지면 res 폴더 아래에 다음과 같은 폴더가 기본으로 생김
- drawable: 이미지 리소스
- layout: UI 구성에 필요한 XML 리소스
- mipmap: 앱 아이콘 이미지
- values: 문자열 등의 값으로 이용되는 리소스
[R.java
파일]
res
폴더 아래에 리소스를 만들면,
자동으로R.java
파일에 상수 변수로 리소스가 등록됨- 코드에서는 이 상수 변수로 리소스를 이용합니다.
R.java
는 개발자가 만드는 파일이 아니며 res 폴더에 있는 리소스를 보고 자동으로 만들어짐 - 예전 버전의 안드로이드 스튜디오에서는 R.java 파일을 찾아 확인해 볼 수 있었으나 버전이 오르고서는 이제 R.java 파일을 보여 주지는 않음
R.java
파일은 개발자가 직접 건드리지 않고 내부에서 리소스를 등록하기 위해 사용하기 때문- 예시
- 만약 그림처럼 개발자가
res/drawable
폴더에person1.png
파일과send.png
파일을 만들었다면,
이 리소스를 식별하기 위한 int형 변수가R.java
파일에 등록됨 - 그리고 코드에서 이 리소스 파일을 이용하려면
R.drawable.person1
과R.drawable.send
로 식별 R.java
파일에 각 폴더의 하위 클래스가 만들어지고 그안에 파일명을 기준으로 int형 변수가 자동으로 만들어짐- 따라서
res/drawable/send.png
파일이라면R.drawable.send
라고 이용함
- 만약 그림처럼 개발자가
[리소스 파일 규칙]
이처럼 안드로이드 리소스 파일이 R.java 파일에 상수 변수로 등록되어 이용되면서 다음과 같은 규칙이 생김
- res 하위의 폴더명은 지정된 폴더명을 사용해야 합니다.
- 즉, 이미지는 drawable 폴더를, UI 관련 XML 파일은 layout 폴더를 이용해야 함
- 각 리소스 폴더에 다시 하위 폴더를 정의할 수는 없습니다.
- 리소스 파일명은 자바의 이름 규칙을 위배할 수 없습니다.
- 자바 이름은 숫자로 시작할 수 없다는 규칙이 있으므로 리소스 파일명으로 a1.png는 가능하지만 1a.png는 불가능
- 리소스 파일명에는 알파벳 대문자를 이용할 수 없습니다.
- addUser.xml처럼 파일명에 알파벳 대문자를 사용하면 안됨
- 두 단어를 연결할 때는 add_user.xml처럼 밑줄(
_
)을 이용해 정의하는 것이 일반적
레이아웃 XML 파일
res/layout
폴더 아래 기본으로 만들어지는 activity_main.xml
파일은 화면을 구성하는 레이아웃 XML 파일임
이 파일을 열어 보면 <androidx.constraintlayout.widget.ConstraintLayout>
태그와 <TextView>
태그가 등록되어 있습니다. 두 태그에 관한 자세한 내용은 화면을 프로그래밍하는 방법을 설명하는 곳에서 다루기로 하고, 여기서는 화면을 구성하는 요소라고 알아 두면 됨
<TextView>
는 화면에 문자열을 출력하는 역할을 함
<TextView>
태그의 속성에 android:text=”Hello World!”
라고 선언되었는데 “Hello World!”라는 문자열을 출력하라는 의미임
결국 기본으로 만들어진 activivty_main.xml 파일은 화면에 “Hello World!”를 출력 하는 구성임
<?xml version=”1.0” encoding=”utf-8”?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=”http://schemas.android.com/apk/res/android”
xmlns:app=”http://schemas.android.com/apk/res-auto”
xmlns:tools=”http://schemas.android.com/tools”
android:layout_width=”match_parent”
android:layout_height=”match_parent”
tools:context=”.MainActivity”>
<TextView
android:id=”@+id/textView”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”Hello World!”
app:layout_constraintBottom_toBottomOf=”parent”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintRight_toRightOf=”parent”
app:layout_constraintTop_toTopOf=”parent” /> </androidx.constraintlayout.widget.ConstraintLayout>
메인 액티비티 파일
앞에서 살펴본 매니페스트 파일의 설정값에 따라 폰에 앱을 설치한 후 앱 아이콘을 터치하면 MainActivity.kt
파일이 실행됨
[메인 액티비티 파일]
파일 내용을 간략하게 살펴보면 AppCompatActivity
를 상속받아 MainActivity
라는 클래스를 정의함
AppCompatActivity
는 Activity
의 하위 클래스임
따라서 MainActivity
는 액티비티 컴포넌트 클래스임
즉, 이 클래스는 화면 출력을 목적으로 하는 액티비티 클래스라는 의미다
1) MainActivity
클래스가 실행되면 onCreate()
함수가 자동으로 호출되며,
2) onCreate()
함수 안의 구문을 실행
3) 여기서 setContentView()
함수는 매개변수에 지정한 내용을 액티 비티 화면에 출력함
4) 이번 코드에서는 R.layout.activity_main
으로 지정했으므로 res/ layout/activity_main.xml
파일에 구성한 내용을 화면에 출력
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}