네트워크_상태에_따라_MyPage_UI_변경_작업 - boostcampwm-2024/and04-Nature-Album GitHub Wiki
-
MyPage
화면에서 동기화 기능과 친구 기능 UI를 네트워크 연결 상태에 따라 동적으로 변경. - 네트워크 상태를 실시간으로 추적하여 UI 업데이트를 반영하도록 설계.
-
ConnectivityManager
는 네트워크 상태를 확인하거나 상태 변화를 감지할 수 있는 주요 클래스이다. - 네트워크 상태를 확인하려면
getNetworkCapabilities()
를 사용하며, 실시간 상태 변화를 감지하려면NetworkCallback
을 등록하여 이벤트를 수신한다.
API | 설명 | 사용 시기 |
---|---|---|
getNetworkCapabilities() |
현재 네트워크 상태를 즉시 확인. | 단순한 상태 확인이 필요할 때 |
registerDefaultNetworkCallback() |
앱이 사용하는 기본 네트워크의 상태 변화를 모니터링. | 앱의 현재 연결 상태를 추적해야 할 때 |
registerNetworkCallback() |
특정 네트워크 조건(Wi-Fi, 모바일 데이터 등)에 따라 상태 변화를 모니터링. | 특정 조건의 네트워크 상태를 세부적으로 모니터링해야 할 때 |
메서드 | 특징 | 사용 이유 |
---|---|---|
registerDefaultNetworkCallback() |
앱의 기본 네트워크 상태를 추적하며, 단일 네트워크 상태를 중심으로 동작. | 현재 연결 상태를 즉시 반영하며, 모든 UI에서 단일 네트워크 상태를 필요로 할 때 적합. |
registerNetworkCallback() |
특정 조건에 맞는 네트워크를 추적 가능. 예: Wi-Fi, 셀룰러 데이터, VPN 등. | 특정 네트워크 조건을 구분하여 여러 네트워크를 동시에 관리해야 하는 경우 적합. |
-
NetworkCapabilities
는 네트워크의 전송 유형과 기능 정보를 캡슐화하는 객체이다.-
전송 유형 확인:
TRANSPORT_WIFI
,TRANSPORT_CELLULAR
와 같은 상수를 사용하여 네트워크 전송 유형을 확인.caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
-
기능 확인: 네트워크가 지원하는 고급 기능(FULL_DUPLEX, VPN 등)을 확인.
-
- [Android 네트워크 상태 확인 공식 문서](https://developer.android.com/develop/connectivity/network-ops/reading-network-state?hl=ko)
- [블로그: Android에서 네트워크 연결 감지하기](https://jja2han.tistory.com/472)
- [네트워크 콜백 활용 사례](https://colinch4.github.io/2023-12-20/10-08-26-060110-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%97%90%EC%84%9C-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%97%B0%EA%B2%B0-%EB%A6%AC%EC%8A%A4%EB%84%88-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0/)
- 팀원이 작성한
NetworkState
는 네트워크 상태를 즉시 확인할 수 있는 간단한 유틸리티로, Context에 의존하지 않고 앱 어디에서든 사용할 수 있었다. - 그러나 네트워크 연결 상태가 변할 때 이를 실시간으로 감지하거나 UI에 반영하는 기능이 없었다.
-
동기화 기능과 친구 기능은 네트워크 상태에 따라 즉각적인 UI 변경이 필요하였으나, 기존
NetworkState
는 이 요구를 충족하지 못했다.
-
실시간 네트워크 상태 관리 필요
- 네트워크 상태가 변할 때 이를 감지하고 UI에 반영해야 한다.
- 이를 위해
StateFlow
와 네트워크 콜백을 사용하는 구조가 필요하다.
-
결합도 관리
-
NetworkManager
를 UI에서 직접 호출하면 Navigation 등 다른 요소와 결합도가 높아질 수 있다. - 따라서
ViewModel
을 통해 네트워크 상태를 전달하여 결합도를 낮추는 방식으로 설계했다.
-
-
다양한 요구사항 대응
- 단순히 네트워크 상태를 확인해야 하는 경우와 실시간 추적이 필요한 경우를 구분하여 관리.
-
NetworkState
와NetworkManager
를 병행 사용하여 각각의 요구사항에 대응할 수 있도록 설계했다.
- 초기에는
NetworkManager
를 UI에서 직접 호출하려고 했다. - Navigation에서
NetworkManager
를 주입하기 위해 매번 명시적으로 전달해야 했으며, 이로 인해 코드 결합도가 높아지고 유지보수가 어려워졌다. - 또한,
NetworkManager
의 기능을 확장하거나 여러 상태를 관리해야 할 경우, 이 방식은 확장성 측면에서 한계를 보일 가능성이 있었다.
- Navigation과의 결합도를 낮추고 유지보수를 용이하게 하기 위해
NetworkViewModel
을 도입했다. - ViewModel을 통해
NetworkManager
의 상태를 구독하고 UI에 전달함으로써 UI와 네트워크 로직을 분리할 수 있었다. - 현재는 네트워크 상태만 관리하지만, 추후 네트워크 상태에 따라 작업을 수행하는 로직을 추가할 경우에도 쉽게 확장 가능하도록 설계되었다.
- 싱글톤으로 설계되어 앱 전역에서 네트워크 상태를 관리한다.
-
ConnectivityManager.NetworkCallback
을 등록하여 네트워크 상태 변화를 감지하고,StateFlow
를 통해 상태를 전달한다.
@Singleton
class NetworkManager @Inject constructor(
@ApplicationContext private val context: Context
) {
private val _networkState = MutableStateFlow(NetworkState.DISCONNECTED)
val networkState: StateFlow<Int> get() = _networkState
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: android.net.Network) {
updateNetworkState()
}
override fun onLost(network: android.net.Network) {
updateNetworkState()
}
}
init {
connectivityManager.registerDefaultNetworkCallback(networkCallback)
updateNetworkState()
}
private fun updateNetworkState() {
val currentNetwork = connectivityManager.activeNetwork
val caps = connectivityManager.getNetworkCapabilities(currentNetwork)
_networkState.value = when {
caps == null -> NetworkState.DISCONNECTED
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> NetworkState.CONNECTED_WIFI
caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> NetworkState.CONNECTED_DATA
else -> NetworkState.DISCONNECTED
}
}
}
-
NetworkManager
를 주입받아 네트워크 상태를 UI에 전달. - UI는 ViewModel을 구독하여 상태 변화를 반영한다.
@HiltViewModel
class NetworkViewModel @Inject constructor(
private val networkManager: NetworkManager
) : ViewModel() {
val networkState: StateFlow<Int> get() = networkManager.networkState
}
-
실시간 반영의 필요성
- 네트워크 상태를 실시간으로 반영해야 하는 UI에서는
NetworkManager
를ViewModel
을 통해 사용하는 방식이 적합하다. - 이를 통해 상태 관리와 UI 업데이트를 분리하고, 네트워크 상태의 변화를 UI에 즉시 반영할 수 있다.
- 네트워크 상태를 실시간으로 반영해야 하는 UI에서는
-
간단한 확인의 필요성
- 네트워크 상태 확인만 필요한 경우에는 기존의
NetworkState
를 사용할 수 있다. -
NetworkState
는 Context 의존성이 없으므로 간단한 작업에서 독립적으로 사용하기 용이하다.
- 네트워크 상태 확인만 필요한 경우에는 기존의
-
병행 사용의 필요성
- 두 가지 방식을 병행 사용하여, 요구사항에 따라 적합한 방법을 선택할 수 있도록 설계하였다.
-
NetworkViewModel 확장 가능성
- 현재
NetworkViewModel
은 단일 네트워크 상태만 전달하지만, 추후 네트워크 상태에 따라 작업을 수행하는 로직을 추가할 때도 유연하게 확장할 수 있다. - 예를 들어, 특정 상태에서 동기화 작업을 자동으로 수행하거나, 네트워크가 복구되었을 때 데이터를 다시 로드하는 등의 로직을 추가할 수 있다.
- 현재
-
NetworkState와 NetworkManager 통합
-
NetworkState
와NetworkManager
는 현재 다른 요구사항에 대응하기 위해 분리된 상태로 유지되고 있다. - 그러나 두 코드가 중복되는 부분이 있어 하나의 관리 클래스로 통합하는 방안도 고려할 수 있다. 🤔
-
-
분리 유지의 필요성
- 화면별로 실시간 네트워크 상태가 필요한 화면과 즉시 상태 확인만 필요한 화면이 나뉘기 때문에, 현재와 같이 분리하여 사용하는 것이 적합하다는 판단도 가능하다.
- 실시간 추적이 필요한 화면에서는
NetworkManager
를 사용하고, 단순 확인이 필요한 화면에서는NetworkState
를 사용하는 것이 더 효율적일 수 있다.
-
통합 vs. 분리
- 통합하면 코드 중복을 줄이고, 네트워크 상태 관리가 중앙 집중화되는 이점이 있다.
- 분리하면 요구사항에 따라 적합한 방식을 선택적으로 사용할 수 있어 코드가 더 유연하게 동작한다.
- 현재는 분리된 상태를 유지하며 요구사항별로 적합한 방식을 사용하는 것이 바람직하다.
- 추후 프로젝트의 복잡도가 증가하거나 네트워크 상태 관련 요구사항이 확장되면, 통합 가능성을 다시 검토할 수 있다.
- 이와 함께 NetworkManager에 상태 관리 외의 추가적인 기능을 제공하여, 실시간 네트워크 이벤트 기반 작업을 더 쉽게 관리할 수 있는 구조로 발전시킬 여지가 있다.