개발/안드로이드

[안드로이드 앱의 기본구조] 3. 앱 구성 파일 분석

세크레투스 2025. 1. 28. 23:53
반응형
SMALL

3. 앱 구성 파일 분석

안드로이드 프로젝트를 만들면 자동으로 완성되는 "Hello World!" 문자열 출력 앱을 살펴보면서 앱을 구성하는 파일과 코드를 분석해보자.

 

프로젝트의 폴더 구성 알아보기

안드로이드 앱 프로젝트를 만들면 많은 폴더와 파일이 생성되지만, 대부분은 빌드 도구와 관련된 것이다.

개발자가 관심을 둬야 할 파일은 프로젝트 폴더에서 [모듈명 -> src -> main] 안에 있다.

그런데, 안드로이드 스튜디오의 프로젝트 탐색 창은 윈도우 파일 탐색기처럼 모든 폴더와 파일을 보여 주지 않는다. 개발자가 분석하거나 작성해야 하는 폴더와 파일만 보여준다.

프로젝트를 만들면 app이라는 모듈이 자동으로 생성된다. 모듈 하나가 앱 하나이며, 프로젝트는 여러 모듈을 묶어서 관리하는 개념이다.

하나의 프로젝트에는 자동으로 만들어지는 app 모듈 이외에 여러 모듈을 추가할 수 있다.

모듈은 앱 단위이므로 새로운 모듈을 추가한다는 것은 새로운 앱을 개발한다는 것과 같다.

 

모듈의 폴더 구성 알아보기

이름 설명
build.gradle.kts 빌드 설정 파일
AndroidManifest.xml 앱의 메인 환경 파일
res 리소스 폴더
activity_main.xml 레이아웃 XML 파일
MainActivity.kt 메인 액티비티 파일

 

그래들 빌드 설정 파일

그래들(gradle)은 안드로이드 앱의 빌드 도구이다. 그래들의 설정 파일이 바로 build.gradle.kts이며, (이하 '그래들 파일') 앱을 빌드라는 데 필요한 설정을 이 파일에 등록한다.

그래들 파일은 안드로이드 스튜디오의 탐색 창에서 코끼리 모양의 아이콘이 있는 [Gradle Scripts]에서 찾을 수 있다.

탐색창을 보면  build.gradle.kts 파일이 2개 있다. 하나프로젝트 수준의 build.gradle.kts (Project: AndroidLab)이고, 또 하나모듈 수준의 build.gradle.kts (Module: app) 이다. 모듈은 앱을 의미하므로, 대부분의 빌드 설정은 모듈 수준의 그래들 파일에 작성한다.

모듈 수준의 그래들 파일을 열어보면 몇가지 설정이 자동 등록돼 있다. 이 값을 수정하거나 새로 추가하면서 빌드 환경을 설정한다.

  • 플러그인 선언
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
}

위의 코드는 플러그인을 선언한 것이다. 기본적으로  android.application과 kotlin.android 플러그인이 선언되어 있으며 필요에 따라 추가 가능하다.

 

  • 컴파일 버전 설정
compileSdk = 34

이 코드는 앱을 컴파일하거나 빌드할 때 적용할 버전을 설정한다. compileSdk = 34로 지정되어 있으면 안드로이드 SDK 34 버전을 적용해서 컴파일하라는 의미이다.

 

  • 앱의 식별자 설정
applicationId = "com.example.androidlab"

applicationId는 앱의 식별자를 설정한다. 이곳에 지정한 문자열은 앱의 식별자가 되므로 고유한 문자열로 지정해야 한다.

만약에 구글 플레이 스토어에 등록된 어떤 앱이 똑같은 식별자를 이미 사용하고 있다면, 이 앱은 플레이 스토어에 등록되지 않는다.

또한, 스마트폰에 식별자가 똑같은 앱이 설치되어 있다면 이 앱은 설치되지 않는다.

 

  • SDK 버전 설정
minSdk = 24
targetSdk = 34

targetSdk는 개발할 때 적용되는 SDK 버전이다.

minSdk는 이 앱을 설치할 수 있는 기기의 최소 SDK 버전이다.

 

  • 앱의 버전 설정
versionCode = 1
versionName = "1.0"

이 코드는 앱의 버전을 설정하는 코드이다.

초깃값은 1이지만, 앱이 사용자의 스마트폰에 설치되어 이용되다가 업데이트 될 때 이 버전을 올려서 다시 배포시킨다.

 

  • 컴파일 옵션
compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
        jvmTarget = "11"
}

이 코드는 개발 언어의 버전을 설정한다. 참고로 자바 버전 선언을 생략하면 기본적으로 1.6이 적용된다.

 

  • 라이브러리 설정
dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)
    implementation(libs.androidx.activity)
    implementation(libs.androidx.constraintlayout)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}

이 코드는 앱에서 이용하는 라이브러리의 버전을 설정한다.

안드로이드 앱은 보통 안드로이드 SDK 라이브러리만으로 개발하진 않는다.

 

메인 환경 파일

AndroidManifest.xml은 안드로이드 앱의 메인 환경 파일이다. (이하 '매니페스트 파일')

개발을 진행하면서 매니페스트 파일을 분석하고 수정할 일이 많은데, 안드로이드 시스템은 이 파일에 설정한 대로 사용자의 폰에서 앱을 실행한다.

즉, 매니페스트 파일은 개발부터 실행까지 중요한 역할을 한다.

  • 네임스페이스 선언
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

<manifest>는 매니페스트 파일의 루트 태그다. 그리고 xmlns는 XML의 네임스페이스 선언이며, URL이 http://schemas.android.com/apk/res/android로 선언되었다면 안드로이드 표준 네임스페이스이다. 

 

  • 네임스페이스 선언
<application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        ...
</application>

<application> 태그는 앱 전체를 대상으로 하는 설정이다. <application> 태그에는 앱의 아이콘을 설정하는 icon 속성이 있는데, 이곳에 지정한 이미지가 앱을 설치한 사용자의 폰에 보이는 실행 아이콘이다. 예에서 icon 속성에 지정한 @mipmap/ic_launcher는 res/mipmap/ic_launcher.png 파일을 의미한다. XML의 속성값이 @으로 시작하면 리소스를 의미한다.

label 속성에는 앱의 이름을 등록하는데, @String/app_name으로 지정했으므로 res/values/string.xml 파일에 app_name으로 등록된 문자열 리소스를 가리킨다. theme 설정은 앱에 적용해야 하는 테마를 설정하는 것으로 res/values/themes.xml 파일에 Theme.AndroidLab 이름으로 선언한 테마를 적용하겠다는 의미이다.

앞에서 언급한 바와 같이 안드로이드 컴포넌트는 시스템에서 생명주기를 관리한다. 그리고 시스템은 매니페스트 파일에 있는 대로 앱을 실행한다. 결국, 컴포넌트는 매니페스트 파일에 등록해야 시스템이 인지한다.

 

  • 액티비티 선언
<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>

액티비티는 <activity> 태그로, 서비스는 <service> 태그로, 브로드캐스트 리시버는 <receiver> 태그로, 그리고 콘텐츠 프로바이더는 <provider> 태그로 등록한다.

컴포넌트 하나 당 태그 하나로 등록하며, 만약 액티비티가 10개라면 <activity> 태그를 10개 선언해야 한다.

액티비티를 등록할 때 필수 속성은 name이다. name 속성에는 클래스 이름을 등록한다.

클래스 이름 앞에 잇는 점(.)은 해당 클래스가 <manifest>에 등록한 package 경로에 있다는 의미이다.

<intenet-filter> 태그는 생략할 수 있다.

<intent-filter>가 선언되고, 그 안에 <action> 태그의 name 값이 android.intent.action.MAIN 문자열로, <category> 태그의 name 값이 android.intent.category.LAUNCHER 로 선언되면 이 액티비티는 앱 아이콘을 클릭했을 때 실행되는 액티비티라는 의미이다.

 

리소스 폴더

res폴더는 앱의 리소스를 등록하는 목적으로 사용된다. 모듈이 만들어지면 res 폴더 아래에 다음과 같은 폴더가 기본으로 생긴다.

  • drawable : 이미지 리소스
  • layout : UI 구성에 필요한 XML 리소스
  • mipmap : 앱 아이콘 이미지
  • values : 문자열 등의 값으로 이용되는 리소스

res 폴더 아래에 리소스를 만들면 자동으로 R.java 파일에 상수 변수로 리소스가 등록되며, 코드에서는 이 상수 변수로 리소스를 이용한다.

R.java는 res 폴더에 있는 리소스를 보고 자동으로 만들어진다.

R.java 파일은 개발자가 직접 건드리지 않고 내부에서 리소스를 등록하기 위해 사용된다.

 

만약에 개발자가 res/drawable 폴더에 person1.png 파일과 send.png 파일을 만들었다면 이 리소스를 식별하기 위한 int형 변수가 R.java 파일에 등록된다.

그리고 코드에서 이 리소스 파일을 이용하려면 R.drawable.person1과 R.drawable.send로 식별한다.

나머지 리소스들도 마찬가지이다.

 

이처럼 안드로이드 리소스 파일이 R.java 파일에 상수 변수(int 형)으로 등록되어 이용되면서 다음과 같은 규칙이 생긴다.

  • res 하위 폴더명은 지정된 폴더명을 사용해야 한다.
  • 각 리소스 폴더에 다시 하위 폴더를 정의할 수 없다.
  • 리소스 파일명은 자바의 이름 규칙을 위배할 수 없다. (자바에서는 숫자로 파일명이 시작할 수 없다.)
  • 리소스 파일명에는 알파벳 대문자를 이용할 수 없다. (ex. addUser.xml(x), add_user.xml(o))

 

레이아웃 XML 파일

res/layout 폴더 아래 기본으로 만들어지는 activity_main.xml 파일은 화면을 구성하는 레이아웃 XML 파일이다.

  • 레이아웃 XML 파일
<?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

메인 액티비티 파일

매니페스트 파일의 설정 값에 따라 폰에 앱을 설치한 후 앱 아이콘을 터치하면 MainActivity.kt 파일이 실행된다.

  • 메인 액티비티 파일
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
    }
}

코드를 간단히 살펴보자.

 

AppCompatActivity를 상속받아 MainActivity 클래스를 정의했다.

AppCompatActivity는 Activity의 하위 클래스이다. 따라서, MainActivity는 액티비티 컴포넌트 클래스이다.

즉, 이 클래스는 화면 출력을 목적으로 하는 액티비티 클래스이다.

 

MainActivity 클래스가 실행되면 onCreate() 함수가 자동으로 호출되며, onCreate() 함수 안의 구문을 실행한다.

여기서 setContentView() 함수는 매개변수에 지정한 내용을 액티비티 화면에 출력한다.

이 코드에서는 R.layout.activity_main으로 지정했으므로 res/layout/activity_main.xml 파일에 구성한 내용을 화면에 출력한다.

 

enableEdgeToEdge()는 액티비티 화면이 상단의 배터리 표시가 있는 영역(=Status Bar)과 하단의 안드로이드 버튼이 있는 영역(=Navigation Bar)까지 나오게 한다.

또한, setOnApplyWindowInsetsListener() 부분은 액티비티에 출력되는 내용이 Navigation Bar 등과 겹치지 않게 하기 위한 설정이다.

enableEdgeToEdge(), setOnApplyWindowInsetsListener()를 이용한 설정이 필요없다면 삭제해도 무관하다.

반응형
LIST