프로그래밍백엔드 개발자 (Kotlin)

Kotlin에서 예외 처리(Exception Handling)는 어떻게 작동합니까? Kotlin의 접근 방식은 Java와 어떻게 다른지, 예외는 어떻게 처리하며, checked/unchecked 예외의 뉘앙스는 무엇인지, try/catch/finally의 사용은 어떤 영향을 미칩니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

Kotlin에서 예외 처리는 try/catch/finally 구조를 사용하여 구현되지만, Java 접근 방식과는 달리 Unchecked Exceptions에 중점을 두고 간결한 구문을 가지고 있습니다. 중요한 차이점은 Kotlin은 checked exceptions이 없으므로 프로그래머가 throws를 명시하거나 그러한 예외를 포착하는 부담이 없다는 것입니다.

문제의 역사

Java는 checked/unchecked exceptions을 사용하며, checked는 명시적인 포착이나 선언을 요구합니다. 이는 종종 임의의 보일러플레이트와 불편한 코드를 초래합니다. Kotlin은 더 간단하게 설계되었으며, 대부분의 예외는 unchecked (RuntimeException으로부터 상속된)여서 처리하기가 쉬우며 코드의 가독성을 높입니다.

문제

Java 개발자들은 Kotlin에서 checked exceptions을 포착하려고 시도하며, 코드는 컴파일되지만 의미가 사라집니다. 또한 finally를 사용할 때의 뉘앙스를 이해하지 못하면 누수나 작동하지 않는 코드가 발생할 수 있습니다.

해결책

Kotlin에서 try/catch/finally를 간결하고 목적에 맞게 사용하세요:

fun process(data: String): Int = try { data.toInt() } catch (e: NumberFormatException) { 0 } finally { println("Processing done") }
  • try/catch/finally는 표현식으로 사용할 수 있어, 함수의 최종 결과가 되거나 변수에 할당될 수 있습니다.
  • 여러 예외를 포착할 수 있으며, catch 내부에서 when 구문을 사용하여 예외 유형에 따른 다양한 반응을 구현할 수 있습니다.

주요 특징:

  • checked exceptions이 없음 — 명시적으로 선언하거나 처리할 필요가 없습니다.
  • try 구조는 표현식으로 작동할 수 있습니다 (결과를 반환함).
  • finally는 종료 작업(예: 자원 정리)에 사용할 수 있지만, 반환 값을 수정하는 작업은 피해야 합니다.

함정이 있는 질문.

finally 블록에서 예외가 발생하면 무엇이 발생합니까? 이것이 반환 값에 어떤 영향을 줍니까?

finally에서 발생한 예외는 항상 try/catch 블록에서의 다른 예외나 return을 덮어쓰므로, 사고 원인에 대한 중요한 데이터 손실이 발생할 수 있습니다.

fun demo(): Int = try { 1 } finally { throw RuntimeException("error in finally") }

Kotlin에서 try/catch가 표현식이 될 수 있습니까? Java와의 차이점은 무엇입니까?

네. Kotlin의 try/catch/finally는 표현식이므로 결과를 반환할 수 있으며 값이 허용되는 위치에서 사용할 수 있습니다.

val value = try { risky() } catch (e: Exception) { fallback() }

Java에서는 이것이 오직 연산자입니다.

throws가 있는 외부 Java 함수를 호출할 경우, Kotlin에서 예외 처리는 반드시 필요합니까?

아니요. checked exceptions는 Kotlin 컴파일러에 의해 무시되므로 명시적으로 포착할 필요가 없지만 실행 중에 여전히 발생할 수 있습니다.

일반적인 오류 및 안티패턴

  • 모든 예외를 포착하는 불필요한 시도 (catch (e: Exception)) — 올바르게 처리할 수 없는 것을 잡음.
  • finally를 잘못 사용하여 반환값을 수정하거나 예외를 전달하는 것.
  • Kotlin 코드 내에서 throws 선언을 사용하려고 하는 시도.

실생활 예제

부정적인 사례

실제와 기대하는 오류를 구분하지 않고 catch (e: Exception)를 구분없이 사용합니다. finally에서 값을 반환하려고 시도하여 오류 발생 시 예기치 않은 동작을 초래합니다.

장점:

  • 모든 실패에 견고하게 대처할 수 있는 코드

단점:

  • 디버깅이 어렵습니다.
  • 오류 메시지 및 발생 원인이 사라집니다.
  • 실제 문제를 숨깁니다.

긍정적인 사례

기대하는 오류만 포착하고 finally는 자원 정리에만 사용하며 try/catch는 가독성을 높이는 곳에서 표현식으로 사용합니다.

장점:

  • 읽고 유지보수하기 쉽고 테스트하기 용이합니다.
  • 명확한 오류 처리

단점:

  • API 설계 및 예외 처리 시 규율이 요구됩니다.