에러를 다루기

우리는 무엇을 다룰 것인가?
  • 에러를 다루는 두 가지 방법
  • 다른 사람들이 잡을 수 있도록 우리의 코드에서 에러를 들어올리기
  • 전통적인 방법

    전통적으로 프로그래머가 작업을 할때는, 예를 들어 함수를 호출할때는, 함수의 결과는 유효성을 검증받을 수 있다. 예를 들어 여러분이 존재하지 않는 파일을 열려고 한다면 반환값은 NULL 값이 될 것이다. 이러한 종류의 상황을 다루는 데는 두 개의 일반적인 전략이 있다:

    1. 함수의 결과에 에러코드를 포함하거나 혹은
    2. 에러의 상태에 대하여 전역 변수를 설정한다.

    어떤 경우에나 에러가 일어났는지 알아보거나 적절한 조치를 취하는 것은 프로그래머의 책임이다.

    BASIC에서 이것은 다음과 같이 보인다:

    OPEN "A:\DATA.TXT" FOR INPUT AS #1
    IF ERR = 53 THEN
       CALL FileNotFoundError
    ELSE
       REM CONTINUE WITH FILE HANDLING HERE
    END IF
    

    이것은 질좋은 프로그램을 생산한 결과가 될 수도 있는데 코드의 절반이상이 모든 작동들이 성공했는지 점검하는데 점유된다. 이것은 성가시며 그 코드를 읽기에 어렵게 만든다 (그러나 실제로 그것은 대다수의 프로그램들이 오늘날 작동하는 방식이다.) 말도 안되는 실수를 피하고자 한다면 일관적인 접근법은 필수적이다.

    예외적인 방법

    더욱 많은 최근의 프로그래밍 환경에서 에러를 다루는 대안적인 방법이 개발 되었다. 이것은 예외처리 라고 불리는 것으로 에러를 버리거나( throw) 혹은 들어올리거나(raise) 함으로써 작동한다. 그러면 시스템은 현재의 코드 블록을 탈출하여 가장 가까운 예외처리 블록으로 강제적으로 점프한다. 시스템은 모든 예외상황을 나포하는 catches 기본 처리기를 제공하며 보통 에러메시지를 출력하고 종료한다.

    예외처리 블록은 약간은 if...then...else 블록과 비슷하게 코딩된다:

    try:
       # program logic goes here
    except ExceptionType:
       # exception processing for named exception goes here
    except AnotherType:
       # exception processing for a different exception goes here
    else:
       # here we tidy up if NO exceptions are raised
    

    우리가 에러발생 후에 말끔하게 정리할 수 있도록 해주는 또 다른 형태의 '예외' 블록이 있디. 그것을 try...finally 블록이라 부르며 전형적으로 파일을 닫고, 버퍼를 디스크에 강제로 쓰는 등등에 사용된다. finally 블록은 try섹션에서 무슨일이 일어나든지 간에 마지막으로 항상 실행된다.

    try:
       # normal program logic
    finally:
       # here we tidy up regardless of the
       # success/failure of the try block
    

    티클은 catch 키워드를 사용하여 어느정도는 비슷한 메카니즘을 가진다:

    set errorcode [catch {
        unset x
        } msg ]
    if {$errorcode != 0} {
        # handle error here
        }
    

    이 경우에 x 는 존재하지 않는다 그래서 우리는 그것을 설정취소 unset 할 수 없다. 티클은 예외를 발생시키지만 catch는 프로그램이 취소되지 않도록 하며 대신에 에러메시지를 msg변수에 집어 넣고 0 이 아닌 값을 반환한다 (그것은 프로그래머에 의해서 정의될 수 있다.). 여러분은 그러면 errorcode에 나포된 반환값을 점검할 수 있다. 만약 0 이 아니라면 그러면 에러가 발생되었고 여러분은 msg변수를 조사할 수 있다.

    베이직은 예외 처리를 지원하지 않지만 그러나 코드를 깨끗하게 유지하는데 도움을 주는 구조를 가지고 있다:

    100 OPEN "A:\Temp.dat" FOR INPUT AS #1
    110 ON ERROR GOTO 10010
    120 REM PROGRAM CODE HERE...
    130 ...
    10000 REM ERRORHANDLERS:
    10010 IF ERR = 54 THEN....
    

    라인 넘버의 사용을 주목하라. 이것은 초기의 베이직을 포함하여 예전의 프로그래밍 언어에서는 일반적인 것이었다. 이제 여러분은 라벨labels로 같은 일을 할 수 있다:

    ON ERROR GOTO Handler
    REM Now create divide by zero error
    x = 5/0
    Handler:
       IF ERR = 23 THEN
          PRINT "Can't divide by 0"
          x = 0
          RESUME NEXT
       END IF
    

    RESUME NEXT을 주목하라. 그것으로 여러분은 에러가 발생한 바로 뒤로 복귀하여 그 프로그램을 계속진행할 수 있다.

    에러를 들어올리기

    우리가 다른 사람들이 나포할 수 있도록 예외상황을, 예를 들어 모듈에서 만들기를 원한다면 무슨일이 일어나는가? 이 경우에 우리는 파이썬에 있는 raise키워드를 사용한다:

    numerator = 42
    denominator = input("What value will I divide 42 by?")
    if denominator == 0:
       raise "zero denominator"
    

    이것은 문자열 객체 예외를 들어올려 try/except 블록이 나포할 수 있도록 한다.

    Tcl의 에러 메카니즘

    Tcl에서 return 서술문은 선택적인 -code 플래그를 취하는데 그것은 괄호쳐진 catch에 의해서 나포되어 진다:

    proc spam {val} {
            set x $val
            return -code 3 [expr $x]
            }
    set err [catch {
                   set foo [spam 7]
                   } msg]
    

    err 는 값 3을 가져야 하며 msg는 값 7을 가져야 한다. 또 다시 티클의 구문은 이전에 그랬던 것 보다는 덜 직관적이다

    BASIC의 에러 처리

    베이직에서 여러분은 ERR 변수를 ERROR 서술문으로 설정할 수 있다:

    ON ERROR GOTO ERRORS
    INPUT "INPUT ERROR CODE"; E
    ERROR E
    
    ERRORS:
    IF ERR = 142 THEN
        PRINT "Error 142 found"
        STOP
    ELSE
        PRINT "No error found"
        STOP
    END IF
    
    


    기억해야 할 것
  • if 서술문을 사용하여 에러코드를 점검하라
  • except절로 예외상황을 처리하라
  • raise 키워드를 사용하여 예외상황을 설정하라
  • 에러는 단순한 문자열일 수 있다.
  • Previous  Next  Contents


    이 페이지에 대하여 질문 혹은 제안사항이 있으면 다음 주소로 나에게 전자메일을 보내라: agauld@crosswinds.net