[Android/Kotlin] BroadcastReceiver 에 대해서, LocalBroadcastManager 까지

곽의진·2023년 9월 9일
0

Android

목록 보기
5/17
post-custom-banner

✅ BroadcastReceiver 란?

BroadcastReceiver는 안드로이드 애플리케이션에서 시스템 또는 앱에서 발생하는 이벤트나 정보를 받아 처리할 수 있는 4대 컴포넌트 중 하나 입니다. BroadCastReceiver에서 캐치하는 이벤트는 시스템 레벨에서 발생할 수도 있고 (예: 배터리 부족, 시간 변경 등), 다른 앱 또는 동일 앱에서 발생할 수도 있습니다.

BroadcastReceiver는 일반적으로 Intent 객체를 사용하여 브로드캐스트 메시지를 받습니다. 이 메시지는 처리할 이벤트에 대한 정보와 데이터를 담고 있습니다.

✅ 장점과 단점

✓ 장점

  • Loose Coupling(느슨한 결합도): 다른 컴포넌트와의 강한 의존성 없이 이벤트를 수신할 수 있기 때문에 유지 보수 및 확장성 측면에서 긍정적입니다.
  • 시스템 이벤트 수신: 시스템 수준의 이벤트를 쉽게 캐치하여 처리할 수 있습니다.
  • 다중 수신: 하나의 이벤트를 여러 BroadcastReceiver에서 수신할 수 있습니다.
  • 리소스 효율성: 앱이 실행되지 않는 상태에서도 BroadcastReceiver는 작동할 수 있기 때문에, 필요한 경우에만 앱을 깨워 리소스를 절약할 수 있습니다

✓ 단점

  • 비동기성: BroadcastReceiver는 비동기적으로 동작하기 때문에 실행 순서를 보장할 수 없습니다.
  • 리소스 사용: 이벤트가 빈번하게 발생하면 리소스 사용이 증가할 수 있습니다.
  • 보안 이슈: 민감한 데이터를 전송할 때는 다른 앱에 의해 수신될 가능성이 있으므로 주의해야 합니다.
  • 복잡성 증가: 여러 BroadcastReceiver가 동일한 이벤트를 수신하면, 그 처리 로직이 복잡해질 가능성이 있습니다.

✅ 사용 예제

안드로이드에서 BroadcastReceiver를 등록하는 방법은 크게 정적 방법과 동적 방법이 있습니다.

✓ 정적 등록 (Static Registration)

정적으로 BroadcastReceiver를 등록하는 경우에는 AndroidManifest.xml 파일에 receiver 태그를 사용하여 등록합니다. 이 방법은 앱이 설치되는 순간에 시스템에 의해 자동으로 등록되며, 앱이 실행되지 않은 상태에서도 브로드캐스트를 받을 수 있습니다.

다음은 코틀린을 활용해 BroadcastReceiver 를 정적 등록으로 구현한 예제입니다.

class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        when(intent.action) {
            "MY_ACTION" -> {
                // Do something
                Log.d("MyReceiver", "Received MY_ACTION")
            }
            else -> {
                // Do nothing
            }
        }
    }
}

// Manifest
<receiver android:name=".MyReceiver">
    <intent-filter>
        <action android:name="MY_ACTION"/>
    </intent-filter>
</receiver>

✓ 동적 등록 (Dynamic Registration)

동적으로 BroadcastReceiver를 등록하는 경우에는 앱의 코드 내에서 registerReceiver() 메서드를 사용하여 등록합니다. 이 방법은 앱이 실행되고 있는 동안에만 브로드캐스트를 수신할 수 있습니다.

다음은 BroadcaastReceiver 를 동적 등록으로 구현한 예제입니다.

class MainActivity : AppCompatActivity() {
    private val myDynamicReceiver = MyDynamicReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 동적으로 BroadcastReceiver 등록
        val intentFilter = IntentFilter("MY_ACTION")
        registerReceiver(myDynamicReceiver, intentFilter)
    }

    override fun onDestroy() {
        // 등록 해제
        unregisterReceiver(myDynamicReceiver)
        super.onDestroy()
    }
}

class MyDynamicReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if ("MY_ACTION" == intent.action) {
            // Do something
        }
    }
}

🚨 주의사항: BroadcastReceiver를 사용시 적절한 시점에 register와 unregister 하지 않는 다면 크래시가 발생합니다.
onCreate() 에 register하였다면 onDestroy에 unregister를 해야하며,
onResume() 에 register하였다면 onStop에 unregister를 해야합니다.

✅ LocalBroadcastManager와 Context를 통해 register의 차이점

✓ LocalBroadcastManager

  • 프로세스 내부에서만 작동: 외부 앱과 통신할 수 없습니다.
  • 보안: 같은 앱 내에서만 브로드캐스트되므로 외부 앱에 의한 수신이나 공격의 위험이 적습니다.

✓ Context를 통한 Register

  • 프로세스 간 통신 가능: 다른 앱이나 시스템과 통신할 수 있습니다.
  • 보안 문제: 필터링을 잘 설정하지 않으면 보안에 취약할 수 있습니다.
// LocalBroadcastManager
LocalBroadcastManager.getInstance(this).registerReceiver(myReceiver, IntentFilter("MY_ACTION"))

// Context를 통한 Register
registerReceiver(myReceiver, IntentFilter("MY_ACTION"))

이렇게 각 BroadcastReceiver 등록 방법은 사용 목적과 프로젝트 상황에 따라 적절히 선택하여 사용할 수 있습니다.

🧐 BroadcastReceiver의 유연성과 다양성은 안드로이드 앱 개발에서 큰 장점이지만, 그만큼 복잡성의 증대 및 테스트 용이성 저하라는 책임도 큽니다. 따라서 앱의 목적과 요구사항을 충분히 이해한 상태에서 BroadcastReceiver를 구현하는 것이 중요합니다.

그렇기에 중요한 점은, 복잡한 시스템에서의 작은 변화도 올바른 이벤트 핸들링을 통해 효율적인 결과를 가져올 수 있다는 점입니다. BroadcastReceiver를 상황에 알맞게 활용하면, 더욱 발전된 앱의 프로세스를 구축할 수 있을 것이라고 생각합니다.

profile
Android Developer
post-custom-banner

0개의 댓글