Sealed Class · Result 패턴 — 개념 빈칸 문제
안내: ( )에 알맞은 말을 적으세요. 영어 키워드도 OK입니다.
정답은 맨 아래에 있습니다.
1. Sealed Class
1-1. sealed class는 가능한 ( )의 개수가 타입 정의에 고정되어 있다.
1-2. sealed class는 보통 ( )처럼 직접 인스턴스를 만들 수 없다.
1-3. 추가 데이터가 없는 상태 하나만 표현할 때는 data ( )를 쓴다.
1-4. 필드가 있는 상태는 data ( )로 만든다.
1-5. sealed의 하위 타입은 보통 ( ) 파일에 선언하며, 바깥에서 임의로 상속할 수 없다.
1-6. when에서 is OrderStatus.Paid처럼 분기하면, 해당 블록 안에서 ( ) cast로 status.paidAt 같은 필드를 쓸 수 있다.
1-7. sealed 타입을 when의 대상으로 쓰고 모든 하위 타입을 is로 처리하면, ( ) 없이 when을 끝낼 수 있다. (exhaustive)
1-8. 나중에 Shipped 같은 하위 타입을 추가하면, 관련 when이 ( ) 에러가 나 빠진 분기를 찾기 쉽다.
1-1. 하위 타입(변형/케이스)
1-2. abstract class
1-3. object
1-4. class
1-5. 같은
1-6. smart
1-7. else
1-8. 컴파일
2. enum · open class와 비교
2-1. enum은 상수 개수가 고정이고, sealed class는 하위 타입마다 ( ) 데이터를 다르게 가질 수 있다.
2-2. open class는 어디서든 상속 가능하지만, sealed class는 ( )된 곳에서만 하위 타입을 둘 수 있다.
2-3. String이나 Int 코드만으로 상태를 두면 ( )나 잘못된 조합이 생기기 쉽다.
2-1. 서로 다른(다른)
2-2. 제한
2-3. 오타
3. Sealed Interface
3-1. sealed class 대신 sealed ( )로도 같은 “닫힌 타입” 패턴을 만들 수 있다.
3-2. UiState<out T>에서 Loading·Error가 UiState<Nothing>인 이유는, 그 상태에는 성공 ( ) T가 없기 때문이다.
3-3. 화면의 로딩/성공/실패를 하나의 타입으로 묶을 때 UiState 같은 ( ) interface를 자주 쓴다.
3-1. interface
3-2. 데이터(값)
3-3. sealed
4. Result 패턴
4-1. Result 패턴은 작업 결과를 ( )과 ( )으로 나누어 반환 타입에 담는 설계 방식이다.
4-2. 실패를 매번 ( )만 쓰지 않고, 호출하는 쪽이 when 등으로 반드시 분기하게 만드는 것이 목적이다.
4-3. AppResult의 두 갈래는 ( )와 ( )이다.
4-4. AppError도 sealed로 두면, 실패 ( )를 when으로 안전하게 나눌 수 있다.
4-5. Failure가 AppResult<Nothing>인 것은, 실패 브랜치에는 성공 ( )이 없다는 뜻이다.
4-6. findUser가 User? 대신 AppResult<User>를 반환하면, “없음”을 null이 아니라 AppError.( ) 같은 타입으로 구분할 수 있다.
4-1. 성공 / 실패 (Success / Failure도 정답)
4-2. throw(예외)
4-3. Success / Failure
4-4. 종류(이유)
4-5. 값(value)
4-6. NotFound
5. kotlin.Result
5-1. Kotlin 표준 라이브러리의 Result<T>는 주로 ( )로 블록을 감싸 예외를 Failure로 만든다.
5-2. parseId("abc").getOrElse { -1L }에서 getOrElse는 ( )일 때 대체 값을 준다.
5-3. 도메인/API에서 에러 종류를 명확히 쓰려면 kotlin.Result보다 sealed( ) + AppError를 쓰는 경우가 많다.
5-4. onSuccess / onFailure는 값을 꺼내 ( ) 효과(출력·로깅 등)를 낼 때 쓴다.
5-1. runCatching
5-2. 실패
5-3. AppResult
5-4. 부수
6. 체이닝 · 예외 (개념)
6-1. map은 Success일 때만 값을 ( )하고, 이미 Failure면 그대로 돌려준다.
6-2. 다음 단계도 AppResult를 반환할 때는 map이 아니라 ( )을 쓴다.
6-3. 연속 작업 중 한 단계라도 Failure이면, 뒤 단계는 실행하지 않고 ( )가 전파된다.
6-4. “사용자 없음”, “입력 오류”처럼 예상 가능한 실패는 AppResult로, 라이브러리가 던지는 예외는 often ( )에서 AppResult로 바꾼다.
6-5. HTTP 응답은 HttpResponse 같은 sealed로, 비즈니스 결과는 AppResult로 나누는 것은 ( )마다 역할을 분리하기 위함이다.
6-1. 변환
6-2. flatMap
6-3. Failure
6-4. 경계(레이어)
6-5. 레이어
7. 한 줄 연결 (짝 맞추기)
왼쪽 번호와 오른쪽 설명을 연결하세요. (답: 1-( ), 2-( ) …)
① sealed class
A. runCatching에 편함
② AppResult
B. 가능한 경우 N개 고정
③ UiState
C. Success / Failure
④ kotlin.Result
D. Loading / Content / Error
①-B, ②-C, ③-D, ④-A
8. O / X (개념)
8-1. ( ) sealed class는 어디서나 자유롭게 상속할 수 있다.
8-2. ( ) enum은 Paid(시각)처럼 하위마다 다른 필드를 두기 어렵다. (일반적인 학습 수준 기준)
8-3. ( ) AppResult.Failure인데도 result.value를 항상 쓸 수 있다.
8-4. ( ) when에서 모든 sealed 하위 타입을 처리하면 else가 필요 없을 수 있다.
8-5. ( ) Result 패턴은 Kotlin 언어에만 있는 공식 문법 키워드이다.
8-6. ( ) kotlin.Result의 실패는 대부분 Throwable(예외)이다.
8-1. X
8-2. O
8-3. X
8-4. O
8-5. X (관용구/설계 패턴)
8-6. O
연습·암기용으로 짧게 묶은 예제
한 파일에 붙여 넣고 main만 실행해 보면 됩니다.
// ========== 1. Sealed Class — 가능한 상태를 타입으로 고정 ==========
sealed class OrderStatus {
data object Created : OrderStatus() // 데이터 없는 상태
data class Paid(val paidAt: Long) : OrderStatus() // 결제 시각
data class Cancelled(val reason: String) : OrderStatus() // 취소 사유
}
// when + is : 모든 하위 타입을 처리하면 else 없이 OK (exhaustive)
fun orderMessage(status: OrderStatus): String = when (status) {
is OrderStatus.Created -> "주문 생성됨"
is OrderStatus.Paid -> "결제 완료: ${status.paidAt}" // smart cast로 paidAt 사용
is OrderStatus.Cancelled -> "취소: ${status.reason}"
}
// ========== 2. Sealed Interface — 화면 상태 묶기 (class와 사용법 동일) ==========
sealed interface UiState<out T> {
data object Loading : UiState<Nothing> // 아직 데이터 없음
data class Content<T>(val data: T) : UiState<T> // 성공, 데이터 있음
data class Error(val message: String) : UiState<Nothing> // 실패, 데이터 없음
}
fun uiMessage(state: UiState<String>): String = when (state) {
is UiState.Loading -> "로딩 중..."
is UiState.Content -> "내용: ${state.data}"
is UiState.Error -> "에러: ${state.message}"
}
// ========== 3. Result 패턴 — 성공 / 실패를 반환 타입으로 표현 ==========
sealed class AppResult<out T> {
data class Success<T>(val value: T) : AppResult<T>() // 성공 + 값
data class Failure(val error: AppError) : AppResult<Nothing>() // 실패 (성공 값 없음)
}
sealed class AppError {
data class NotFound(val id: String) : AppError()
data class InvalidInput(val field: String, val message: String) : AppError()
}
data class User(val id: Long, val name: String)
// Repository 역할: null 대신 AppResult 반환
fun findUser(id: Long): AppResult<User> {
val user = if (id == 1L) User(1, "김코틀린") else null
return if (user != null) {
AppResult.Success(user)
} else {
AppResult.Failure(AppError.NotFound("user:$id"))
}
}
// 호출부: 반드시 Success / Failure 분기
fun printUser(result: AppResult<User>) {
when (result) {
is AppResult.Success -> println("이름: ${result.value.name}")
is AppResult.Failure -> when (val e = result.error) { // 실패 종류도 sealed
is AppError.NotFound -> println("없음: ${e.id}")
is AppError.InvalidInput -> println("${e.field}: ${e.message}")
}
}
}
// ========== 4. kotlin.Result — 짧은 작업·예외 감싸기 (표준 라이브러리) ==========
fun parseId(text: String): Result<Long> = runCatching {
text.toLong() // 실패 시 예외 → Result.failure
}
fun printId(text: String) {
parseId(text)
.onSuccess { println("id = $it") }
.onFailure { println("파싱 실패: ${it.message}") }
}
// ========== 5. (선택) flatMap — 연속 작업, 중간에 실패하면 멈춤 ==========
fun <T, R> AppResult<T>.map(transform: (T) -> R): AppResult<R> =
when (this) {
is AppResult.Success -> AppResult.Success(transform(value))
is AppResult.Failure -> this
}
fun getUserLabel(id: Long): AppResult<String> =
findUser(id).map { user -> "${user.name}(id=${user.id})" }
// ========== 실행 ==========
fun main() {
println(orderMessage(OrderStatus.Paid(1710000000L)))
println(uiMessage(UiState.Content("안녕")))
printUser(findUser(1L)) // 성공
printUser(findUser(99L)) // NotFound
printId("42")
printId("abc")
println(getUserLabel(1L))
}
| 기억할 것 | |
|
Sealed
|
sealed class + data object / data class 하위 타입
|
|
when
|
is로 분기, 전부 처리하면 else 불필요
|
|
Result
|
Success(값) / Failure(에러)
|
|
실패 상세
|
AppError도 sealed → when 한 번 더
|
'Language > Kotlin' 카테고리의 다른 글
| [Kotlin] Coroutine 기초 과제 (0) | 2026.06.02 |
|---|---|
| [복습] 1~3강까지 미션 (0) | 2026.05.27 |
| [Kotlin] Coroutine 기초 (0) | 2026.05.20 |
| [Kotlin] Collection API & 함수형 프로그래밍 (0) | 2026.05.20 |
| [Kotlin] Scope Function 완전 정리 (0) | 2026.05.20 |