New Score :0
High Score :0
Run Best
NICE BUSINESS TYPE INDICATOR
3. ๊ธ์ ์ ์น๊ตฌ์๊ฒ ๋น๋ ธ๋๋ฐ ์ค๋์ด ๋์ ์ฃผ๊ธฐ๋ก ํ๋ .. ๊ทธ๋ฐ๋ฐ ์นด๋๊ฐ์ ๋ด์ผํ๋ ๋ ๋ ์ค๋์ธ๋ฐ... ์ด๊ฑธ ์ด์ฉ๋...
4. ์ฐ๋ฆฌ ํ์ฌ๋ ์ค์ํ ์์ฌ ๊ฒฐ์ ์ ํ ๋?
5. ์ด์ฌํ ์ผํ ๋๋ฅผ ์ํ ์ ๋ฌผ์ ์ฃผ๊ณ ์ถ๋ค. ์ด๋ค๊ฒ ์ข์๊น?
6. ์ํ์์ ํฌ์์ํ์ ์ถ์ฒ๋ฐ์๋ค. ์ด๋ค๊ฑธ ๊ฐ์ ํ์ง?
7. ํ์ฌ์์์ ๋๋?
8. ๊ฟ์์ ๊นจ์ด๋๋ 20๋ ์ ์ผ๋ก ๋์๊ฐ๋ค. ๋น์ ์ด ์ ์ผ ๋จผ์ ํ๋์ผ์?
9. ๋ด๊ฐ ์ธ์ฌ ๋ด๋น์๋ผ๋ฉด ์ ๊ท ์ ์ฌ์ ์ฑ์ฉ ์ ์ ์ผ ์ค์ํ๊ฒ ๋ณด๋๊ฒ์?
10. ํ์ฌ์ ์ ๋ง ์ซ์ดํ๋ ๋๋ฃ๊ฐ ์๋ค๋ฉด?
11. ๊ฐ๋ํ ์ง์ ๊ฐ์ฅ์ด ๋์๋ค.. ์๋ ์ ์์ผ ๋ ์ ๋ฌผ์?
12. ํ์ ํ์ฌ ์ถ๊ทผ ์คํ์ผ์?
13.ํ์ฌ ์ฒด์ก๋ํ ํ๋ ๋ ์ด๋ค. ์ค๋ ๋ญํ์ง?
14. ๋์ ์ ๋ฌด ์คํ์ผ์?
Kotlin Sealed ํด๋์ค์ ์ดํด: ๋์์ธ ํจํด ๋ฐ ํ์ฉ ์ฌ๋ก ๋ถ์
Kotlin์ sealed
ํด๋์ค๋ ์ ํ๋ ํด๋์ค ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ํต์ฌ ๊ธฐ๋ฅ์ผ๋ก, ์ปดํ์ผ ํ์์ ๋ชจ๋ ํ์ ํ์
์ ์ธ์งํ ์ ์๋ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ์ฃผ๋ก ์ํ ๊ด๋ฆฌ ๋ฐ ์ด๋ฒคํธ ์ฒ๋ฆฌ ์์คํ
์์ ํ์
์์ ์ฑ์ ๋ณด์ฅํ๋ฉฐ, ๋ค์ํ ๋์์ธ ํจํด๊ณผ์ ์๋์ง๋ฅผ ํตํด ์ฝ๋ ํ์ง์ ๊ทน๋ํํฉ๋๋ค. ๋ณธ ๋
ผ๋ฌธ์์๋ sealed
ํด๋์ค์ ์๋ ์๋ฆฌ์ ์ค์ ํ๋ก๋์
ํ๊ฒฝ์์์ ์ ์ฉ ์ ๋ต์ ์ฒด๊ณ์ ์ผ๋ก ๋ถ์ํฉ๋๋ค.
1. Sealed ํด๋์ค์ ๊ตฌ์กฐ์ ํน์ฑ
1.1 ๊ณ์ธต ์ ์ด ๋ฉ์ปค๋์ฆ
sealed
ํด๋์ค๋ ์ถ์ ํด๋์ค๋ก, ๋์ผ ๋ชจ๋ ๋ด์์๋ง ์์ ๊ฐ๋ฅํ ์ ์ฝ์ ๊ฐ์ง๋๋ค(Kotlin 1.5 ์ดํ ํจํค์ง ๋ฒ์ ํ์ฅ). ์ด ์ ์ฝ์ ์ปดํ์ผ๋ฌ๊ฐ ๋ชจ๋ ์๋ธํด๋์ค๋ฅผ ์ธ์งํ ์ ์๊ฒ ํ์ฌ, when
ํํ์์์์ ์์ ์ฑ ๊ฒ์ฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
sealed class NetworkResult {
data class Success(val data: T) : NetworkResult()
data class Error(val code: Int, val message: String) : NetworkResult()
object Loading : NetworkResult()
}
โฒ ๋คํธ์ํฌ ์๋ต ์ฒ๋ฆฌ ๋ชจ๋ธ ์์. ์ํ๋ณ ๋ฐ์ดํฐ ํ์ ๋ถ๋ฆฌ[4]
1.2 ๋คํ์ฑ ๊ตฌํ ๋ฐฉ์
๊ฐ ์๋ธํด๋์ค๋ ๋
๋ฆฝ์ ์ธ ํ๋กํผํฐ์ ๋ฉ์๋๋ฅผ ๋ณด์ ํ ์ ์์ผ๋ฉฐ, data class
์ object
๋ฅผ ํผ์ฉํ์ฌ ๊ตฌํ ๋น์ฉ ์ต์ ํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. Loading
์ํ๋ ์ฑ๊ธํด์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์, Success/Error
๋ ๋ฐ์ดํฐ ์ ๋ฌ์ ์ํด data class
๋ก ์ค๊ณ๋ฉ๋๋ค.
"Sealed ํด๋์ค์ ์๋ธํ์ ์ ์ปดํ์ผ ์์ ์ ์์ ํ ์๋ณ ๊ฐ๋ฅํ๋ฏ๋ก, ๋ฐํ์ ํด๋์ค ๊ฒ์ฌ ์ค๋ฒํค๋๋ฅผ ์ ๊ฑฐํฉ๋๋ค."
2. ํ์ ์์ ์ฑ ํ๋ณด ์ ๋ต
2.1 ์์ ์ฑ ๊ฒ์ฆ ์์คํ
when
ํํ์๊ณผ์ ๊ฒฐํฉ ์ ์ปดํ์ผ๋ฌ๊ฐ ๋ชจ๋ ์ผ์ด์ค๋ฅผ ๊ฒ์ฆํ๋ฏ๋ก else
๋ถ๊ธฐ ๋ถํ์. ์๋ก์ด ์๋ธํด๋์ค ์ถ๊ฐ ์ ๊ธฐ์กด when
๋ธ๋ก์์ ์ปดํ์ผ ์๋ฌ ๋ฐ์, ์ฒ๋ฆฌ ๋๋ฝ ๋ฐฉ์ง.
fun handle(result: NetworkResult) = when(result) {
is NetworkResult.Success -> processData(result.data)
is NetworkResult.Error -> showError(result.code)
NetworkResult.Loading -> displayProgress()
// 'else' ์์ด ๋ชจ๋ ์ผ์ด์ค ์ฒ๋ฆฌ ๋ณด์ฅ
}
2.2 ์ํ ๋จธ์ ์ค๊ณ ํจํด
์ ํ ์ํ ๋จธ์ (FSM) ๊ตฌํ์ ์ ํฉํ ๊ตฌ์กฐ ์ ๊ณต. ์ ์ด ๊ฐ๋ฅํ ์ํ๋ฅผ ํ์ ์์คํ ์ผ๋ก ๋ชจ๋ธ๋งํ์ฌ ์๋ชป๋ ์ํ ์ ์ด๋ฅผ ์ปดํ์ผ ๋จ๊ณ์์ ์ฐจ๋จ.
2.2.1 UI ์ํ ๊ด๋ฆฌ ์ฌ๋ก
sealed class ScreenState {
object Loading : ScreenState()
data class Content(val items: List) : ScreenState()
data class Error(val exception: Throwable) : ScreenState()
}
โฒ ๊ฐ UI ์ํ๋ณ ๋ฐ์ดํฐ ์บก์ํ
3. ๋์์ธ ํจํด ํตํฉ ์ ๊ทผ๋ฒ
3.1 State ํจํด ๊ตฌํ
์ํ ํจํด์์ ๊ฐ ์ํ๋ฅผ sealed
์๋ธํด๋์ค๋ก ๊ตฌํ, ์ปจํ
์คํธ ๊ฐ์ฒด์ ํ๋์ ์ํ ๊ฐ์ฒด์ ์์. ์ํ ์ ์ด ๋ก์ง์ ํ์
์์คํ
์ ๋ฐ์.
sealed class AuthorizationState {
object Unauthorized : AuthorizationState()
data class Authorized(val user: User) : AuthorizationState()
}
class AuthManager {
private var state: AuthorizationState = Unauthorized
fun login(user: User) {
state = Authorized(user)
}
fun logout() {
state = Unauthorized
}
}
โฒ ์ธ์ฆ ์ํ ๋จธ์ ๊ตฌํ ์์
3.2 ์ ๋ต ํจํด ์ฐ๊ณ
์๊ณ ๋ฆฌ์ฆ ๊ตฐ์ sealed
๊ณ์ธต์ผ๋ก ์ ์, ๋ฐํ์์ ์ ๋ต ๊ต์ฒด ๊ฐ๋ฅ. ์ปดํ์ผ ํ์์ ๋ชจ๋ ์ ๋ต ๊ฒ์ฆ.
sealed class CompressionStrategy {
abstract fun compress(data: ByteArray): ByteArray
class ZipStrategy : CompressionStrategy() {
override fun compress(data: ByteArray) = /* ZIP ๋ก์ง */
}
class GZipStrategy : CompressionStrategy() {
override fun compress(data: ByteArray) = /* GZIP ๋ก์ง */
}
}
4. ์ค๋ฌด ์ ์ฉ ์ต์ ํ ์ ๋ต
4.1 API ์๋ต ์ฒ๋ฆฌ ํ์คํ
REST API ์๋ต ์ฒ๋ฆฌ์ ๋ํ ํ์ ์์ ํ ์ฒ๋ฆฌ ์ฒด๊ณ ๊ตฌ์ถ. ์ฑ๊ณต/์คํจ/๋ก๋ฉ ์ํ๋ฅผ ๊ณ์ธตํํ์ฌ ์ค๋ฅ ์ฒ๋ฆฌ ํต์ผ์ฑ ํ๋ณด.
sealed class ApiResponse {
data class Success(val data: T) : ApiResponse()
data class Error(val code: Int, val message: String) : ApiResponse()
object NetworkError : ApiResponse()
fun onSuccess(action: (T) -> Unit): ApiResponse {
if (this is Success) action(data)
return this
}
}
โฒ ์ฒด์ด๋ ๊ฐ๋ฅํ ์๋ต ์ฒ๋ฆฌ๊ธฐ
4.2 ์ด๋ฒคํธ ๋ฒ์ค ์ํคํ ์ฒ
์ด๋ฒคํธ ์ ํ์ sealed
ํด๋์ค๋ก ํ์
ํ, ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ฒ๋ฆฌ ์์ ์ฑ ๋ณด์ฆ. LiveData/Flow์ ๊ฒฐํฉํ์ฌ ์์ ์ ์ธ ์ด๋ฒคํธ ์ ํ.
sealed class AppEvent {
data class NavigationEvent(val route: String) : AppEvent()
data class DataUpdateEvent(val payload: T) : AppEvent()
object SessionExpiredEvent : AppEvent()
}
class EventBus {
private val _events = MutableSharedFlow()
val events = _events.asSharedFlow()
suspend fun post(event: AppEvent) {
_events.emit(event)
}
}
5. ์ฑ๋ฅ ์ต์ ํ ๊ธฐ๋ฒ
5.1 ์ธ์คํด์ค ์์ฑ ๋น์ฉ ๊ด๋ฆฌ
object
๋ฅผ ํ์ฉํ ์ฑ๊ธํด ์ํ ๊ตฌํ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ต์ ํ. data class
์์ ํผ์ฉ ์ ๋ต.
sealed class ProcessState {
object Idle : ProcessState()
data class Running(val progress: Int) : ProcessState()
data class Completed(val result: Result) : ProcessState()
}
โฒ ์ํ๋ณ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์ ๋ต ์ฐจ๋ณํ
5.2 ์ธ๋ผ์ธ ํด๋์ค ํ์ฉ
๊ฐ ๊ธฐ๋ฐ ํด๋์ค์ ๊ฒฐํฉํ์ฌ ๋ํผ ๊ฐ์ฒด ์ค๋ฒํค๋ ์ ๊ฑฐ(Kotlin 1.9+ value
ํด๋์ค).
@JvmInline
value class UserId(val value: String)
sealed class UserEvent {
data class Created(val id: UserId) : UserEvent()
data class Updated(val id: UserId) : UserEvent()
}
6. ํ์ฅ ์ํคํ ์ฒ ํจํด
6.1 MVI ํจํด ํตํฉ
Model-View-Intent ์ํคํ
์ฒ์์ ์ํ ๋ณํ๋ฅผ sealed
ํด๋์ค๋ก ๋ชจ๋ธ๋ง, ์์ธก ๊ฐ๋ฅํ ์ํ ๊ด๋ฆฌ ๊ตฌํ.
sealed class MainState {
object Loading : MainState()
data class Content(val items: List) : MainState()
data class Error(val cause: Throwable) : MainState()
}
sealed class MainIntent {
object LoadData : MainIntent()
data class Refresh(val force: Boolean) : MainIntent()
}
6.2 ๋ ์ด์ด๋ ์ํคํ ์ฒ ์ ์ฉ
๋๋ฉ์ธ ๊ณ์ธต์์ ์ ์ค์ผ์ด์ค ๊ฒฐ๊ณผ ํ์
์ ์ ์ sealed
ํด๋์ค ํ์ฉ, ํ๋ ์ ํ
์ด์
๊ณ์ธต์ผ๋ก์ ์ค๋ฅ ์ ํ ๋ฐฉ์ง.
sealed class UseCaseResult {
data class Success(val data: T) : UseCaseResult()
data class BusinessError(val code: Int) : UseCaseResult()
data class InfrastructureError(val cause: Throwable) : UseCaseResult()
}
7. ๋น๊ต ๋ถ์: Enum ํด๋์ค vs Sealed ํด๋์ค
7.1 ์ธ์คํด์ค ๊ด๋ฆฌ ์ฐจ์ด
ํน์ฑ | Enum Class | Sealed Class |
์ธ์คํด์ค ์ | ๋จ์ผ ์ธ์คํด์ค | ๋ค์ค ์ธ์คํด์ค ๊ฐ๋ฅ |
๋ฐ์ดํฐ ์ฐ๊ด์ฑ | ์ ํ์ ํ๋กํผํฐ | ํ๋ถํ ๋ฐ์ดํฐ ๊ตฌ์กฐํ ๊ฐ๋ฅ |
ํ์ฅ์ฑ | ๊ณ ์ ๋ ์์ ์งํฉ | ๋์ ๊ณ์ธต ํ์ฅ ๊ฐ๋ฅ |
ํจํด ๋งค์นญ | ๊ธฐ๋ณธ ์ง์ | ์์ ํ ํ์ ๊ฒ์ฌ ์ง์ |
โฒ ๊ตฌ์กฐ์ ์ฐจ์ด ๋น๊ตํ
7.2 ์ฑ๋ฅ ์งํ ๋น๊ต
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋:
object
๊ธฐ๋ฐsealed
์๋ธํด๋์ค๋enum
๊ณผ ๋๋ฑ - ์ฒ๋ฆฌ ์๋:
when
๋ถ๊ธฐ์์ JVMtableswitch
์ต์ ํ ๋์ผ ์ ์ฉ - ํ์ฅ ๋น์ฉ: ์
enum
์์ ์ถ๊ฐ ์ ์ฌ์ปดํ์ผ ํ์ vssealed
์๋ธํด๋์ค๋ ๋ชจ๋ ๋ด ์์ ๋ก์ด ํ์ฅ
8. ๊ณ ๊ธ ํ์ฉ ์๋๋ฆฌ์ค
8.1 ๋ค์ค ์์ ๊ณ์ธต ๊ตฌํ
sealed interface
๋ฅผ ํ์ฉํ ์ํ์ ๊ณ์ธต ํ์ฅ(Kotlin 1.5+). ์ฌ๋ฌ ์ธํฐํ์ด์ค ๊ตฌํ์ ํตํด ๊ด์ฌ์ฌ ๋ถ๋ฆฌ.
sealed interface DatabaseResult
sealed interface NetworkResult
sealed class CompositeResult : DatabaseResult, NetworkResult {
data class Success(val data: Any) : CompositeResult()
sealed class Error : CompositeResult() {
data class DbError(val code: Int) : Error()
data class NetworkError(val exception: Exception) : Error()
}
}
8.2 DSL(Domain Specific Language) ๊ตฌ์ฑ
ํ์ ์์ ํ ๋น๋ ํจํด ๊ตฌํ์ ํ์ฉ, ๋ณต์กํ ๊ฐ์ฒด ์์ฑ ๊ณผ์ ์ ๊ณ์ธตํ.
sealed class QueryBuilder {
data class Select(val columns: List) : QueryBuilder()
data class Where(val condition: String) : QueryBuilder()
data class Join(val table: String, val on: String) : QueryBuilder()
fun build(): String {
return when(this) {
is Select -> "SELECT ${columns.joinToString()}"
is Where -> "WHERE $condition"
is Join -> "JOIN $table ON $on"
}
}
}
9. ๊ฒฐ๋ก ๋ฐ ์ต์ ํ์ฉ ๊ฐ์ด๋๋ผ์ธ
sealed
ํด๋์ค๋ Kotlin ํ์
์์คํ
์ ํต์ฌ ์์๋ก, ๋ค์๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค์์ ์ต์ ์ ์๋ฃจ์
์ ์ ๊ณตํฉ๋๋ค:
- ์ ํ ์ํ ๋จธ์ ๊ตฌํ: ์ํ ์ ์ด๋ฅผ ํ์ ์์คํ ์ผ๋ก ๋ชจ๋ธ๋ง
- ๊ณ์ธต์ ์ค๋ฅ ์ฒ๋ฆฌ: ๋๋ฉ์ธ๋ณ ์ค๋ฅ ์ ํ์ ๋ช ์์ ๊ณ์ธต์ผ๋ก ๊ตฌ๋ถ
- ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ: ์ด๋ฒคํธ ์ ํ ์์ ์ฑ ๋ณด์ฅ
- ๋ค๋จ๊ณ API ์๋ต ์ฒ๋ฆฌ: ์ฑ๊ณต/์คํจ/์งํ ์ํ๋ฅผ ํตํฉ ๊ด๋ฆฌ
- ๋ณต์กํ ๋๋ฉ์ธ ๋ชจ๋ธ๋ง: ํ์ ํ์ ๋ณ ๋์ ์ฐจ์ด ๊ตฌํ
๊ฐ๋ฐ ํ์ sealed
ํด๋์ค๋ฅผ ํ์ฉํ์ฌ ์ปดํ์ผ ํ์ ์์ ์ฑ๊ณผ ํ์ฅ์ฑ์ ๋์์ ํ๋ณดํ ์ ์์ผ๋ฉฐ, ์ง์์ ์ธ ๋ฆฌํฉํ ๋ง ๋ด์ฑ ํฅ์์ ๊ธฐ๋ํ ์ ์์ต๋๋ค. ํนํ MVI/MVVM ์ํคํ
์ฒ์์ ์กฐํฉ์ ํ๋ Android ์ฑ ๊ฐ๋ฐ ํ์ค์ผ๋ก ์๋ฆฌ๋งค๊นํ๊ณ ์์ต๋๋ค. ํฅํ Kotlin์ sealed
์ธํฐํ์ด์ค ์งํ์ ๋ฉํฐํ๋ซํผ ์ง์ ๊ฐํ๋ ๋์ฑ ์ ๊ตํ ํ์
์์คํ
๊ตฌ์ถ์ ๊ฐ๋ฅํ๊ฒ ํ ๊ฒ์
๋๋ค.