예외 던지기
문제가 발생하면 null 반환 대신 예외를 던지겠습니다.
그러면 어떤 문제냐에 따라 대처가 가능할 수 있고, 디버깅에 도움 되는 메타 데이터도 얻을 수 있습니다.
function ask() {
return prompt("생일 언제임?");
}
function parse(birthday: string): Date {
let date = new Date(birthday);
if (!isValid(date)) {
throw new RangeError('YYYY/MM/DD 로 입력하셈여')
}
return date;
}
이제 이 코드를 사용할 때 전체 응용 프로그램이 크래시 되지 않도록 매끄럽게 처리하기 위해 주의해서 예외를 잡아야 합니다.
function ask() {
return prompt("생일 언제임?");
}
function parse(birthday: string): Date {
let date = new Date(birthday);
if (!isValid(date)) {
throw new RangeError("YYYY/MM/DD 로 입력하셈여");
}
return date;
}
// 입력한 날짜가 유효한지 검사
function isValid(date: Date) {
return (
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date.getTime())
);
}
try {
let date = parse(ask());
console.info("생일은", date.toISOString());
} catch (e) {
console.error(e.message);
}
다른 에러가 발생했을 때 무시하지 않도록, 처리하지 않은 에러는 다시 던지는 것이 좋습니다.
function ask() {
return prompt("생일 언제임?");
}
function parse(birthday: string): Date {
let date = new Date(birthday);
if (!isValid(date)) {
throw new RangeError("YYYY/MM/DD 로 입력하셈여");
}
return date;
}
// 입력한 날짜가 유효한지 검사
function isValid(date: Date) {
return (
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date.getTime())
);
}
try {
let date = parse(ask());
console.info("생일은", date.toISOString());
} catch (e) {
if (e instanceof RangeError) {
console.error(e.message);
} else {
throw e;
}
}
나중에 다른 개발자가 parse나 ask에서 또 다른 형태의 RangeError를 던질 수 있게 하려면 에러를 서브클래싱하여 더 구체적으로 표현하면 됩니다.
이런 방식으로 내가 만든 에러와 다른 개발자가 추가한 에러를 구분할 수 있습니다.
function ask() {
return prompt("생일 언제임?");
}
// 커스텀 에러 타입
class InvalidDateFormatError extends RangeError{}
class DateISInTheFutureError extends RangeError{}
function parse(birthday: string): Date {
let date = new Date(birthday);
if (!isValid(date)) {
throw new RangeError("YYYY/MM/DD 로 입력하셈여");
}
if(date.getTime() > Date.now()){
throw new DateISInTheFutureError('타임로드 했닝?')
}
return date;
}
// 입력한 날짜가 유효한지 검사
function isValid(date: Date) {
return (
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date.getTime())
);
}
try {
let date = parse(ask());
console.info("생일은", date.toISOString());
} catch (e) {
if (e instanceof DateISInTheFutureError) {
console.error(e.message);
} else if(e instanceof DateISInTheFutureError){
console.error(e.message)
} else {
throw e;
}
}
이제 커스텀 에러를 이용하면 어떤 문제가 생겼는지 알려줄 수 있을 뿐 아니라 문제가 생긴 이유도 설명할 수 있습니다.
문제를 디버깅할 때 서버 로그를 함께 확인하거나, 사용자가 어떤 실수를 했으며 어떻게 문제를 해결할 수 있는지 알려주는 커스텀 에러 다이얼로그 등을 구현할 때 이런 구체적인 에러가 도움이 됩니다.
여러 동작을 try/catch 구문으로 감싸는 형태로, 연쇄적이고 중첩된 동작을 효율적으로 만들 수 있습니다.
이 코드는 어떻게 사용할 수 있을까요?
큰 try/catch 구문 안의 코드가 하나의 파일에 담겨 있고, 나머지 코드는 다른 라이브러리에서 이포트된 코드라고 가정합니다.
그렇다면 개발자는 특정 타입의 에러 또는 기존의 RangeError가 던져질 수 있다는 사실을 어떻게 알고 잡아서 처리할 수 있을까요?
그러려면 함수 이름에 명시하거나 문서화 주석(docblock)에 정보를 추가해야 합니다.
function ask() {
return prompt("생일 언제임?");
}
// 커스텀 에러 타입
class InvalidDateFormatError extends RangeError{}
class DateISInTheFutureError extends RangeError{}
/**
*
* @throw {InvalidDateFormatError} : 사용자가 생일을 잘못 입력함
* @throw {DateISInTheFutureError} : 사용자가 생일을 미래 날짜로 입력함
*/
function parse(birthday: string): Date {
let date = new Date(birthday);
if (!isValid(date)) {
throw new RangeError("YYYY/MM/DD 로 입력하셈여");
}
if(date.getTime() > Date.now()){
throw new DateISInTheFutureError('타임로드 했닝?')
}
return date;
}
// 입력한 날짜가 유효한지 검사
function isValid(date: Date) {
return (
Object.prototype.toString.call(date) === "[object Date]" &&
!Number.isNaN(date.getTime())
);
}
try {
let date = parse(ask());
console.info("생일은", date.toISOString());
} catch (e) {
if (e instanceof DateISInTheFutureError) {
console.error(e.message);
} else if(e instanceof DateISInTheFutureError){
console.error(e.message)
} else {
throw e;
}
}
'👶 TypeScript' 카테고리의 다른 글
에러 처리 - Option 타입 (0) | 2023.01.23 |
---|---|
에러 처리 - 예외 반환 (0) | 2023.01.23 |
에러 처리 - null 반환 (0) | 2023.01.22 |
프로토타입 안전하게 확장하기 (0) | 2023.01.22 |
이름 기반 타입 흉내내기 (0) | 2023.01.22 |