try.. catch는 finally 라는 코드 절을 하나 더 가질 수 있습니다.

*finally안의 코드는 다음과 같은 상황에서 실행됩니다.*

*finally 를 사용하면 try..catch 를 다음과 같이 확장할 수 있습니다.*

try {
	// 코드 실행..
} catch (err) {
	// 에러 핸들링..
} finally {
	// 항상 실행..
}

*finally 절은 무언가를 실행하고, 실행 결과에 상관없이 실행을 완료하고 싶은 경우 사용됩니다.*

피보나치 함수 fib(n) 의 연산 시간을 측정하고 싶다고 가정해 봅시다. 함수 실행 전에 측정을 시작해서 실행이 끝난 후 측정을 종료하면 되겠죠. 그런데 함수 실행 도중 에러가 발생하면 어떻게 될까요? 아래 fib(n)에는 음수나 정수가 아닌 수를 입력할 경우 에러가 발생합니다.

이런 경우에 finally를 사용할 수 있습니다. finally 절은 무슨 일이 일어났든 관계없이 연산시간 측정을 끝마치기 적절한 곳입니다. fib 함수가 에러 없이 정상적으로 실행되든 에러가 발생하든 상관없이, finally 를 사용하면 연산 시간을 제대로 측정할 수 있습니다.

let num = +prompt("양의 정수를 입력해주세요.", 35);

let diff, result;

function fib(n) {
	if(n < 0 || Math.trunc(n) != n) {
		throw new Error("음수나 정수가 아닌 값은 처리할 수 없습니다.");
	}
	return n <= 1 ? n : fib(n - 1) + fib(n - 2);
}

let start = Data.now();

try {
	result = fib(num);
} catch (err) {
	result = -1;
} finally {
	diff = Data.now() - start;
}

alert(result || "에러 발생");
alert( `연산 시간: ${diff}ms` );

코드를 실행하고 프롬프트 대화상자에 35를 입력하면 try 다음에 finally 가 정상적으로 실행되면서 연산 시간을 확인할 수 있습니다. -1을 입력하면 에러가 발생하고, 연산 시간은 0ms가 됩니다.

*함수return 이나 throw 를 만나면 종료되는데, 이렇게 finally 절을 사용하면 두 경우 모두를 처리할 수 있습니다.*

<aside> 💡 [ finally와 return ] finally 절은 try catch 절을 빠져나가는 어떤 경우에도 실행됩니다. return을 사용해 명시적으로 빠져나가려는 경우도 마찬가지 입니다. 아래 예시의 try 블록 안엔 return 이 있습니다. 이 경우엔 값이 바깥 코드로 반환되기 전에 finally가 실행됩니다.

function func() {
	try {
		return 1;
	} catch (err) {

	} finally {
		alert('finally');
	}
}
alert( func() ); // finally 안의 alert가 실행되고 난 후, 실행됨

</aside>

<aside> 💡 [ try..finally ] catch 절이 없는 try..finally 구문도 상황에 따라 유용하게 쓸 수 있습니다. try..finally 안에선 에러를 처리하고 싶지 않지만, 시작한 프로세스가 마무리 되었는지 확실히 하고 싶은 경우에 사용합니다.

function func() {
	try { // 무언가를 측정하는 경우와 같이 끝맺음이 있어야 하는 프로세스
		// ..
	} finally {
		// 스크립트가 죽더라도 완료됨
	}
}

위 코드엔 catch 가 없기 때문에 try 안에서 발생한 에러는 항상 밖으로 떨어져 나옵니다. finally는 실행 흐름이 함수를 떠나기 전에 실행됩니다.

</aside>