Visual Basic에서는 예외 처리를 위해 Try...Catch...Finally 블록을 사용합니다. 예외를 가로챈 후 재던지려면 — 즉, 호출 스택을 따라 예외를 전달하려면 Throw 또는 Throw ex 연산자를 사용합니다.
차이점:
Throw (인자 없음)는 현재 예외를 재던지며 원래의 호출 스택(Call Stack)을 유지합니다.Throw ex는 예외 객체를 던지지만 호출 스택을 리셋하여 실제 문제 발생 위치에 대한 정보를 제거합니다.변경되지 않은 예외의 경우, 예외를 올바르게 재던지기 위해 인자 없는 Throw를 사용하는 것이 좋습니다.
올바른 재던지기 예:
Try DangerousOperation() Catch ex As Exception ' 로깅... Throw ' 호출 스택이 유지됩니다. End Try
잘못된 방법:
Try DangerousOperation() Catch ex As Exception Throw ex ' 호출 스택 리셋, 진단이 어려워집니다. End Try
Throw 대신 Throw ex를 사용할 경우 호출 스택에 어떤 일이 발생하나요?
인자 없는
Throw를 사용하면 원래의 호출 스택이 유지됩니다 — 예외가 발생한 위치입니다.Throw ex를 사용하면 스택이 현재 줄에서 시작되며 원래 발생 위치가 사라집니다. 이는 디버깅을 복잡하게 만드는데, 문제가 발생한 코드의 어느 부분인지 알 수 없습니다.
이야기
대형 은행 프로젝트에서 개발자들이 논리 오류를 던지기 위해
Throw ex를 사용하였습니다. 로그를 분석할 때, 예외가 발생한 위치를 확인할 수 없었습니다. 왜냐하면 그들은 올바른 추적이 없었기 때문입니다.
이야기
데이터 접근 계층에서는 SqlException을 재던지기 위해
Throw를 사용했으나, 어떤 경우에는 자동 코드 포맷팅 도구가 이를Throw ex로 자동 변경했습니다. 이로 인해 로그에서 자동 데이터 추출 시스템이 고장났고, 사고 대응 시간이 증가했습니다.
이야기
Exception 객체를 수정하고 인자 없는
Throw로 재던지려는 시도가 로그에 변경 사항이 기록되지 않게 만들었습니다 — 오직 원래 객체를 InnerException으로 유지하며 새 예외 객체를 명시적으로 생성하는 것으로만 문제가 해결되었습니다.