0%

Error Handling

Error Handling


에러가 런타임에서 성공적으로 확인된 경우,

  1. 현재 스택에서 함수 실행을 중단하고
  2. 프로세스 노드에서 프로세스를 종료하고
  3. 스택을 추적해 콘솔에서 사용자에게 에러에 대한 설명을 제공한다.

  1. 단순히 에러를 확인만 하지 말고, Handling 하자!

    • console.log 를 사용하면 에러 로그와 헷갈리기 쉽기 때문에 자제하고,
    • try - catch 문으로 감쌌다면 에러를 예상한 것이므로, 해당 에러에 대한 해결 방안을 마련해 놓아야 한다.

    👇

    • console.error 또는 console.exception 활용하기

      error

      1
      2
      3
      4
      console.debug('디버그 메세지'); 
      console.info('정보 메세지');
      console.warn('경고 메세지');
      console.error('에러 입니다.');
    • 유저에게 error를 알리기

    • 서비스 자체에 error를 기록하기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // bad
    try {
    functionThatMightThrow();
    } catch (error) {
    // just logging out
    console.log(error);
    }

    // good
    // error "handling"
    try {
    functionThatMightThrow();
    } catch (error) {
    // 1. console.error
    // === console.exception
    console.error(error);
    // 2. 유저에게 알리기
    notifyUserOfError(error);
    // 3. 서비스 자체에 에러 기록하기
    reportErrorToService(error);
    // ... etc
    }
  2. Promise 가 반환한 rejected 를 넘기지 말고, Handling 하자!

    Handling 방법은 위와 동일하게, 각 에러에 맞게 정의한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // bad
    getdata()
    .then(data => {
    functionThatMightThrow(data);
    })
    .catch(error => {
    // just logging out...
    console.log(error);
    });

    // good
    getdata()
    .then(data => {
    functionThatMightThrow(data);
    })
    .catch(error => {
    // 1.
    console.error(error);
    // 2.
    notifyUserOfError(error);
    // 3.
    reportErrorToService(error);
    // ...etc
    });

기본적인 Handling 방법

JAVA 기준


  • 오류 코드보다 예외 를 사용할 것

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public void sendShutDown() {
    try {
    tryToShutDown();
    } catch (DeviceShutDownError e) {
    logger.log(e);
    }
    }

    private void tryToShutDown() throws DeviceShutDownError {
    DeviceHandle handle = getHandle(DEV1);
    DeviceRecord record = retrieveDeviceRecord(handle);
    pauseDevice(handle);
    clearDeviceWorkQueue(handle);
    closeDevice(handle);
    }
  • try-catch-finally 부터 작성할 것

    • try 문은 transaction처럼 동작하는 실행코드로, catch 문은 try문에 관계없이 프로그램을 일관적인 상태로 유지하도록 한다.
  • 예외에 의미를 제공할 것

    • 예외를 던질 때는 전후 상황을 충분히 덧붙인다.
    • 실패한 연산 이름과 실패 유형도 언급한다.
  • 호출자를 고려해 예외 클래스를 정의할 것

    • 써드파티 라이브러리를 사용하는 경우 그것들을 wrapping함으로써 라이브러리 교체 등의 변경이 있는 경우 대응하기 쉬워진다.
    • Wrapper 클래스를 이용하여 호출하는 라이브러리 API를 감싸면서 예외 유형 하나를 반환하므로 의존성이 크게 감소한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    try {
    port.open();
    } catch (PortDeviceFailure e) {
    reportError(e);
    logger.log(e.getMessage(), e);
    } finally {
    ...
    }

    public class LocalPort {
    ...

    public void open() {
    try {
    innerPort.open();
    } catch (DeviceResponseException e) {
    throw new PortDeviceFailure(e);
    } catch (ATM1212UnlockedException e) {
    throw new PortDeviceFailure(e);
    } catch (GMXError e) {
    throw new PortDeviceFailure(e);
    }
    }
    }
  • 에러 시 null 을 반환하거나 전달하지 말 것



Ref

https://ibrahimovic.tistory.com/39

https://nesoy.github.io/articles/2018-02/CleanCode-ErrorHandle