1. 예외처리란?
코드 실행 중에 예기치 못한 에러가 발생했을 때, 이로부터 코드의 실행 흐름을 복구할 수 있는데, 이를 예외처리(Excpetion handling) 라고 한다.
JavaScript는 기본적으로 싱글 스레드라서 스레드가 멈춘다는 것은 프로세스가 멈추는 것이라서, 예외처리는 필수이다.
2. JavaScript의 예외처리 방법
& try catch finally
try ... catch .. finally 구문을 사용하여 에러가 나더라도 코드의 실행을 지속할 수 있다.
try {
console.log('에러가 나기 직전까지의 코드는 잘 실행됩니다.');
new Array(-1); // RangeError: Invalid array length
console.log('에러가 난 이후의 코드는 실행되지 않습니다.');
} catch (e) {
console.log('코드의 실행 흐름이 catch 블록으로 옮겨집니다.');
alert(`다음과 같은 에러가 발생했습니다: ${e.name}: ${e.message}`);
}
→ 에러가 났을 때 원상 복구를 시도할 때, try블록 내부에 작성하면, 에러가 발생했을 때 코드의 실행 흐름이 try 블록에서 catch 블록으로 옮겨간다. 이 때, catch 블록 안에서는 에러에 대한 정보를 담고 있는 객체 e를 사용할 수 있다.
for (let i of [1, 2, 3]) {
try {
if (i === 3) {
break;
}
} finally {
console.log(`현재 i의 값: ${i}`);
}
}
→ finally 블록이 사용되면, try 블록 안에서의 에러 발생 여부와 관계없이 무조건 실행된다.
→ finally 블록은 catch 블록과도 사용된다.
→ 에러가 안 났을 때 : try-finally
→ 에러가 났을 때 : try - 에러 발생 - catch -finally
const even = parseInt(prompt('짝수를 입력하세요'));
if (even % 2 !== 0) {
throw new Error('짝수가 아닙니다.');
}
→ 에러의 종류를 구분해야하거나 에러 객체에 기능을 추가해야할 필요가 있을 때 사용한다.
(1) Promise 의 경우
Promise.resolve()
.then(() => {
throw new Error('catch 메소드를 통해 예외 처리를 할 수 있습니다.');
})
.then(() => {
console.log('이 코드는 실행되지 않습니다.');
})
.catch(e => {
return e.message;
})
.then(console.log);
→ 기존 try catch 블럭에 넣을 경우에는 try 블록을 비동기 함수가 만날 수 없다.
→ 그래서,비동기 위와 같이 비동기 콜백의 내부에 try 블록을 작성해줘야 한다.
→ then 메소드의 연쇄 안에서 에러가 발생하면, try...catch 구문과 유사하게 처음 만나는 에러 처리 콜백으로 코드의 실행 흐름이 건너뛰는 결과를 넣게 된다.
(2) async await 사용의 경우
async function func(){
try{
const res = await fetch("https://~~");
}
catch(e){
console.log(e.message);
}
}
func(); //Failed to fetch
→ async await 형태를 사용하면, 위의 체인 형태의 복잡한 구조를 좀 더 단순하게 만들어줄 수 있다.
3. 내 코드에서의 적용
프르젝트를 진행하면서 , 백엔드에서 MYSQL 연동관련 api 호출을 할 때, 요청 파라메타가 전달이 되지 않는 오류를 가장 많이 받았었습니다.
그래서 이 부분에 대해서 에러처리를 해 볼 예정입니다.
mysql connection 객체로 쿼리 실행 시에 , 에러 발생하면 error를 throw하는 형태이며,
SQLdata에 값이 제대로 들어오지 않았을 때 , error가 발생하고 서버가 중단됩니다.
getClubDetailInfo: async (req, res) => {
const selectSQL = `SELECT * FROM CLUB_TABLE WHERE C_IDX =?`;
const SQLdata = [req.query.data];
connection.query(seletSQL, SQLData, (error, result) => {
if (error) throw error;
res.status(200).send(result);
});
}
아래처럼 수정을 한 후로,SQLdata 문제가 생기더라도 , 서버는 끊기지 않으며, 상태 코드로 현재문제만 전달받을 수 있게 되었습니다.
이 외의 api 코드도 대부분 수정전 코드와 같이 구성되어있어서, 아래와 같이 수정을 하였습니다.
getClubDetailInfo: async (req, res) => {
const selectSQL = `SELECT * FROM CLUB_TABLE WHERE C_IDX =?`;
const SQLdata = [req.query.data];
try {
// 기존 SQLdata 문제를 null,undefined 체크를 미리 해주어,
// 문제 발생 시에 TypeError를 던져주고 아래 실행문은 실행되지 않고, catch문으로 넘어가고 상태 코드 405 를 클라이언트로 전달해준다.
if (req.query.data === null || req.query.data === undefined)
throw TypeError("SQLdata Null Error");
connection.query(selectSQL, SQLdata, (error, result) => {
if (error) throw error;
res.status(200).send(result);
});
} catch (error) {
if (error instanceof TypeError) {
res.status(405).send("SQL Error");
} else {
res.status(406).send("Error :" + error);
}
}
}
4. 느낀점
사이트를 만들면서, try catch 구문이 예외처리문이라는 정도는 알고 있었지만, 제대로 된 처리를 안해 둔 상태였습니다.
이번에 적용을 하면서 가장 많이받았던 오류를 떠올려 처리를 해주었는데, 아직 제가 생각하지 못한 예외처리부분들이 많을 것 같습니다.
좀 더 처리해야될 부분이 생기면 바로바로 업데이트해나가야겠다는 생각이 들었습니다.
https://helloworldjavascript.net/pages/290-exception.html
https://www.youtube.com/watch?v=EBmIHrLTVdg&ab_channel=코드종
많은 것을 배웠습니다, 감사합니다.