xEzIxX/expressTest

JS 에러핸들링, 가독성이 좋은 코드

Opened this issue · 0 comments

가독성이 더 좋은 코드

중첩 레벨을 줄여 코드의 가독성을 높이기

코드를 먼저, 함수는 그 다음에 선언하기

이름만 보고도 헬퍼 함수의 역할을 쉽게 유추할 수 있게 헬퍼 함수 이름을 명명했다면 함수 본문을 읽을 필요도 없습니다.

주석

주석에 들어가면 좋은 내용

  1. 고차원 수준 아키텍처
  2. 함수 용례
  3. 당장 봐서는 명확해 보이지 않는 해결 방법에 대한 설명

try..catch와 에러핸들링

try {…} 블록 안에서 에러가 발생해도 catch에서 에러를 처리하기 때문에 스크립트는 죽지 않습니다.
실행 가능한(runnable) 코드, 즉 유효한 js코드에만 동작


js엔진은 코드를 읽고 난 후 코드를 실행!!

  • 코드를 읽는 중 발생하는 에러는 'parse-time에러'라고 부름, 엔진은 이해 못해서 코드 안에서 복구XXX
  • try..catch는 동기적으로 동작, 즉 setTimeout처럼 scheduled 코드에서 발생한 예외는 못잡는다. (왜냐면 setTime에 넘겨진 익명 함수는 엔진이 try..catch를 떠난 이후에 실행되기 때문에)
  • 이 예외를 잡으려면 반드시 함수 내부에 구현해야함
setTimeout(function() {
  try {
    noSuchVariable; // setTimeout같은 scheduled 코드 부에 try..catch 구현
  } catch {
    alert( "에러를 잡았습니다!" );
  }
}, 1000);

에러 객체

  • 에러가 발생하면 js는 에러 상세내용이 담긴 객체를 생성 -> catch블록에 이 객체를 인수로 전달!
  • 내장 에러 전체와 에러 객체는 두 가지 주요 프로퍼티*(name, message)*를 가짐

1. name(에러 이름/ err.name)
만약 정의되지 않은 변수 때문에 발생한 에러라면 "ReferenceError"가 이름이 됨.
2.message(에러 상세 내용을 담는 문자 메세지/ err.message)
3. stack(현재 호출 스텍/ err.stack)
에러를 유발한 중첩 호출들의 순서 정보를 가진 문자열
디버깅 목적으로 사용

throw연산자를 이용하여 직접 에러를 만들어서 던지기

  • 에러 객체에 name과 message 프로퍼티를 넣어주는 것을 권장
throw <error obj>
  • js는 Error, SyntaxError, ReferenceError, TypeError등의 표준 에러 객체 관련 생성자를 지원 -> 이 내장 생성자들을 이용하여 err 객체 생성 가능!
let error = new Error(message);
let error = new SyntaxError(message);
let error = new ReferenceError(message);
  1. 위와 같이 일반객체가 아닌* 내장 생성자를 사용해 만든 내장 에러 객체의 name 프로퍼티생성자의 이름과 동일한 값을 갖는다.
  • 프로퍼티 message의 값은 인수에서 가져옴.
let error = new Error("custom err message");

alert(error.name); // Error
alert(error.message); // custom err message
  1. 잘못된 데이터를 받았을 때, JSON.parse는 어떤 종류의 에러를 만들까?
    name프로퍼티가 없는 경우
try {
  JSON.parse("{ 잘못된 형식의 json o_O }");
} catch(e) {
  alert(e.name); // SyntaxError
  alert(e.message); // Unexpected token b in JSON at position 2
}

'throw 연산자를 통해' 에러 던지기

let json = '{ "age": 30 }'; // 불완전한 데이터

try {

  let user = JSON.parse(json); // <-- 에러 없음

  if (!user.name) {
    throw new SyntaxError("불완전한 데이터: 이름 없음"); // (*)
  }

  alert( user.name );

} catch(e) {
  alert( "JSON Error: " + e.message ); // JSON Error: 불완전한 데이터: 이름 없음
}

(*) : throw연산자는 message를 이용해 syntaxError를 생성
(에러 생성 방식은 자바스크립트가 자체적으로 에러를 생성하는 방식과 동일)

에러 '다시' 던지기

또 다른 예기치 않은 에러가 try {...} 블록 안에서 발생 할 수도!!!

let json = '{ "age": 30 }'; // 불완전한 데이터

try {
  user = JSON.parse(json); // <-- let user가 아님

  // ...
} catch(err) {
  alert("JSON Error: " + err); // JSON Error: ReferenceError: user is not defined
  // (실제론 JSON Error가 아닙니다.)
}

catch는 예상치 못한 에러를 잡긴 함, 그치만 위 코드에서는 종류에 상관없이 JSON Error 메세지를 보여줌-> 디버깅을 어렵게 만든다! -> 다시 던지기 기술 필요!!

  • catch는 알고 있는 에러만 처리하고 나머지는 다시 던져야 합니다!

다시 던지기 기술 :

  1. catch가 모든 에러를 받는다.
  2. catch(err){...}블록 안에서 에러 객체 err를 분석
  3. 에러 처리 방법을 알지 못한다면 throw err!
  • 보통 에러 타입instanceof 명령어로 체크
try {
  user = { /*...*/ };
} catch(err) {
  if (err instanceof ReferenceError) {
    alert('ReferenceError'); //  정의되지 않은 변수에 접근하여 'ReferenceError' 발생
  }
}
  • 혹은 err.name프로퍼티로 에러 클래스 이름을 알 수도 있음, 기본형 에러는 모두 err.name객체를 가짐/ 혹은 err.constructor.name을 사용할 수도 있음.
let json = '{ "age": 30 }'; // 불완전한 데이터
try {

  let user = JSON.parse(json);

  if (!user.name) {
    throw new SyntaxError("불완전한 데이터: 이름 없음");
  }

  blabla(); // 예상치 못한 에러

  alert( user.name );

} catch(e) {

  if (e instanceof SyntaxError) {
    alert( "JSON Error: " + e.message );
  } else {
    throw e; 
    //try..catch밖으로 rethrow->바깥에 try..catch가 있다면 거기서 에러를 잡음!!
  }

}
  • catch 블록에선 어떻게 다룰지 알고 있는 에러만 처리, 알 수 없는 에러는 ‘건너뛸 수’ 있습니다.
function readData() {
  let json = '{ "age": 30 }';

  try {
    // ...
    blabla(); // 에러!
  } catch (e) {   //readData는 SyntaxError만 처리
    // ...
    if (!(e instanceof SyntaxError)) {
      throw e; // 알 수 없는 에러 다시 던지기
    }
  }
}

try {
  readData();
} catch (e) {
  alert( "External catch got: " + e ); // 함수 바깥의 try..catch에서는 예상치 못한 에러도 처리
}

finally 절은 try..catch 절을 빠져나가는 어떤 경우에도 실행

return을 사용해 명시적으로 빠져나가려는 경우도 finally가 실행됨

try.. finally

에러를 처리하고 싶지 않지만, 시작한 프로세스가 마무리되었는지 확실히 하고 싶은 경우
아래 코드는 catch가 없어서 try안에서 발생한 에러는 항상 밖으로 나옴

function func() {
  // 무언가를 측정하는 경우와 같이 끝맺음이 있어야 하는 프로세스
  try {
    // ...
  } finally {
    // 스크립트가 죽더라도 완료됨
  }
}

try..catch에서 처리하지 못한 에러 잡기

따로 js에는 대응 방법이 없지만.. 호스트 환경 대다수는 자체적으로 에러 처리 기능 제공
Node.js의 process.on("uncaughtException")

커스텀 에러와 에러 확장

커스텀 에러와 에러 확장

참고 :
코어자바스크립트 - try..catch와 에러 핸들링
코어자바스크립트-코딩 스타일