๋ชฉ์ฐจ
๋ฐฐ๊ฒฝ
ํ๋ก์ ํธ๊ฐ ์ ์ ๋ง๋ฌด๋ฆฌ๋๋ ์ต๊ทผ...
์๋ฒ ์์ ์ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ๊ธฐ์กด ๋ก์ง์ ๋ํด ์๋ฌธ์ ๊ฐ์ง๊ณ ์๋ ๋ถ๋ถ์ ๋ํด ์ด์ ์ ํจ๊ป ํ๋ ๊ฐ๋ฐ์๋ถ๊ป ์ง๋ฌธ์ ๋๋ ธ๋ค!!!
๊ทธ๋ฐ๋ฐ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋๋ ์๋ฒ ์คํจ, ์ฑ๊ณต ์ฒ๋ฆฌ์ ๋ํ ์ดํด๊ฐ ์ ~~๋ง ๋ถ์กฑํ ์ํ์๋ค. ๋ฐ๋ผ์ ๊ทธ๋ฐ ์ํ๋ก ์ง ์ฝ๋๊ฐ ๋ชจ๋ ์๋ชป๋์๋ค๋ ํผ๋๋ฐฑ์ ๋ฐ๊ฒ ๋์๋ค.
์ด๋ ๊ฒ ํฌ๊ฒ ์๋ชป๋ ์ ์ ์ ์ ์๋ค๋ ใ ใ ์ง๋ฌธ์ ๋๋ ค์ ์ ๋ง ๋คํ์ด๊ณ ๋ต๋ณ ์ฃผ์ ๊ฒ์ ์ ๋ง ๊ฐ์ฌํ๋ค ๐
์๋ชป๋ ์ฝ๋
์๋ชป๋ ์ฝ๋๋ฅผ ๋ณด๊ณ ๋ฌธ์ ์ ๊ณผ ๋ถ์กฑํจ ์ ์ ์ฑ์๋ณด์
class GetReportListUseCase
@Inject
constructor(
private val reportRepository: ReportRepository,
) {
operator fun invoke(lastReportId: String?) =
flow {
// todo : ๊ทธ๋ฅ "" ๋ก ๋ฃ์ด์ค๋ ๋จ ์์ ํ ๊ฒ
val result = reportRepository.searchReport(SearchReportRequest(lastReportId = lastReportId))
result.onFailure {
throw it
}
emit(result.getOrNull())
}.catch {
Timber.e(it.localizedMessage)
}
}
์ฝ๋์ ๋ฌธ์ ์
1. result.onFailure { throw it }
์คํจ ์ ์์ธ๋ฅผ throw ํ๊ณ ์๋ค.
๊ทธ๋ฆฌ๊ณ .catch { Timber.d("failed to search user Report list" ) ์์๋ ๋ค์ ํ๋ฒ ์์ธ๋ฅผ ์ก์ผ๋ ค๊ณ ํ๊ณ ์๋ค..
์ฐ์ onSuccess์ onFailure๋ ๋ฌด์์ ํ๋ ์์ด๋ค ์ธ์ง๋ถํฐ ์ดํดํ์.
onSuccess
result.onSuccess { value ->
// ์ฐ์ฐ์ด ์ฑ๊ณตํ์ ๋ ์คํ๋๋ ๋ธ๋ก
// value : ์ฑ๊ณต์ ์ผ๋ก ์ป๋ ๊ฒฐ๊ณผ๊ฐ
- ์ฐ์ฐ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ ๋ ํธ์ถ๋๋ค.
- ์ฑ๊ณตํ ๊ฒฐ๊ณผ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ์ฒ๋ฆฌํ ์ ์๋ค(value)
- ์ฐ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์ถ๊ฐ๋ก ๊ฐ๊ณตํ๊ฑฐ๋ ์ฌ์ฉํ ๋ ํ์ฉํ ์ ์๋ค.
onFailure
result.onFailure { exception ->
// ์ฐ์ฐ ์ค ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ์คํ๋๋ ๋ธ๋ก
// exception : ๋ฐ์ํ ์์ธ ๊ฐ์ฒด
- ์ฐ์ฐ ์ค ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ํธ์ถ๋๋ค
- ์์ธ ๊ฐ์ฒด๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ์์ธ ์ฒ๋ฆฌ๋ฅผ ํ ์ ์๋ค(exception)
- ๋ก๊น , ์๋ฌ ๋ฉ์์ง ํ์, ๋์ฒด ๋์ ๋ฑ์ ์ ์ํ ๋ ์ฌ์ฉํ๋ค.
throw ํ๋ฉด ์ด๋ค ์ผ์ด ์ผ์ด๋ ๊น?
1. ์์ธ ์์ฑ
- ํ์ฌ ์ค์ฝํ์์ ๋ฐ์ํ ์์ธ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
- ์์ธ์ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ณด์กดํ๋ค.
2. ํธ์ถ ์คํ ์ ํ
- ์์ธ๋ ํ์ฌ ๋ฉ์๋์์ ํธ์ถํ ๋ถ๋ชจ ๋ฉ์๋๋ก ์ ํ๋๋ค.
- ๊ฐ ํธ์ถ ์คํ ๋ ๋ฒจ์ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ค.
3. ์์ธ ์ฒ๋ฆฌ ๋๊ธฐ
- ์ ์ ํ ์์ธ ์ฒ๋ฆฌ๊ธฐ(try, catch)๋ฅผ ์ฐพ์ ๋๊น์ง ๊ณ์ ์ ํ๋๋ค.
- ๋ง์ฝ ์ด๋์์๋ ์ฒ๋ฆฌ๋์ง ์์ผ๋ฉด ํ๋ก๊ทธ๋จ์ด ์ค๋จ๋ ์ ์๋ค.
- ๊ฐ๋ฐ์๊ฐ ์๋์ ์ผ๋ก ์๋ฌ๋ฅผ ์์ ๋ ์ด์ด๋ก ์ ํํ ๋ ์ฌ์ฉํ๋ค
// ์์ธ๋ฅผ ๋ช
์์ ์ผ๋ก ๋ฐ์์ํค๊ณ ์ ํํ ๋ throw ๋ฅผ ์ฌ์ฉํ๋ค.
fun getList() {
// ์์ธ ๋ฐ์ ๊ฐ๋ฅ์ฑ ์๋ ์ฝ๋
throw RuntimeException("wrong")
}
fun callGetList() {
try {
getList()
} catch(e : Exception) {
// ์์ธ ์ฒ๋ฆฌ
println(e.message)
}
}
๊ฐ์ ํ ์ฝ๋
์๋๋ ๊ฐ์ ํด๋ณธ ์ฝ๋์ด๋ค!
class GetReportListUseCase
@Inject
constructor(
private val reportRepository: ReportRepository,
) {
operator fun invoke(lastReportId: String?): Flow<SearchReportResponse?> =
flow {
// 1. ๋ ํฌ์งํ ๋ฆฌ ํธ์ถ ์ ์์ธ ๋ฐ์
try {
val result = reportRepository.searchReport(SearchReportRequest(lastReportId = lastReportId))
result
.onSuccess { searchResult ->
emit(searchResult)
}.onFailure { exception ->
when (exception) {
// todo : ์ดํ UiState๋ฅผ ํตํด HttpError ๋ฐ์ ์ ์๋ฌ ๋ฉ์์ง ๋ณด์ด๊ธฐ
is HttpException -> Timber.e("Network error: ${exception.message}")
else -> Timber.e("Unknown error: ${exception.message}")
}
// ์์ธ ๋ฐ์ ์ ๊ธฐ๋ณธ๊ฐ ๋ฐํ
emit(SearchReportResponse())
}
} catch (e: Exception) {
// result.onFailure์์ ์ฒ๋ฆฌ๋์ง ์์ ๋ชจ๋ ์์ธ๋ฅผ ์ต์ข
์ ์ผ๋ก ์ก์๋ธ๋ค.
// ์์์น ๋ชปํ ์์ธ ๋ฐ์ ๊ฐ๋ฅ์ฑ
// 1. JSON ํ์ฑ ์ค๋ฅ
// 2. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ด๋ถ ๋ฒ๊ทธ๋ก ์ธํ ์์ธ
Timber.e(e, "Unexpected error in GetReportListUseCase")
// ์์ธ ๋ฐ์ ์ ๊ธฐ๋ณธ๊ฐ ๋ฐํ
emit(SearchReportResponse())
}
}
}
throw
์์ธ throw ๊ณผ์
ํ๋ก๊ทธ๋จ ์คํ ํ๋ฆ :
1. ํจ์ ์์
2. ์์ธ ๋ฐ์ !
3. ํ๋ก๊ทธ๋จ ์คํ ์ค๋จ
4. ์์ธ ์ ๋ณด ์ ํ
throw๋ ํน์ ์ํฉ์์ ๋ฐ์ํ ์ ์๋ ์์ธ๋ฅผ ์ฒ๋ฆฌํด์ฃผ๊ธฐ ์ํด catch๋ฌธ์์ ์ก์ ์ ์๋๋ก ํด๋น ์์ธ๋ฅผ ๋์ง๋(throw) ์ฒ๋ฆฌ ๊ณผ์ ์ด๋ค.
class CustomNetworkException(message: String) : Exception(message)
fun performNetworkCall() {
val random = Random.nextInt(0, 3)
when (random) {
0 -> throw CustomNetworkException("์ฐ๊ฒฐ ์ค๋ฅ")
1 -> throw IllegalArgumentException("์๋ชป๋ ์ธ์")
2 -> throw RuntimeException("์ ์ ์๋ ์ค๋ฅ")
}
}
์ด๋ ๊ฒ random ์์ ๋ฐ๋ผ์ throw๋ฅผ ํตํด ์์ธ๋ฅผ ๋์ ธ์ฃผ์๋ค.
๊ฐ๋ฐ ์ค์์๋ ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ ์ํฉ์์ throw๋ฅผ ํตํด ์์ธ๋ฅผ ๋์ ธ์ฃผ๋ฉด ๋๋ค!!
catch
์์ธ catch ๊ณผ์
ํ๋ก๊ทธ๋จ ์คํ ํ๋ฆ :
1. try ๋ธ๋ก ์์
2. ์์ธ ๋ฐ์!
3. catch ๋ธ๋ก์ผ๋ก ์ด๋
4. ์์ธ ๋ฉ์์ง ์ถ๋ ฅ
5. finally ๋ธ๋ก ์คํ
6. ํ๋ก๊ทธ๋จ ์ ์ ๊ณ์ ์คํ
์์์ ๋์ง ์์ธ๋ค์ ์ฌ๊ธฐ์ catch๋ฅผ ํ๊ณ ๋ฐ์ํ๋ ์์ธ์ ๋ฐ๋ผ์ ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์๋ค.
์ด์ฒ๋ผ catch๋ฌธ์ ํตํด ์ฒ๋ฆฌํ๊ณ ์ถ์ ์์ธ๋ฅผ ์ก์์ ์ํ๋ ์ฒ๋ฆฌํ ์ ์๋ค.
fun main() {
try {
performNetworkCall()
} catch (e: CustomNetworkException) {
// ํน์ ์์ธ ์ฒ๋ฆฌ
println("๋คํธ์ํฌ ์ค๋ฅ ์ฒ๋ฆฌ: ${e.message}")
} catch (e: IllegalArgumentException) {
// ๋ค๋ฅธ ์ ํ์ ์์ธ ์ฒ๋ฆฌ
println("์ธ์ ์ค๋ฅ ์ฒ๋ฆฌ: ${e.message}")
} catch (e: Exception) {
// ๋ชจ๋ ๋๋จธ์ง ์์ธ ์ฒ๋ฆฌ
println("์ผ๋ฐ ์์ธ ์ฒ๋ฆฌ: ${e.message}")
} finally {
// ํญ์ ์คํ๋๋ ๋ธ๋ก
println("์ ๋ฆฌ ๋ฐ ์์ ํด์ ")
}
}
์์ธ throw ํ ์คํ ํ๋ฆ
์์ธ๊ฐ ๋ฐ์ํ๋ฉด ํ๋ฆ์ ์ฆ์ ์ค๋จ๋๊ณ ๋ค์ ์ค์ ์์นํ ์ฝ๋๋ ์คํ๋์ง ์๋๋ค.
fun exampleThrowError() {
println("์ด ์ฝ๋๋ ์คํ ๋จ")
throw RuntimeException("Something went wrong!")
// ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ํ๋ก๊ทธ๋จ ํ๋ฆ์ด ์ฆ์ ์ค๋จ๋๋ค.
println("์ด ์ฝ๋๋ ์คํ๋์ง ์์")
}
catch ์ ์คํ ํ๋ฆ
catch ๋ธ๋ก ์ดํ์ ํ๋ก๊ทธ๋จ์ ๊ณ์ ์คํ๋๊ณ , finally ๋ธ๋ญ์ผ๋ก ์์ฑ๋ ์ฝ๋๋ ์์ธ์ ์๊ด์์ด ์ ์ ์คํ๋๋ค
fun exampleCatchError(){
try {
// ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ ์ฝ๋ ๋ธ๋ญ
val result = 10/0 // ์ด ์ค์์ ArithmeticException ๋ฐ์
println("์ด ์ฝ๋๋ ์คํ๋์ง ์์")
} catch (e : ArithmeticException) {
// ํน์ ์๋ฌ๋ฅผ ์ก์์ ์ฒ๋ฆฌ
println("0์ผ๋ก ๋๋ ์ ์์ต๋๋ค :${e.message}")
} finally {
// ์์ธ ๋ฐ์ ์ฌ๋ถ์ ์๊ด์์ด ์ ์ ์คํ
println("์ ๋ฆฌ ์์
์ํ")
}
// catch ๋ธ๋ก ์ดํ ํ๋ก๊ทธ๋จ ๊ณ์ ์คํ
println("ํ๋ก๊ทธ๋จ ๊ณ์ ์งํ")
}
์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ ๋ฐฉ์
ํ์ฌ๋ ์๋์ ๊ฐ์ด ์ฌ์ฉํด์ฃผ๊ณ ์๋ค.
์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ์๋ null์ ๋ฐํํด์ฃผ๊ณ , ์ฑ๊ณตํ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐฉ์ถํ๋๋ก ํด์ฃผ์๋ค.
์ด ๋ถ๋ถ์ ์ถํ ์ฌ์ฉ์์์ ์ํธ์์ฉ์ ๋ณด๋ฉด์ ๋ํ๋๋ ์ํฉ์ ๋ง์ถ์ด ์์ ํด์ค ์์ ์ด๋ค!
flow {
val result = reportRepository.getReport(reportId)
result.onFailure {
when (it) {
is HttpException -> Timber.e("Network error: ${it.message}")
else -> Timber.e("Unknown error: ${it.message}")
}
emit(null)
}
result.onSuccess {
emit(it)
}
}
'๐ค2024 ์๋๋ก์ด๋ > ๐ฟ ์ํ ํ๋ก์ ํธ ๊ฐ๋ฐ ์ผ์ง' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Android : Kotlin] ์์กด์ฑ ์ฃผ์ ์ ๊ธฐ๋ณธ์ ์ดํดํด๋ณด์~! (2) | 2024.12.27 |
---|---|
MVC , MVP, MVVM ๋๋์ด ์ดํดํ๋ค (0) | 2024.12.20 |
๐ [Android Repository Pattern]์ ์ฌ์ฉํ๋ ์ด์ ์์๋ณด๊ธฐ! (3) | 2024.11.18 |
โบ๏ธAndroid : flow๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฌ์ฉํด๋ณด์~! (2) | 2024.11.04 |
ํ๋ก์ ํธ์ Jetpack Navigation ์ ์ฉํ๊ธฐ (8) | 2024.10.15 |