앞서 배웠던 try catch를 알아보면서... 더 깊은 공부를 해보도록 하자.
프리코스에서 했던 throw
문법도 공부하면서 말이다! (throw는 추후 포스팅)
throw
는 간단하게 말하면 에러를 생성하는 키워드이다.
문법은 아래와 같다.
throw <error object>
이론적으로는 모든 자료형을 에러 객체(원시형 자료형도 포함)로 사용할 수 있다. 하지만 이전 게시글에서 배웠던 기본 내장 에러(name, message를 프로퍼티로 갖는 에러 객체)와의 호환을 위해 name, message 프로퍼티를 포함하는 객체로 에러 객체를 만들 것을 권장한다.
자바스크립트는
등 우리가 흔히 보는 에러이름으로 객체 생성자를 지원한다. 말로하니 어렵다. 쉽게 설명하자면 아래와 같은 코드를 작성할 수 있다는 뜻이다.
let error = new Error(message);
let error = new SyntaxError(message);
let error = new ReferenceError(message);
일반 객체가 아닌 내장 생성자를 사용해 만든 내장 에러 객체의 name
프로퍼티는 생성자 이름과 동일한 값을 갖는다. (SyntaxError로 만들었으면 SyntaxError가 name 프로퍼티임) 프로퍼티 message
의 값은 인수에서 가져온다.
아래 코드처럼 말이다!
let error = new Error('에러 발생~!');
alert(error.name); // Error
alert(error.message); // 에러 발생~1
서버에서 사용자 정보를 가져온다고 생각해보자. 사용자 정보에서 name은 포함되어 있겠다고 예상할 수 있다.
그런데 만약 받아온 사용자 정보에 name이 없다면? 에러를 발생시켜서 잡아야한다.
아래 코드처럼 말이다.
try {
let user = JSON.parse(json); // 서버에서 사용자 정보를 가져오는 코드
if(!user.name) {
throw new SyntaxError('불완전한 데이터: 이름 없음'); // 에러 생성
}
} catch(e) {
alert('JSON Error: ' + e.message); // JSON Error: 불완전한 데이터: 이름 없음
}
'예를 통해 이해해보자' 에 적힌 코드를 다시 읽어보자.
try에서 name을 받아오지 못한 에러로 catch에서 경고하게 된다.
그런데 만약 try에서 다른 에러가 발생한다면.. 의도치 않은 내용이 e.message
에 담기게 된다. JSON Error가 아닌데도 말이다.
그럼 어떻게 처리해야할까? 다시 던지기
를 이용하면 된다.
catch는 알고있는 에러만 처리하고 나머지는 다시 던지기
. 이게 다시 던지기
의 정의이다.
과정은 다음과 같다.
1. catch
는 모든 에러를 받는다
2. catch(err) {...}
블럭 안에서 에러 객체 err
을 분석한다.
3. 에러 처리 방법을 알지 못하면 throw err
를 한다.
이때 에러 타입 체크를 instanceof 명령어를 사용한다. (근데 이 명령어는 지양해야한다고 한다. 이유는 추후 블로깅)
try {
user = {...}; // 변수 선언 키워드(let 등)를 사용하지 않았다. 에러 발생
} catch (err) {
if(err instanceof ReferenceError) {
alert('ReferenceError');
}
}
원래의 예제로 돌아가서 다시 던지기
를 적용해보면 다음과 같다.
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; // 에러 다시 던지기 (*)
}
}
catch 안의 (*)에서 다시 던져진 에러는 try catch 의 밖으로 던져진다. 이때 밖에 try catch 가 있다면 여기서 에러를 잡으며, 아니라면 스크립트는 죽는다.
이런 방식으로 catch 블럭에서는 어떻게 다룰지 알고 있는 에러만 처리하고, 알 수 없는 에러는 '건너뛸 수' 있는 것이다.