아무리 능한 사람이라도, 에러있는 스크립트를 작성할 수 있습니다.
원인은 실수, 예상치 못한 사용자 입력, 잘못 된 서버 응답 등이 될 수 있습니다.
스크립트에서 에러가 발생하면, 스크립트는 죽고(중단되고) 콘솔에 에러가 출력됩니다.
그러나 try...catch
를 통해 스크립트가 죽는걸 방지하고,
에러를 잡아서(catch) 더 나은 무언가를 할 수 있습니다.
try
와 catch
두개의 주요 블록으로 구성됩니다.
try {
// 코드
}
catch (err){
// 에러 핸들링
}
try
내의 코드가 실행되고, 에러가 없다면 끝까지 실행된 후 catch
는 무시됩니다.
에러가 있다면, 실행이 중단되고, catch
블록으로 흐름이 넘어갑니다.
err
은 무슨일이 일어났는지에 대한 '에러 객체'를 포함합니다.
try...catch
는 런타임 에러에만 동작합니다.
중괄호 짝이 안 맞는 등 문법적으로 잘못되면, 동작하지 않습니다.
자바스크립트 엔진은 코드를 읽고, 코드를 실행합니다.
읽는 중에 생긴 에러는 parse-time 에러
라고 부르는데, 코드를 이해할 수 없기 때문에,
코드 안에서 복구가 불가능합니다.
try...catch
는 유효한 코드에서의 에러만 처리하며,
이를 런타임 에러, 예외(Exception)
라고 부릅니다.
try...catch
는 동기적으로 작동합니다.
setTimeOut
처럼 스케줄된 작업은 처리하지 못합니다.
에러가 발생하면 자바스크립트는 에러 상세내용이 담긴 객체를 생성합니다.
두가지 주요 프로퍼티를 가집니다.
name
: 에러의 이름message
: 에러의 상세 내용 메시지표준은 아니지만, 대부분의 호스트 환경에서 제공하는 프로퍼티 stack
stack
: 현재 호출 스택, 에러를 유발한 중첩 호출들의 순서 정보에러에 대한 상세한 정보가 필요하지 않으면, catch
에서 인자를 생략할 수 있습니다.
try{
// 코드
}
catch{ // -> (err) 생략
// 핸들링
}
try...catch
사용 예제
JSON으로 인코딩 된 값을 읽을 수 있게 해주는 JSON.parse(str)
메소드는
주로 서버에서 전달받은 데이터를 디코딩 할 때 사용합니다.
다만, 잘못된 형식이 들어온 경우, JSON.parse()
는 에러를 만들어 스크립트가 죽습니다.
let json = "{ bad json }";
try {
let user = JSON.parse(json); // <-- 에러 발생
alert( user.name );
} catch (e) {
// 에러가 발생하면 제어 흐름이 catch 문으로 넘어옵니다.
alert( e.name );
alert( e.message );
}
위와 같은 예시에서, json
이 문법적으로 잘못되진 않았지만, 필수 프로퍼티를 가지지 않았다면
let json = '{"age":24}';
try {
let user = JSON.parse(json); // <-- 에러X
alert( user.name ); // undefined
} catch (e) {
}
이처럼 에러가 발생하지 않지만, user.name
이 없는 건 에러를 유발하는 상황입니다.
throw 연산자는 에러를 생성합니다.
문법은 다음과 같습니다.
throw <error obeject>
원시형을 포함한 어떤 것도, 에러 객체가 될 수 있으나,
호환을 위해 name
, message
프로퍼티를 포함하는 것이 좋습니다.
일반 객체가 아닌 내장 생성자를 이용할 수 있습니다.
let error = new Error(meassage);
let error = new SyntaxError(meassage);
let error = new ReferenceError(meassage);
// ...
name
은 생성자명, message
는 인자에서 받습니다.
이제 앞 상황에서 throw
연산자를 통해 에러를 던집니다.
let json = {age:24} // name이 없음
try{
let user = JSON.parse(json);
if(!user.name) throw new SyntaxError('불완전한 데이터:이름 없음'); // 에러
alert( user.name );
} catch(e) {
alert( "JSON Error: " + e.message );
}
throw
와 만나고, try
가 중단된 후, 흐름이 catch
로 넘어갑니다.
JSON 에러를 포함한 모든 에러를 catch
블럭에서 처리하게 됩니다.
위에서 불완전한 JSON 데이터를 try...catch
로 처리했습니다.
그러나, try
블럭 내에선 예기치 않은 변수가 발생할 수 있습니다.
위 예시에서 불완전한 데이터를 다루려는 목적으로 try...catch
를 썼습니다.
그런데, catch
는 try
블럭에서 발생하는 모든 에러를 잡으려는 목적으로 만들어졌습니다.
위에서 catch
는 모든 에러를 잡았지만, 예기치 못한 상황에서도, JSON Error로 처리가 됩니다.
이러한 문제를 피하고자 다시 던지기 기술을 사용합니다.
catch
는 알고 있는 에러만 처리하고 다시 던져야 합니다.
catch
는 모든 에러를 잡습니다.catch
블럭 내에서 에러 객체를 분석합니다.throw err
합니다.보통 에러 타입을 instanceof
명령어로 체크합니다.
catch(err){
if(!(err instanceof SyntaxError)) {
throw err // 다시던지기
}
// SyntaxError Handling
}
try{
readData()
}catch(err){
alert('external Error :' + err); // 에러를 잡음
}
다시 던져진 에러는 밖으로 던져집니다.
여기서 바깥에 try...catch
가 있다면 거기서 잡고, 없다면 스크립트가 죽을 것 입니다.
이렇게 하면 catch
블록에선 다룰 수 있는 에러만 처리하고 나머지는 건너뛸 수 있습니다.
try...catch
는 finally
라는 코드 절을 하나 더 가질 수 있습니다.
에러와 관계없이 항상 실행 되며,
에러가 없을 때는, try
실행 후,
에러가 있을 때는, catch
실행 후에 실행됩니다.
try..catch...finally
안의 변수는 지역변수 입니다.