Android에서 Context는 정말 자주 볼 수 있는 것 같다.
Toast를 띄울 때라던가, 단순 Activity끼리 이동할 때라던가,
혹은 RoomDB에서 DB 인스턴스를 만들 때 등 Context가 매개변수로 들어가게 된다.
Toast.makeText(context, text, duration).show()
Context은 무엇인가?
ApplicationContext도 있던데, 언제 쓰는걸까?
오늘은 이 두 가지를 중점으로 정리해보려고 한다.
Context
Context란?
Context를 단어 그대로 해석하면 맥락이며, 공식 문서에는 다음처럼 알려주고 있다.
Interface to global information about an application environment.(application 환경에 대한 전역 정보 인터페이스)
또한 Context를 통해서 리소스나 클래스 접근, activity 실행, broadcast나 Intent 수신이 가능하다고 알려준다.
"맥락"이라는 의미에서 다시 생각하면 결국 Context는 Application의 현재 상태(맥락)이라고 이해하면 될 것 같다.
그래서 Application 정보를 알고 싶을 때 Context를 가지고 오는거고.
R.String, R.Color 등 리소스를 가져오려면 Context가 필요했는데,
리소스 외에도 Database, SharedPreferences 등 시스템 자원에 접근하기 위해선 Context가 필요하다.
Context의 상속 구조
Context의 상속구조는 아래와 같으며
Application, Service, Activity는 모두 Context를 상속받고 있음을 알 수 있다.
View.getContext()를 호출하면 View를 가진 Activity의 Context를 가져온다.
혹은 Service.getBaseContext()를 호출하면 자신(Service)의 Context를 반환한다.
이 때 Context는 Activity 혹은 Service의 lifecycle을 따르게 된다.
그러나 만약 Context가 필요한 객체가 앱이 살아있는 내내 필요하다면?
Application Context
Application Context는 getApplicationContext()를 호출했을 때 얻을 수 있다.
공식 문서에서 해당 함수는 다음을 return 한다고 알려준다.
Return the context of the single, global Application object of the current process.(현재 Process의 단일 전역 Application object의 Context를 return)
덧붙여 현재 Component가 아닌, Process의 수명에 연결된 현재 Context와 수명 주기가 분리된 Context가 필요한 경우에만 사용하라고 알린다.
이게 대체 뭔말인고 하니
ApplicationContext는 전역(global)으로 사용하는 Context, 싱글톤(Single) 인스턴스라고 한다.
Activity에서 getApplicationContext()으로 가져오는 Context가 아닌 Activity Context는 Activity의 lifecycle과 연결되어 있다.
때문에 Activity Context를 사용하는 곳이 Activity가 종료되어도 계속 남아있는다면
불필요한 참조가 생겨 메모리 누수 문제가 발생한다.
이러한 경우(=Context를 사용하는 객체가 싱글톤인 경우)에는 ApplicationContext를 쓰는 게 좋다는 것.
ApplicationContext를 사용하는 대표적 예시로 위에서 언급한 RoomDB의 데이터베이스를 초기화할 때.
해당 Database는 Singleton으로 구현하기 때문에 Context가 아닌 ApplicationContext를 사용하게 된다.
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database-name"
).build()
그렇다면 반대로 Context가 필요할 때마다 ApplicationContext으로 다 사용해도 될까?
아니다.
직접 확인하지 않았지만 ApplicationContext가 완전하지 않다는 이야기가 있고(Dialog 등 주로 GUI 관련해서 실패한단다)(출처),
Activity Context와 다르게 ApplicationContext는 앱 프로세스가 살아있는 동안 계속 남아있어 가비지 컬렉터가 수집하지 않는다.
때문에 메모리에서 할당 해제하지 않는다면 메모리 누수가 발생할 수 있다.
요약
- Context란?
- application의 현재 상태, 즉 앱 프로세스의 맥락
- 리소스, 데이터베이스, SharedPreferences 등 시스템 자원에 접근하기 위해 필요
- Activity, Service, Application은 Context를 상속받음
- ApplicationContext
- getApplicationContext()로 얻을 수 있는 Context
- 전역으로 사용하는 Context로, 싱글톤 인스턴스
- Context를 사용하는 객체가 싱글톤인 경우 메모리 누수 방지를 위해 ApplicationContext를 사용
- 그 외에 Activity가 파괴될 때 같이 파괴되거나, GUI와 관련있다면 Activity Context를 사용
참고 자료
위에는 두 가지 정도만 언급했지만, 그 밖에도 Context를 잘못 사용했을 때 메모리 누수가 되는 경우가 많다고 한다.
다만 Context를 호출한 객체의 수명주기를 고려한다면 이를 방지할 수 있다!로 결론지어본다.
'Android' 카테고리의 다른 글
[적용기] Clean Architecture는 정말 좋을까? (2) | 2023.05.13 |
---|---|
[적용기] MVVM ViewModel과 AAC ViewModel (4) | 2023.05.10 |
[TIL/개념] Activity와 Fragment (2) - Fragment와 Fragment의 lifecycle (0) | 2023.03.21 |
[TIL/개념] Activity와 Fragment (1) - Activity와 Activity의 lifecycle (0) | 2023.03.21 |
[TIL/개념] 의존성 주입(Dependency injection, DI) 기초 (0) | 2023.03.09 |