sealed class와 sealed interface는 Kotlin에서 제한된 유형 계층 구조를 위한 메커니즘으로, 가능한 모든 하위 클래스가 컴파일 타임에 알려집니다. 일반 추상 클래스와 달리 sealed class는 when 표현식에서 모든 변형의 완전한 처리를 보장합니다. JetBrains Kotlin Language Guide(2026) 문서에 따르면, sealed 유형은 Kotlin 프로젝트에서 상태, UI 화면 및 결과 유형을 모델링하는 기초입니다.
핵심 요점
sealed class는 제약이 있는 추상 클래스입니다. 모든 직접 하위 클래스는 sealed class 자체와 동일한 파일에서 선언되어야 합니다. 이 제약으로 인해 계층 구조가 닫히며(sealed), 파일 외부의 코드는 새 하위 클래스를 추가할 수 없습니다.
sealed interface는 Kotlin 1.5에서 추가되었으며, 동일한 보장을 제공하지만 인터페이스의 유연성을 갖습니다. sealed interface는 하나의 파일에서 여러 클래스, 객체 또는 다른 인터페이스에 의해 구현될 수 있습니다. sealed class와 달리 sealed interface에는 단일 상속 제한이 없으며, 클래스는 여러 sealed 인터페이스를 동시에 구현할 수 있습니다.
Kotlin Evolution and Roadmap(2026)에 따르면, sealed interface는 보다 유연한 모델링을 위해 커뮤니티 요청으로 추가되었습니다. 주요 동기는 다중 클래스 상속 없이 독립적인 유형 계층 구조를 결합하는 능력입니다.
sealed class의 선언은 class 앞에 sealed 한정자로 시작합니다. 하위 클래스는 동일한 파일에서 선언됩니다.
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val message: String) : NetworkResult()
object Loading : NetworkResult()
}
sealed class의 각 하위 클래스는 고유한 속성과 메서드를 가질 수 있습니다. Loading은 싱글톤(object)이고, Success와 Error는 매개변수가 있는 data class입니다. 컴파일러는 세 가지 변형을 모두 알고 when에서 사용될 때 완전성을 확인합니다.
sealed 클래스는 중첩될 수 있어, 타입 안전성을 잃지 않으면서 복잡한 데이터 모델을 위한 다중 레벨 계층 구조를 만듭니다.
sealed class UiState {
object Idle : UiState()
object Loading : UiState()
data class Content(val items: List<Item>) : UiState()
data class Error(val exception: Throwable) : UiState()
}
sealed interface는 sealed class와 유사하게 선언되지만, 하나의 클래스에서 여러 sealed 인터페이스를 구현할 수 있습니다.
sealed interface Action
sealed interface Loggable
data class Navigate(val route: String) : Action, Loggable
data class ShowToast(val text: String) : Action
object GoBack : Action, Loggable
Navigate 클래스는 Action과 Loggable이라는 두 개의 sealed 인터페이스를 동시에 구현합니다. 이는 단일 상속 제한으로 인해 sealed class에서는 불가능합니다. sealed interface는 독립적인 계층 구조를 결합하는 유연성을 제공합니다.
sealed interface는 계층 구조가 공유 상태나 생성자를 필요로 하지 않을 때 선호됩니다. JetBrains Kotlin Guidelines(2026)에 따르면, 공통 생성자가 필요하지 않은 모든 새 계층 구조에서는 기본적으로 sealed interface를 사용해야 하며, 이는 향후 확장을 위해 코드를 더 유연하게 만듭니다.
sealed 유형의 주요 장점은 when 표현식에서의 완전한(exhaustive) 처리입니다. 컴파일러는 가능한 모든 하위 클래스가 포함되었는지 확인합니다.
fun handleResult(result: NetworkResult): String = when (result) {
is NetworkResult.Success -> "Data: ${result.data}"
is NetworkResult.Error -> "Error: ${result.message}"
is NetworkResult.Loading -> "Loading..."
// else는 필요하지 않음 — 컴파일러가 모든 변형이 포함되었음을 알고 있음
}
만약 개발자가 sealed 계층 구조에 새 하위 클래스를 추가했지만 when에서 처리하는 것을 잊었다면, 컴파일러가 오류를 발생시킵니다. 이는 else 분기를 사용하는 개방형 계층 구조에서는 사용할 수 없는 유형 수준의 안전성입니다.
Google Android Developers(2026)에 따르면, sealed 클래스는 Jetpack Compose에서 UI 상태를 모델링하는 권장 방법입니다. when의 완전한 검사는 개발자가 화면의 가능한 모든 표시 변형을 처리하지 않은 상태를 방지합니다.
enum class와 sealed class는 종종 혼동되지만, 서로 다른 목적과 기능을 가지고 있습니다.
| 특징 | sealed class | enum class |
|---|---|---|
| 인스턴스 | 여러 개(data class), 하나(object) | 상수당 정확히 하나 |
| 속성 | 각 하위 클래스마다 다름 | 모든 상수에 동일 |
| 상속 | 가능(sealed class에서) | 불가능(암시적 final) |
| 생성자 | 매개변수를 가질 수 있음 | 모든 상수에 공통만 가능 |
| 계층 구조 | 제한됨, sealed | 고정된 상수 집합 |
sealed class와 enum class 사이의 선택은 작업에 따라 다릅니다. 변형이 추가 데이터를 전달하지 않으면 enum을 사용하십시오. 각 변형에 고유한 필드가 포함되어 있으면 sealed class 또는 sealed interface를 사용하십시오.
sealed 유형은 타입 안전 모델링이 필요한 일련의 표준 시나리오에서 Kotlin 프로젝트에 사용됩니다.
각 Compose 화면은 가능한 모든 상태(Idle, Loading, Content(data), Error(exception))를 설명하는 sealed class UiState를 가질 수 있습니다. when 표현식은 모든 상태가 처리되도록 보장합니다.
NetworkResult(Success, Error, Loading 변형)는 Retrofit 및 Ktor를 사용하는 Kotlin 프로젝트의 표준 패턴입니다. sealed class는 각 요청 결과의 안전한 처리를 보장합니다.
sealed interface를 사용한 네비게이션 경로는 모듈이 통합된 계층 구조 내에 있으면서 자체 경로를 선언할 수 있게 합니다. 이는 컴파일 타임에 알 수 없는 경로로 인한 오류를 제거합니다.
KotlinConf(2025)에 따르면, sealed class와 sealed interface는 현대 Kotlin 애플리케이션에서 타입 안전 디자인의 기초입니다. 이들은 data class와 결합되어 컴파일 타임 안전성을 잃지 않으면서 복잡한 도메인 구조를 모델링합니다.
자주 묻는 질문
sealed class의 모든 직접 하위 클래스는 동일한 파일에 선언되어야 합니다. sealed interface에도 동일한 규칙이 적용됩니다. 구현은 하나의 파일에 있어야 합니다.
아니요, 단일 파일 규칙은 sealed interface에도 적용됩니다. 모든 구현은 sealed interface가 선언된 파일에 있어야 합니다.
sealed interface는 상태나 생성자가 없으며 다중 구현을 허용합니다. sealed class는 생성자와 공유 상태를 가질 수 있지만, 클래스는 하나의 sealed class만 상속할 수 있습니다.
컴파일러가 when의 완전성을 확인합니다. 모든 하위 클래스가 처리되지 않으면 코드가 컴파일되지 않습니다. 이는 런타임 오류를 제거하고 코드를 더 안전하게 만듭니다.
네, sealed class는 생성자를 가질 수 있습니다(기본적으로 private). 모든 하위 클래스는 super()를 통해 이 생성자에 매개변수를 전달할 수 있습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.