728x90
반응형
상황 이해하기
먼저 두 개의 코드를 비교하며 문제를 살펴보겠습니다.
1. 문제 코드

- 무슨 일이 일어나는지?
- countdown 변수에 함수가 할당됩니다. 이 함수는 재귀적으로 countdown(n - 1)을 호출해 카운트다운을 수행합니다.
- myFunction에 countdown을 복사합니다. 이때 myFunction은 countdown이 가리키는 함수를 참조하게 됩니다.
- countdown = null로 설정하면, countdown 변수가 더 이상 함수를 가리키지 않고 null을 가리키게 됩니다.
- myFunction(5)를 호출하면 함수가 실행되면서 countdown(n - 1)을 호출하려고 하지만, countdown은 이미 null이 되었기 때문에 "countdown is not a function"이라는 TypeError가 발생합니다.
- 왜 에러가 발생할까?
- countdown은 함수를 참조하던 변수였지만, null로 재할당되었기 때문에 함수가 아닙니다.
- 재귀 호출에서 countdown(n - 1)은 함수 내부에서 countdown 변수를 사용합니다. 그런데 이 변수가 null로 바뀌었기 때문에 호출이 실패합니다.
- 여기서 문제는 함수가 자신을 호출할 때 외부 변수(countdown)에 의존하고 있다는 점이에요.
2. 정상 코드

- 무슨 일이 일어나는지?
- countdown에 할당된 함수는 이름이 printCountdown인 **기명 함수 표현식(Named Function Expression)**입니다.
- myFunction에 countdown을 복사합니다. 여전히 동일한 함수를 참조합니다.
- countdown = null로 설정해도, 함수 내부에서 printCountdown(n - 1)는 함수 자신의 이름을 사용해 재귀 호출을 합니다.
- myFunction(5)를 호출하면 printCountdown가 정상적으로 작동하며 5부터 0까지 출력하고 'End!'로 끝납니다.
- 왜 정상 작동할까?
- 함수 내부에서 printCountdown라는 고유한 이름으로 자신을 호출하기 때문에, 외부 변수(countdown)가 null로 바뀌어도 영향을 받지 않습니다.
- printCountdown는 함수 정의 시 내부적으로 고정된 이름으로, 외부 변수의 변경과 무관하게 작동합니다.
핵심 차이점: 변수 vs 함수 이름
- 문제 코드에서는:
- 재귀 호출에 countdown이라는 변수 이름을 사용했습니다.
- countdown 변수가 null로 바뀌면, 함수가 더 이상 자신을 호출할 수 없게 됩니다.
- 즉, 함수가 외부 변수에 의존하고 있어서 변수가 바뀌면 문제가 생깁니다.
- 정상 코드에서는:
- 재귀 호출에 printCountdown이라는 함수 이름을 사용했습니다.
- 이 이름은 함수 내부에서만 유효한 고유한 식별자로, 외부 변수(countdown)가 바뀌어도 영향을 받지 않습니다.
- 함수가 자신의 이름을 통해 스스로를 호출하기 때문에 안정적입니다.
왜 기명 함수 표현식이 안전한가?
- **기명 함수 표현식(Named Function Expression)**은 함수 내부에서 자신의 이름을 사용할 수 있게 해줍니다.
- 반면, 익명 함수 표현식에서는countdown은 외부 변수에 의존하므로, 변수가 변경되면 재귀 호출이 실패합니다.
실질적인 해결책
이 문제를 방지하려면 재귀 함수를 작성할 때 기명 함수 표현식을 사용하는 것이 좋습니다. 이유는:
- 함수가 외부 변수의 변경에 영향을 받지 않도록 보호됩니다.
- 디버깅 시 스택 트레이스에 함수 이름이 표시되어 추적이 쉬워집니다.
쉽게 이해하기
- 비유: 함수를 "요리사"로 생각해보세요.
- 익명 함수 표현식(let countdown = function(n) {...})은 요리사가 자신의 이름을 모르고, "주인(외부 변수)"에게 물어봐야 할 때를 뜻합니다. 주인이 바뀌면(예: countdown = null) 요리사는 일을 못해요.
- 기명 함수 표현식(let countdown = function printCountdown(n) {...})은 요리사가 자신의 이름을 알고 있어서 주인이 바뀌어도 혼자서 잘 해낸다는 뜻이에요.
- 결론: 재귀 함수를 만들 때는 함수 내부에서 자신을 호출할 수 있도록 이름을 주는 게 안전합니다.
요약
- 익명 함수 표현식에서는 재귀 호출이 외부 변수(countdown)에 의존하기 때문에, 변수가 null로 바뀌면 에러가 발생합니다.
- 기명 함수 표현식에서는 함수 내부에서 자신의 이름(printCountdown)을 사용하므로, 외부 변수가 바뀌어도 정상 작동합니다.
- 그래서 함수 표현식을 사용할 때, 특히 재귀가 필요할 때는 기명 함수 표현식을 추천합니다.
728x90
반응형