안드로이드 Application 객체와 Manifest

aufcl4858·2025년 8월 17일
post-thumbnail

Application 클래스란 무엇인가?

Application 클래스는 안드로이드 앱의 전역 상태를 관리하는 베이스 클래스다. 앱이 시작될 때 가장 먼저 생성되고, 앱이 완전히 종료될 때까지 메모리에 유지되는 싱글톤 객체라고 보면 된다.

주요 특징

생명주기: 모든 Activity, Service, BroadcastReceiver보다 먼저 생성되고 나중에 소멸된다. 앱 전체의 생명주기와 동일하다고 생각하면 쉽다.

전역 접근: 앱 어디서든 접근 가능한 전역 데이터나 설정을 저장하기에 적합하다.

Application의 주요 사용 사례

실무에서 Application 클래스는 다음과 같은 용도로 활용된다

전역 리소스 관리: 앱 전체에서 공유하는 이미지 캐시, 사용자 로그인 상태, 앱 설정값(다크모드, 언어설정 등), 네트워크 상태 등을 관리한다. 이런 데이터들은 여러 화면에서 접근해야 하고 앱이 실행되는 동안 지속되어야 하기 때문에 Application에서 관리하는 것이 적절하다.

컴포넌트 초기화: Firebase, Crashlytics, 분석 도구 등 앱 전체에서 사용하는 라이브러리들을 앱 시작 시점에 초기화한다. 이런 라이브러리들은 한 번만 초기화하면 되고, 가능한 한 빨리 초기화되어야 하므로 Application.onCreate()에서 처리하는 것이 일반적이다.

의존성 주입 컨테이너: Retrofit 인스턴스, Database 인스턴스, Repository 객체 등 앱 전체에서 사용할 싱글톤 객체들을 생성하고 관리한다. Dagger, Hilt 같은 DI 프레임워크를 사용하지 않는 경우 Application에서 간단한 DI 컨테이너 역할을 수행할 수 있다.

앱 생명주기 모니터링: ActivityLifecycleCallbacks를 등록해서 앱이 포그라운드로 전환되거나 백그라운드로 이동할 때를 감지하고, 그에 따른 작업(사용자 세션 갱신, 알림 정리, 백그라운드 작업 시작/중지 등)을 수행한다.

메모리 관리 및 성능 최적화: 시스템의 메모리 부족 상황을 감지하고 캐시를 정리하거나 불필요한 리소스를 해제하는 등의 최적화 작업을 담당한다.

class MyApplication : Application() {
    var isUserLoggedIn = false
    var currentTheme = "light"
    
    override fun onCreate() {
        super.onCreate()
        // 앱 시작 시 초기화 작업
        initializeLibraries()
        setupGlobalConfiguration()
    }
    
    // os Version 14 미만에서 사용
    override fun onLowMemory() {
        super.onLowMemory()
        // 메모리 부족 시 처리
        clearCaches()
    }
    
    override fun onTrimMemory(level: Int) {
	    super.onTrimMemory(level)
        // 메모리 상태에 따른 분기
    }
}

Application vs Activity: 생명주기와 리소스 관리의 차이점

이 부분이 많은 개발자들이 헷갈려하는 지점이다. Application과 Activity는 생명주기와 리소스 관리 측면에서 명확한 차이가 있다.

지속성의 차이

  • Application: 앱이 살아있는 동안 계속 존재
    • 앱 실행 시 최초 1회만 생성
    • MainActivity -> SecondActivity -> MainActivity로 이동해도 Application.onCreate()는 처음 한 번만 호출
  • Activity: 사용자의 화면 전환에 따라 생성/소멸
    • 화면 진입할 때마다 생성
    • MainActivity -> SecondActivity -> MainActivity로 이동하면 MainActivity.onCreate()가 두 번 호출됨

리소스 관리 전략

Application에서는 장기 메모리 관리에 집중한다

override fun onTrimMemory(level: Int) {
    super.onTrimMemory(level)
    when (level) {
        TRIM_MEMORY_UI_HIDDEN -> {
            // UI가 숨겨졌을 때 - 캐시 일부 해제
            imageCache.trimToSize(imageCache.size() / 2)
        }
        TRIM_MEMORY_COMPLETE -> {
            // 앱이 종료될 가능성 높음 - 모든 캐시 해제
            imageCache.evictAll()
        }
    }
}

Activity에서는 단기 메모리 관리에 집중한다

override fun onPause() {
    super.onPause()
    // 화면이 보이지 않을 때 메모리 절약
    largeBitmap?.recycle()
}

override fun onDestroy() {
    super.onDestroy()
    // 액티비티 종료 시 모든 리소스 정리
    mediaPlayer?.release()
}

Application 사용 시 주의사항

Application 클래스를 잘못 사용하면 심각한 문제가 발생할 수 있다. 특히 메모리 누수는 주의해야 할 부분이다.

절대 하면 안 되는 것들:

class MyApplication : Application() {
    // ❌ Activity Context 저장 - 메모리 누수!
    private var activityContext: Context? = null
    
    // ❌ View나 Activity 참조 - 메모리 누수!
    private var currentActivity: Activity? = null
    private var someView: View? = null
}

무거운 작업은 백그라운드에서:

override fun onCreate() {
    super.onCreate()
    
    // ❌ UI 스레드에서 무거운 작업 - 앱 시작 지연
    // heavyInitialization()
    
    // ✅ 백그라운드에서 초기화
    GlobalScope.launch(Dispatchers.IO) {
        heavyInitialization()
    }
}

onTerminate()는 신뢰하지 말 것:

override fun onTerminate() {
    super.onTerminate()
    // ❌ 이 메서드는 실제 기기에서 호출되지 않음
    // 중요한 정리 작업을 여기에 두면 안 됨
}

AndroidManifest.xml의 역할

AndroidManifest.xml은 앱의 신분증 같은 역할을 한다. 안드로이드 시스템이 앱을 실행하기 전에 반드시 알아야 하는 모든 정보가 담겨 있다.

주요 목적

  1. 앱 컴포넌트 선언: Activity, Service, BroadcastReceiver, ContentProvider
  2. 권한 요청: 인터넷, 카메라, 위치 정보 등
  3. 앱 메타데이터 정의: 이름, 아이콘, 테마 등
  4. 하드웨어/소프트웨어 요구사항: 최소 SDK, 필수 하드웨어 기능
  5. Intent Filter 정의: 다른 앱과의 상호작용 방식
<application
    android:name=".MyApplication"
    android:label="@string/app_name"
    android:icon="@mipmap/ic_launcher">
    
    <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>
    
    <service
        android:name=".BackgroundService"
        android:exported="false" />
</application>

Intent Filter를 통한 앱 상호작용

Intent Filter는 안드로이드 앱들이 서로 소통할 수 있게 해주는 핵심 메커니즘이다. 다른 앱에서 보내는 암시적 Intent를 받을 수 있게 해준다.

이미지 공유 받기:

<activity android:name=".ImageShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="image/*" />
    </intent-filter>
</activity>

웹 링크 처리 (Deep Link):

<activity android:name=".ProductDetailActivity">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https"
              android:host="myshop.com"
              android:pathPattern="/product/.*" />
    </intent-filter>
</activity>

이렇게 설정하면 브라우저에서 https://myshop.com/product/123 링크를 클릭했을 때 우리 앱의 ProductDetailActivity가 실행된다.

Activity 등록의 중요성

Manifest에 Activity를 등록하지 않으면 어떻게 될까? 답은 간단하다. 런타임 에러가 발생한다.

// 등록되지 않은 Activity를 실행하려고 하면
val intent = Intent(this, UnregisteredActivity::class.java)
startActivity(intent) // ❌ ActivityNotFoundException 발생!

에러 메시지도 친절하게 알려준다

ActivityNotFoundException: Unable to find explicit activity class 
{com.example.myapp/com.example.myapp.UnregisteredActivity}; 
have you declared this activity in your AndroidManifest.xml?

따라서 새로운 Activity를 만들 때마다 반드시 Manifest에 등록해야 한다

<activity
    android:name=".NewActivity"
    android:exported="false" />

마무리

Application 클래스와 AndroidManifest.xml은 안드로이드 앱의 기초가 되는 핵심 컴포넌트다. Application은 앱의 전역 상태와 장기간 지속되는 리소스를 관리하고, Manifest는 시스템에게 앱의 구조와 요구사항을 알려주는 역할을 한다.

이 둘을 제대로 이해하고 활용하면 더 안정적이고 효율적인 안드로이드 앱을 개발할 수 있다. 특히 메모리 누수 방지와 적절한 리소스 관리는 앱의 성능에 직접적인 영향을 미치므로 항상 주의깊게 다뤄야 한다.

개발하면서 "이게 Application에 들어가야 하나, Activity에 들어가야 하나?" 고민이 든다면, 그 데이터나 기능이 앱 전체에서 지속적으로 필요한지, 아니면 특정 화면에서만 필요한지를 생각해보자. 그러면 답이 나올 것이다.

profile
데브누누

0개의 댓글