이전 글
Intro
이번 게시글에선 서버의 상태를 체크하는 기능을 추가할 예정입니다.
커스텀 Preference View 만들기
Android의 Preference에서 사진과 같이 서버 상태를 보여주려면 커스텀 뷰를 만들어야 합니다.
Indicator만 커스텀 뷰로 만들어서 Preference의 widgetLayoutResource로 할당해주면 됩니다
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16dp">
<View
android:id="@+id/viewIndicator"
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="@drawable/shape_server_status_indicator"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="서버 상태"
app:layout_constraintBottom_toBottomOf="@id/viewIndicator"
app:layout_constraintStart_toEndOf="@id/viewIndicator"
app:layout_constraintTop_toTopOf="@id/viewIndicator" />
</androidx.constraintlayout.widget.ConstraintLayout>
class ServerStatusPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet,
defStyleAttr: Int = androidx.preference.R.attr.preferenceStyle,
defStyleRes: Int = 0
) : Preference(context, attrs, defStyleAttr, defStyleRes) {
init {
widgetLayoutResource = R.layout.pref_server_status_layout
}
private var serverStatus: ServerStatus = ServerStatus.CHECKING
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val indicator: View = holder.findViewById(R.id.viewIndicator)
val statusText: TextView = holder.findViewById(R.id.tvStatus) as TextView
val background = indicator.background as? GradientDrawable
holder.itemView.post {
background?.setColor(context.getColor(serverStatus.colorRes))
statusText.text = context.getString(serverStatus.statusRes)
summary = context.getString(serverStatus.summaryRes)
}
}
fun setServerStatus(status: ServerStatus) {
serverStatus = status
notifyChanged()
}
}
서버 상태 Enum 추가
서버 상태를 Enum으로 정의하고, 각 상태별 Indicator 색상, 상태 설명 등을 추가 하였습니다.
enum class ServerStatus(
@ColorRes val colorRes: Int,
@StringRes val statusRes: Int,
@StringRes val summaryRes: Int,
) {
CHECKING(R.color.blue, R.string.developer_server_status_checking_title, R.string.developer_server_status_checking_sub),
RUNNING(R.color.green, R.string.developer_server_status_running_title, R.string.developer_server_status_running_sub),
DEGRADED(R.color.orange, R.string.developer_server_status_degraded_title, R.string.developer_server_status_degraded_sub),
ERROR(R.color.red, R.string.developer_server_status_error_title, R.string.developer_server_status_error_sub),
UNKNOWN(R.color.grey, R.string.developer_server_status_unknown_title, R.string.developer_server_status_unknown_sub);
companion object {
fun getStatus(state: ServerState): ServerStatus {
return when (state) {
ServerState.Running -> RUNNING
ServerState.Degraded -> DEGRADED
ServerState.Error -> ERROR
ServerState.Unknown -> UNKNOWN
ServerState.Checking -> CHECKING
}
}
}
}
서버 상태 체크
저희 Runnect 서버는 Spring Boot로 구현되어 있습니다.
Spring Boot에서는 Actuator를 추가하면 기본적으로 Health Check를 지원합니다.
이 Health Check를 이용해서 앱에서 서버의 상태를 체크하는 방법은 간단합니다.
아래와 같이 `${SERVER_URL}/actuator/health`로 요청을 보내면 됩니다.
interface ServerStatusService {
@GET
fun checkServerStatus(
@Url url: String
): Flow<Result<ResponseServerStatus>>
}
상용 서버, 테스트 서버의 상태를 같이 체크하기 위해서 Retrofit의 할당된 BaseUrl은 무시하고, 전달 받은 Url을 이용하도록 하였습니다.
서버 상태 구별
이제 Health Check API로 받은 응답을 이용해 서버의 상태를 구분할 수 있습니다.
저희 서버의 Health Check 응답은 아래와 같이 status만 제공합니다.
저희는 status 정도만 사용했지만 필요에 따라 Spring Boot Actuator에서 커스텀 가능합니다.
@Serializable
data class ResponseServerStatus(
@SerialName("status")
val status: String
)
이를 이용해 ViewModel에선 아래와 같이 분기 해주었습니다.
private fun checkServerStatus(
serverUrl: String,
state: MutableSharedFlow<ServerState>
) = launchWithHandler {
serverStatusRepository.checkServerStatus(serverUrl)
.flowOn(Dispatchers.IO)
.onStart {
state.emit(ServerState.Checking)
}.catch {
state.tryEmit(ServerState.Unknown)
}.collectResult(
onSuccess = {
state.tryEmit(ServerState.Running)
},
onFailure = {
when (it.getCode()) {
503 -> ServerState.Degraded
else -> ServerState.Error
}.let(state::tryEmit)
}
)
}
}
결론
위와 같이 Spring Boot Actuator의 Health Check를 이용하여 앱에서 서버의 상태를 간단히 체크할 수 있었습니다.
사이드 프로젝트 특성상 서버 성능이 좋지 않아서 자주 다운되거나 오류가 발생하곤 합니다.
앱에서 서버 상태를 체크할 수 있으니 개발할 때도 유용하고, 서버 개발자 외에 다른 인원들도 수시로 상태 체크를 할 수 있으니 서비스 운영에도 도움이 될 수 있었습니다 :)
'안드로이드 > 이론' 카테고리의 다른 글
[ 안드로이드 ] Kotlin-Serialization 옵션 정리 (2) | 2024.10.04 |
---|---|
[ 안드로이드 ] LocalBroadcaseManager Deprecated 대응 (0) | 2024.07.12 |
[ 안드로이드 ] 액티비티 배경 투명하게 설정 (+ 투명 배경 유지 안되는 이슈 해결) (0) | 2024.03.25 |
[ 안드로이드 ] Multi ViewType RecyclerView ViewHolder 순서 고정하기 (0) | 2024.01.14 |
[ 안드로이드 ] 앱 내에 개발자 모드 추가하기 2 (0) | 2023.12.29 |