[Kotlin] 봉인된 클래스(Sealed Class)와 봉인에 대하여

2026. 2. 9. 16:04·Language/Kotlin

1. 시작

모두가 잘 알고 사용하고 있는 클래스와 상속을 이용한 다형성은 Open-Closed Principal의 기본이자 단순한 구현에서 벗어나 각 클래스들에 명확하고 분명한 책임을 부여하는데 이점이 있다. 하지만 높은 확장성은 인터페이스나 추상 클래스를 사용해 결과로 받은 객체가 내가 정의한 서브타입임을 보장할 수 없음을 의미하기도 하다. 이러한 구조를 '제한 없는 계층구조(non-restricted hierarchy)'라고 하며, 아래와 같이 작성할 경우 else 구문이 강제된다.

abstract class Result

class Success(val data: String) : Result()
class Failure(val exception: Throwable) : Result()

// 'when' expression must be exhaustive. Add an 'else' branch.
fun handleResult(result: Result) = when (result) {
    is Success -> println("성공 히히힝")
    is Failure -> println("-,.-")
}

 

2. 봉인된 클래스(Sealed Class)

결국 다형성의 이점을 최대한으로 누리되, 무분별한 확장을 방지하여 타입 안정성을 확보하고 컴파일 타입 안정성을 확보하기 위해 등장한 것이 '봉인된 클래스(sealed class)'라고 볼 수 있다.

// sealed는 자동으로 추상 클래스가 되서 abstract 불필요
sealed interface Result

class Success(val data: String) : Result
class Failure(val exception: Throwable) : Result

 

봉인된 클래스나 인터페이스의 서브타입들은 다음의 제약조건을 가진다.

  • 봉인된 클래스나 봉인된 인터페이스와 같은 패키지와 모듈에서 정의되어야 한다.
  • 지역적이 될 수 없고, 객체 표현식을 사용해 정의할 수 없다.
package com.gani.kotlinexcercise.essentials.sealed

class Malformed() : Result
class Jesus() : Result

// object declaration is possible
object Goat : Result

fun printTeaPot() = run {
    // Anonymous object cannot extend a sealed interface.
    val teaPot = object { //: Result {
        val status = 418
        val message = "I'm a teapot"
    }

    println("${teaPot.status} ${teaPot.message}")
}
package com.gani.kotlinexcercise.essentials.sealed.other

// A class can only extend a sealed class or interface declared in the same package.
class Impossible() // : Result

 

정리하자면 sealed 클래스(또는 sealed interface)는 “가질 수 있는 타입의 경우의 수”를 제한하는 도구다. 즉 상속 가능한 서브타입의 범위를 컴파일 타임에 봉인해 두고, 그 집합 안에서만 상태와 행위를 표현하도록 강제한다. 이는 값이 아니라 구조와 역할의 범위를 닫는 개념에 가깝다. 같은 Result라는 추상 개념 아래 Success, Failure와 같은 서로 다른 타입을 배치하고, when이나 switch에서 모든 경우를 안전하게 다루도록 만드는 식이다. 다시 말해 sealed는 ‘서브타입의 집합’을 정의하는 모델링 도구다.

 

어떤 제한적인 개념 속에서 Enum과 사용처가 어떻게 다른가라고 생각할 수 있지만, enum은 ‘값의 집합’을 표현한다. 가능한 선택지가 미리 정해진 상수 목록이며, 각각은 독립적인 타입이 아니라 동일한 열거형의 인스턴스다. 상태의 종류나 코드값, 옵션 목록처럼 변하지 않는 선택지를 명확히 나열하는 데 강하다. 같은 “경우의 수를 제한한다”는 공통점이 있지만, sealed가 타입 계층을 닫아 구조적 모델링을 돕는다면 enum은 정해진 값의 목록을 선언해 의미를 고정하는 데 초점이 있다. 결국 sealed는 타입을 제한하고, enum은 값을 제한한다는 차이가 본질이라고 볼 수 있다.

 

3. How to seal(미완성)

그럼 여기서 한 가지 궁금해지는 것은 "컴파일러는 도대체 어떻게 sealed의 하위 타입을 전부 알고 있는 걸까?" IDE가 분기의 누락 지점을 경고하고, 새로운 subtype이 생기면 기존 코드가 바로 깨지는 걸 보면 컴파일러가 알고 있는 것은 확실하기 때문이다.

 

컴파일 과정에서 컴파일러는 소스 코드를 파싱해 Syntax Tree를 만드는 과정을 거치는데, 이 때 sealed 키워드를 발견하면 동일한 패키지 내에서 해당 클래스를 상속받는 하위 클래스들을 샅샅이 찾는다(Kotlin 1.0 ~ 1.4는 동일한 파일 내에 있어야 했음). 그리고 sealed 키워드가 붙은 클래스의 경우 이 하위 클래스들의 추적을 위해 sealedSubclassess에 담아두고 관리하며, JVM 바이트 코드를 생성할 때에는 PermittedSubclasses라는 속성을 이용해 관리하게 된다. 

// K1
/**
 * @return direct subclasses of this class if it's a sealed class, empty list otherwise
 */
@ReadOnly
@NotNull
Collection<ClassDescriptor> getSealedSubclasses();

 

K2 컴파일러에서는 Descriptor 대신 Symbol과 FirClass 개념을 사용한다고는 하는데, 으악 아직은 여기까지 살펴보기에는 더 기본적으로 알아야 할 것이 많은 것 같아 여기까지... 똥싸다 끊은 것 처럼 마무리되는 기분이지만 쓰고 있는 본인도 이 기분을 느끼고 있기 때문에 기본적인 학습을 더 하고 컴파일 과정에서의 궁금증을 조금 더 해소해서 이 3번을 보다 정확한 정보를 전달할 수 있도록 보완하겠다..! (급 gg)


REFERENCES

1. 마르친 모스카와.  『코틀린 아카데미 - 핵심편』. 프로그래밍인사이트, 2022.

2. Kotlin Documentation — Sealed classes and interfaces

3. Kotlin Blog - New Language Features Preview in Kotlin 1.4.30

반응형
저작자표시 비영리 변경금지 (새창열림)

'Language > Kotlin' 카테고리의 다른 글

[Kotlin] 인라인 함수(inline function)  (0) 2026.02.10
[Kotlin] 다양한 형태의 객체(object, companion, data, constant)  (0) 2026.02.04
[Kotlin] 데이터 묶음을 표현하는 Data Class  (0) 2026.02.03
'Language/Kotlin' 카테고리의 다른 글
  • [Kotlin] 인라인 함수(inline function)
  • [Kotlin] 다양한 형태의 객체(object, companion, data, constant)
  • [Kotlin] 데이터 묶음을 표현하는 Data Class
갈닉
갈닉
중요한 건 엔지니어가 되겠다는 마음. 근데 이제 인문학을 곁들인.
    반응형
  • 갈닉
    KwanIk Devlog
    갈닉
  • 전체
    오늘
    어제
    • 분류 전체보기 (57)
      • Algorithm (41)
        • 알고리즘 개요 (8)
        • 문제풀이 (33)
      • Language (6)
        • Java (1)
        • Kotlin (4)
        • Rust (1)
      • Framework (0)
        • Spring (0)
        • Spring Security (0)
        • Spring Data JPA (0)
      • Computer Science (1)
        • 프로그래밍 언어 (0)
        • 자료구조 (1)
        • 보안 (0)
      • ETC (1)
        • MSA (0)
        • TDD (1)
        • DDD (0)
      • 개발서적 (3)
        • 오브젝트 (3)
      • Life (5)
        • 생각생각 (4)
        • 회고록 (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

    • My Github
  • 공지사항

  • 인기 글

  • 태그

    객체지향
    java
    bitmask
    오브젝트
    DP
    시뮬레이션
    Algorithm
    구현
    greedy
    boj
    backtracking
    비트마스크
    코틀린
    백준
    BFS
    Kotlin
    자바
    알고리즘
    너비우선탐색
    백트래킹
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
갈닉
[Kotlin] 봉인된 클래스(Sealed Class)와 봉인에 대하여
상단으로

티스토리툴바