스터디

[Manifest-Android] 4. Context

참깨빵위에참깨빵_ 2025. 6. 13. 01:05
728x90
반응형

앱 환경 또는 상태를 나타내며 앱 리소스, 클래스에 대한 접근을 제공하는 요소다. 컴포넌트가 DB, 리소스 등에 접근할 수 있게 해 주고 액티비티 시작, 레이아웃 inflate 같은 작업에선 필수로 쓰인다.

컨텍스트 종류는 여러 개가 있다.

 

Application Context

 

앱 전체 생명주기에 연결되는 컨텍스트고 현재 액티비티 / 프래그먼트처럼 독립적인 생명주기가 긴 전역 컨텍스트가 필요할 때 사용한다. getApplicationContext()로 가져와 사용하고 쉐어드, DB 등 앱 전체 리소스에 접근하거나 브로드캐스트 리시버 등록, 앱 생명주기 내내 유지되는 라이브러리, 컴포넌트 초기화에 사용한다.

 

Activity Context(액티비티의 this 객체)

 

액티비티 생명주기에 연결되고 리소스 접근, 다른 액티비티 시작, 액티비티 레이아웃 inflate에 쓰인다.

 

Service Context

 

서비스 생명주기에 연결되고 네트워크 작업 실행, 음악 재생 등 백그라운드 작업에 쓰인다.

 

Broadcast Context

 

브로드캐스트 리시버 호출 시 제공된다. 생명주기가 짧고 일반적으로 특정 브로드캐스트에 응답 시 사용된다. 짧은 생명주기를 가진 만큼 오래 실행되는 작업을 이 컨텍스트로 실행하면 안 된다.

 


 

컨텍스트를 잘못 쓰면 메모리 누수, 크래시 등 문제가 발생할 수 있다. 이걸 피하려면 모범 사례를 이해하는 게 좋은데 가장 일반적인문제는 액티비티 / 프래그먼트 컨텍스트 참조를 생명주기 이후에도 유지하는 것이다.

이 때 가비지 컬렉터가 컨텍스트나 관련 리소스의 메모리를 회수 못 해서 메모리 누수가 발생할 수 있다. 아래 코드는 메모리 누수를 유발한다.

 

object Singleton {
    var context: Context? = null
}

 

컨텍스트를 써야 하는 생명주기가 긴 객체에선 ApplicationContext를 사용한다. 컨텍스트 타입에 따라 용도가 다르기 때문에 적절하게 사용하는 게 중요하다.

특히 컨텍스트는 리소스 접근하거나 UI와 상호작용하는 메인 쓰레드를 위해 설계됐다. 백그라운드에서 쓰면 크래시, 쓰레딩 문제가 발생할 수 있다.

UI 관련 컨텍스트 리소스와 상호작용하려면 그 전에 메인 쓰레드로 전환하는 게 좋다. withContext나 runOnUiThread가 선택지가 될 수 있다.

또한 익명 내부 클래스, 콜백은 실수로 컨텍스트의 참조를 가질 수 있으니 사용에 주의하라.

 

ContextWrapper

 

컨텍스트 객체를 래핑해서 컨텍스트에 호출을 위임하는 기능을 제공하는 클래스. 컨텍스트의 원래 동작을 수정하거나 확장하는 역할을 한다. 이걸 쓰면 기본 컨텍스트를 안 바꿔도 기능 커스텀이 가능하다.

사용 사례는 아래와 같다.

 

  • 커스텀 컨텍스트 : 다른 테마를 적용하거나 리소스를 특수 처리하는 등 어떤 목적을 위해 커스텀 컨텍스트를 만들어야 하는 경우 사용
  • 동적 리소스 처리 : 문자열, dimen, style 등 리소스를 동적 제공하거나 수정하기 위해 컨텍스트를 래핑하는 처리가 필요할 수 있다
  • 종속성 주입 : hilt는 이걸 써서 컴포넌트에 커스텀 컨텍스트를 넘긴다

 

이걸 사용해서 얻는 이점은

 

  • 재사용성 : 래퍼 클래스에 커스텀 로직을 캡슐화해서 여러 컴포넌트에서 재사용 가능
  • 캡슐화 : 원래 컨텍스트 구현을 안 바꿔도 동작 수정 가능
  • 호환성 : 이전 버전과 호환성을 유지하고 기존 컨텍스트 객체와도 잘 작동함

 

액티비티에서 this vs baseContext

 

둘 다 컨텍스트에 대한 접근을 제공하지만 용도가 다르고 안드로이드 컨텍스트 계층 구조 수준도 다르다.

액티비티에서 this는 액티비티 클래스의 현재 인스턴스를 참조한다. 액티비티는 ContextWrapper의 하위 클래스라 간접적으로 Context의 하위 클래스가 된다. 화면 이동, 다이얼로그 표시 등에 사용할 수 있다.

 

baseContext는 액티비티가 상속하는 ContextWrapper 클래스의 일부다. 일반적으로 컨텍스트 메서드의 핵심 구현을 제공하는 ContextImpl의 인스턴스다.

getBaseContext()로 접근하며 직접 쓰는 경우는 거의 없고 커스텀 ContextWrapper 구현으로 작업하거나 래핑된 컨텍스트 뒤에 있는 원래 컨텍스트를 참조해야 할 때 써야 할 가능성이 높아진다.

 

둘의 차이는

 

  • scope : this는 현재 액티비티 인스턴스와 그 생명주기를 나타내고 baseContext는 액티비티가 빌드되는 하위 수준의 컨텍스트를 나타낸다
  • 사용 : 액티비티 시작 등 액티비티 생명주기 or UI 연관 작업에서 일반적으로 this를 사용한다. baseContext는 컨텍스트 핵심 구현과 상호작용할 경우 쓰인다
반응형