프로그래밍 언어의 오류에는 크게 2가지가 있습니다.
2가지 모두'오류'라고 부릅니다. 프로그램 실행 전에 발생하는 오류를 구문 오류
라고 부르며,
프로그램 실행 중에 발생하는 오류를 예외
또는 런타임 오류
라고 구분하여 부릅니다.
구문 오류
구문 오류는 괄호의 짝을 맞추지 않았다든지, 문자열을 열었는데 닫지 않았다든지 할 때 발생하는
오류입니다. 이러한 구문 오류가 있으면 웹 브라우저가 코드를 분석조차 하지 못하므로 실행 되지 않습니다.
console.log("괄호를 닫지 않는 실수를 했습니다"
구문 오류 : Uncaught SyntaxError: missing) after argument list
예외
예외 또는 런타임 오류는 실행 중에 발생하는 오류를 의미합니다.
console.rog("log를 rog로 잘못 입력했습니다")
예외 오류 : Uncaught TypeError: console.rog is not a function
이처럼 실행 중에 발생하는 오류가 예외입니다. 자바스트립에서는 SyntaxError
라고 출력되는
오류 이외의 모든 오류(TypeError
,ReferenceError
,RangeError
)가 예외로 분류됩니다.
조건문을 사용해서 예외가 발생하지 않게 만드는 것을 기본 예외 처리
라고 부릅니다.
다음 코드는 querySelector()
메소드로 문서 객체를 추출한 뒤 textContent
속성에 글자를
할당하는 코드입니다. 그런데 body 태그 내부에 h1 태그가 없습니다. 따라서 예외가 발생합니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const h1 = document.querySelector('h1')
h1.textContent = '안녕하세요'
})
</script>
</html>
문서 객체를 선택했는데 문서 객체가 없는 경우라면, 다음과 같이 조건문으로 h1이 존재하는
경우에만 teextContent
속성을 변경하도록 예외 처리를 할 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const h1 = document.querySelector('h1')
if (h1) {
h1.textContent = '안녕하세요'
} else {
console.log('h1 태그를 추출할 수 없습니다.')
}
})
</script>
</html>
이전 절에서 알아보았던 예외를 조금 더 쉽게 잡을 수 있는 기능으로 try catch finally
구문이
있습니다. 이와 같은 try catch finally
구문을 사용해서 예외를 처리하는 방법을
고급 예외 처리 라고 부릅니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
try {
willExcept.byeBye()
console.log("try 구문의 마지막 줄") // 위에서 예외가 발생하므로, 실행되지않고 catch 구문으로 이동
} catch (exception) {
console.log("catch 구문의 마지막 줄")
}
</script>
</head>
<body>
</body>
</html>
"finally 구문은 무조건 실행된다." 라는 것을 생각하면서 다음 코드의 실행 결과를 예측해보세요.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
try {
willExcept.byeBye()
console.log("try 구문의 마지막 줄")
} catch (exception) {
console.log("catch 구문의 마지막 줄")
} finally {
console.log("finally 구문의 마지막 줄")
}
</script>
</head>
<body>
</body>
</html>
try 구문에서 예외가 발생하고 catch구문이 실행됩니다. try 구문에서 예외가 발생하든 안 하든
무조건 finally 구문은 실행되므로 위와 같은 결과를 볼 수 있습니다.
finally 구문을 사용하는 이유
try catch finally
구문을 배우고나면 finally
구문을 왜 써야 하는지 궁금증을 가질수 있다.
catch
구문 내부에서 finally 구문을 넣어도 결과가 비슷하게 나올 수 있다고 생각하기 때문입니다.
두 코드의 실행 결과를 예측해 보세요. catch 구문 내부에서 return 키워드를 사용한 경우입니다.
<!DOCTYPE html> //예제 1번
<html>
<head>
<title></title>
<script>
function test() {
try {
alert('A 위치입니다.')
throw "예외 강제 발생" // throw 키워드로 예외를 강제로 발생시킵니다.
} catch (exception) {
alert('B 위치입니다.')
return
}
alert('C 위치입니다.')
}
// 함수를 호출합니다.
test()
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html> //예제 2번
<html>
<head>
<title></title>
<script>
function test() {
try {
alert('A 위치입니다.')
throw "예외 강제 발생"
} catch (exception) {
alert('B 위치입니다.')
return
} finally {
alert('C 위치입니다.')
}
}
// 함수를 호출합니다.
test()
</script>
</head>
<body>
</body>
</html>
코드를 실행하면 예제1은 "A 위치입니다."와 "B 위치입니다." 만 출력합니다.
return 키워드를 사용해 함수를 벗어났으므로 "C 위치입니다." 라는 글자를 출력하지 않는 것입니다.
하지만 예제2는 "A 위치입니다.", "B 위치입니다.", "C 위치입니다."를 모두 출력합니다.
이는 finally 구문을 반드시 실행한다는 특성 떄문입니다.
try catch 구문을 사용할 때 catch의 괄호 안에 입력하는 식별자가 예외 객체
입니다.
아무 식별자나 입력해도 괜찮지만, 일반적으로 e
나exception
이라는 식별자를 사용합니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
try {
const array = new Array(999999999999999)
} catch (exception) {
console.log(exception)
console.log()
console.log(`예외 이름: ${exception.name}`)
console.log(`예외 메시지: ${exception.message}`)
}
</script>
</head>
<body>
</body>
</html>
<anonymous>
2 : 파일이름
23 : 줄번호
상황에 따라서 예외를 강제로 발생시켜야 하는 경우도 있습니다. 예외를 강제로 발생시킬 때는
throw
키워드를 사용합니다.
throw 구문을 사용하면 곧바로 예외를 발생시킵니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
function divide(a, b) {
if (b === 0) {
throw '0으로는 나눌 수 없습니다.'
}
return a / b
}
console.log(divide(10, 2))
console.log(divide(10, 0))
</script>
</head>
<body>
</body>
</html>
예외를 강제로 발생시키는 이유는 무엇일까요? 일반적으로 개발할 때는 어떤 사람이 lodash
라이브러리
처럼 다양한 기능을 가진 유틸리 함수( 또는 클래스 )를 만들고, 다른 사람들이 그러한 라이브러리의 함수를
활용하는 경우가 많습니다.
내가 만든 함수를 내가 사용할 때는 아무 문제 없이 사용할 수 있겠지만, 내가 만든 함수를 다른 사람이 사용할 때는 내가 의도하지 않은 형태로 코드를 사용할 수도 있습니다. 이럴 때 예외를 강제로 발생시키면
사용자에게 주의를 줄 수 있으며, 의도한 대로 처리하게 유도할 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
function test(object) {
console.log(object.a + object.b)
}
test({})
</script>
</head>
<body>
</body>
</html>
일반적인 프로그래밍 언어라면,
그러면 사용자는 자신이 잘못 사용했다는 것을 인지하고 수정할 수있습니다.
하지만 자바스크립트는,
즉 아무 오류 없이 코드가 정상적으로 실행됩니다.
이처럼 자바스트립트는 undefined와 NaN이라는 값이 있어서 다른 프로그래밍 언어에 비해서 예외를
많이 발생하지는 않습니다. 그렇기 때문에 사용자에게 함수를 잘못 사용했다는 것을 강제로라도
인지시켜줄 필요가 있다는 것입니다.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
function test(object) {
if (object.a !== undefined && object.b !== undefined) {
console.log(object.a + object.b)
} else {
throw new Error("a 속성과 b 속성을 지정하지 않았습니다.")
}
}
test({})
</script>
</head>
<body>
</body>
</html>