Java, Kotlin은 둘 다 JVM 생태계 언어로써 상당히 비슷한 면이 많다.
하지만 둘은 다른 언어다보니, 당연히 다른 점들도 꽤 많이 존재한다. kotlin의 null-safe operator로 편리하고 안전하게 null 관련 처리를 할 수도 있고, 확장함수를 통해 자유롭게 커스터마이징이 가능하며, 다양한 lambda functions를 제공해줌으로써 Java의 stream 기능 못지 않게 간단한 코드를 작성할 수 있다.
그럼 반대로 Java에선 제공해주지만 Kotlin에서는 제공하지 않는 기능이 뭐가 있을까?
Java에서는 checked exception을 제공하지만, Kotlin에서는 이를 제공하지 않는다!
이번 포스팅에선 이 내용에 대해 적어보도록 하겠다.
Checked Exception? Unchecked Exception?
먼저 checked exception과 unchecked exception이 무엇인지부터 살펴보자.
간단히 말하자면 RuntimeException을 상속받는 예외들은 unchecked exception, 그렇지 않으면 checked exception이다.
만약 커스터마이징한 예외를 반환하고 있다면 해당 예외들은 unchecked exception이다. 또, 값을 0으로 나눈다거나 배열에 접근할 때 범위를 벗어난 인덱스에 접근할 경우도 unchecked exception이다.
checked exception은 Runtime 시에 발생하는 예외가 아닌, IOException, SQLException과 같이 컴파일러 입장에서 알아챌 수 있는 예외들을 주로 의미한다.
참고로 기본 전략으로는 unchecked exception은 발생하면 트랜잭션이 rollback되지만, checked exception은 발생해도 트랜잭션이 commit 돼버리므로 주의하자. 기본적으로 DB 트랜잭션은 RuntimeException이 발생하면 rollback을 시키도록 동작되기 때문이다. 아래 영상을 한번 참고해보자.
Kotlin은 왜 Checked Exception을 제공하지 않을까?
위에서 보았듯이 exception에는 checked exception과 unchecked exception이 존재한다.
그리고 Java에서는 checked exception을 제공하지만 kotlin에서는 checked exception을 제공하지 않는다.
정말인가 싶어 이전에 일부 개발에 참여했었던 우아한테크코스 지원플랫폼 레포에서 예외를 열심히 찾아보았지만 정말로 RuntimeException을 상속하는 예외들만 존재했다.
https://github.com/woowacourse/service-apply
왜 그런걸까?
kotlin 개발자들이 이를 깜빡한걸까?
그렇지 않다!
kotlin 공식문서를 보면 이유가 자세히 나와있다.
Appendable append(CharSequence csq) throws IOException;
This signature says that every time I append a string to something (a StringBuilder, some kind of a log, a console, etc.), I have to catch the IOExceptions. Why? Because the implementation might be performing IO operations (Writer also implements Appendable). The result is code like this all over the place:
try {
log.append(message)
} catch (IOException e) {
// Must be safe
}
And that's not good. Just take a look at Effective Java, 3rd Edition, Item 77: Don't ignore exceptions.
출처: kotlin 공식문서(https://kotlinlang.org/docs/exceptions.html#checked-exceptions)
checked exception을 유발하는 메서드를 보면 위와 같이 메서드 옆에 throws로 해당 예외를 프로그래머가 처리하도록 한다.
그렇기 때문에 위처럼 매 코드마다 try-catch로 예외를 처리해야한다. 만약 FileNotFoundException이라면 default 파일로 대체하는 방법도 있겠지만, 그 외의 IOException, SQLException일 경우는 진짜 위처럼 열심히 try-catch로 예외를 처리해주어야 할 것이다.
이는 개발자의 생산성을 낮출 뿐 아니라, 가독성 면에서도 좋지 않다.
공식문서에도 소개돼있듯이, `이펙티브 자바 Item 77: 예외를 무시하지 말라`처럼 예외를 명확하게 처리해주어야 한다.
checked exception이 발생될 때 포괄적인 예외인 IOException, SQLException을 넘겨주는 것은 해당 원칙에 위배된다.
그렇다고 checked exception을 try-catch로 처리한 후 catch 내에서 별도로 커스터마이징된 명확한 예외인 unchecked exception을 다시 넘겨줄 바에는 아예 checked exception을 사용하지 않는 것이 더 좋을 수 있는 것이다.
이와 같은 이유로 kotlin에서는 checked exception을 별도로 제공하지 않는다고 한다.
불분명하고 다루기 힘든 checked exception을 사용할 바엔 아예 checked exception을 사용하지 않는 방안을 택한 것 같다.
kotlin 공식문서에 아래 문서들을 추가 증거물(?)로 제공했는데, 관심 있으면 한 번 읽어보도록 하자.
https://www.artima.com/articles/the-trouble-with-checked-exceptions
https://radio-weblogs.com/0122027/stories/2003/04/01/JavasCheckedExceptionsWereAMistake.html
추가로, Kotlin과 Java의 차이점을 정리한 공식문서도 있다!
관심있으면 살펴보길 바란다.
https://kotlinlang.org/docs/comparison-to-java.html#what-kotlin-has-that-java-does-not
참고
- 코틀린 공식문서: https://kotlinlang.org/
- checked exception, unchecked exception: https://cheese10yun.github.io/checked-exception/
- 이펙티브 자바 3판 10장_예외 관련 정리 포스팅: https://madplay.github.io/post/effectivejava-chapter10-exceptions
- checked exception, unchecked exception 사진 출처: https://codegym.cc/groups/posts/28-exceptions-checked-unchecked-and-custom
- 우테코 지원플랫폼 코틀린 코드: https://github.com/woowacourse/service-apply
'Kotlin > Kotlin | Spring 학습기록' 카테고리의 다른 글
[Spring] ArgumentResolver 사용 시 주의점 (feat. OSIV) (3) | 2023.02.26 |
---|---|
[Kotlin] Swagger 문서에 DTO 필드 required 표시해주기 (0) | 2023.02.21 |
[Kotest] Nested Test spec에서의 context 생명주기 및 트랜잭션 (11) | 2022.09.08 |
[Kotest] Kotest Spec으로 다양한 테스트 코드 스타일을 작성해보자 (0) | 2022.08.13 |
[Kotlin] Kotlin DSL + Spring REST Docs + MockMvc 적용기 (2) (0) | 2022.07.17 |