JS | Try Catch 문법과 에러 핸들링

송은석·2022년 9월 8일
0

오늘은 Try..Catch 문법과 이를 통한 에러 핸들링에 대해 다루어보고자 합니다.

프로그램 실행 중 에러가 발생하면, 에러 콘솔과 함께 스크립트가 중단됩니다.

스크립트의 갑작스런 종료를 막기 위해 try..catch 문법이 사용될 수 있습니다. try 구문 실행 중 에러가 발생할 경우 catch에서 제어 흐름을 가져가 스크립트가 중단되지 않게 하는 방식이지요.

try {
	// 1 - 실행 중 에러 발생
} catch(err) {
	alert(err); // 2 - 실행 흐름을 가져옴.
}

에러 객체

에러 발생 시 자바스크립트는 에러 상세 내용이 담긴 객체를 생성하여 이를 catch 블록에 인수로 전달합니다. 생성된 에러 객체는 속성으로 name, message, stack을 가지게 됩니다.

보통, name을 통해서 에러의 종류를 판별하고, message를 통해 내용을 전달하게 됩니다.(로그로 남기거나, response로 전달하거나..)

만약 에러를 디버깅할 경우, stack에 나타난 에러를 유발한 호출들의 순서를 참고할 수 있습니다.

에러 다시 던지기(rethrowing)

catch를 통해 발생하는 모든 에러를 잡아낼 수 있으나, 그 이후의 처리는 사용자의 몫입니다. 프로그램을 작성할 때 발생하는 에러들을 정확히 다루고, 체계적으로 만들고 싶다면 에러들을 분류하여 처리하는 것이 좋습니다. 정확히 말하자면 알고 있는 에러는 처리하고, 알지 못하는 에러라면 다시 던져야 하는 것입니다.

try {
	ImNotReferenceVariable;
} catch (err) {
	if (err instanceof ReferenceError) { // err.name을 통해 구분할 수도 있습니다.
		alert("Reference Error")
	} else {
		throw err;
	}
}

이렇게 에러 처리를 할 경우, 현재 try..catch 상에서 알고 있는 에러를 처리하고, 모르는 에러는 현재 구문 상위의 구문에서 처리하게 됩니다. 각 구문 마다의 에러 책임 처리가 확실해집니다.

다시 던지기 예제

아래는 제가 토이 프로젝트 중 사용한 코드의 일부분 입니다. 유저의 정보를 받아 회원가입을 처리하는 코드인데요, catch 구문을 통해 이미 존재하는 유니크 키를 가진 데이터가 insert될 경우 해당하는 에러의 코드를 판별하여 다시 에러 객체를 던져주고 있습니다.

그리고 그렇지 않은 경우에는 에러 객체를 다시 상위의 스코프로 던져주게 됩니다.

try {
    const hashedPassword = await hashPassword(user.password);

    const newUser = await prisma.user.create({
        data: {
            ...userDetails,
            password: hashedPassword,
        },
    });

    return true;
} catch (err) {
    const errorCaught = err as any;

    if (errorCaught.code === "P2002") { 
        return new Error("Unique constraint failed");
    } else {
        return new Error(errorCaught);
    }
}

finally 구문

try 구문이 완료되거나 catch 구문으로 흐름이 넘어가거나 상관없이 마지막에 실행시키고 싶은 구문이 있다면 finally를 작성하면 됩니다.

try에 return이 있다면 값이 바깐 코드로 반환되기 직전, catch에서 throw로 코드가 마무리된다면 throw 직전에 finally의 코드가 실행됩니다.

try {
	// 1 실행 코드
  return "return"; // 3 finally 코드 후 마지막으로 반환
} catch (err) {
	//...
} finally {
	// 2 실행 코드
}

전역 catch

만약 try..catch가 아닌 전역 코드 상에서 에러가 발생한다면 어떻게 해야할까요?

nodejs에서는 일반적으로 procces.on(’uncaughtException’) 방식을 통해 전역 에러를 처리하게 됩니다.

process.on('uncaughtException', (err, origin) => {
 console.log(
		`Caught exception: ${err}\n` +
    `Exception origin: ${origin}`
  );
});

throw error

err는 에러 객체로, 위에서 설명한 에러 객체의 속성을 가집니다.

origin은 예외의 발생 원인으로, 예외가 unhandled rejection 혹은 동기적 에러인지에 관한 것인지를 알려줍니다. unhandledRejection 혹은 uncaughtException 중 하나의 값을 가지게 됩니다.

브라우저 상에서는 window.onerror 방식을 사용합니다.

window.onerror = function(message, url, line, col, error) {
    alert(`${message}\n At ${line}:${col} of ${url}`);
 };

결론

자바스크립트는 프로그램 실행 중 발생하는 에러를 처리하기 위해 try..catch 문법을 사용합니다.

좋은 프로그램을 만들고 싶다면 단순히 catch로 에러를 잡아내는 것을 넘어 적절한 로그나 메시지를 통해 에러를 처리하도록 해야 합니다. 그에 대한 좋은 패턴으로 에러 다시 던지기가 있으며, 이를 통해 try..catch의 구문 단위로 에러를 처리할 수 있습니다. 또한 전역 단위에서도 에러를 다룰 수 있습니다.



출처

profile
Done is better than perfect🔥

0개의 댓글