Porffor에 이제 클로저가 생겼습니다

ko생성일: 2026. 5. 11.갱신일: 2026. 5. 11.

몇 달에 걸친 간헐적인 작업 끝에 Porffor에 마침내 클로저가 구현되었습니다. 컴파일러 관점에서의 클로저 캡처, 성능과 메모리의 절충점, 그리고 왜 가능한 한 적게 캡처해야 하는지에 대해 설명합니다.

몇 달에 걸친 간헐적인 작업 끝에, Porffor에 마침내 클로저가 구현되었습니다. 혹시 모르신다면, 클로저는 렉시컬 경계를 넘어 변수를 바인딩하는 고급 방식입니다. 이것은 다음과 같은 코드를 작성할 수 있다는 뜻입니다:

function foo() {
  let cool = 1337;
  return () => cool++;
}

const bar = foo();
bar(); // 1337
bar(); // 1338

...그리고 ReferenceError: cool is not defined가 발생하지 않습니다. 컴파일러 관점에서 보면 bar 내부에는 cool이 정의되어 있지 않기 때문입니다. 컴파일 타임의 시맨틱 분석 이후, 우리는 bar가 클로저 캡처로부터 cool을 필요로 한다는 것을 알아냅니다. bar를 인스턴스화할 때, 우리는 그 환경인 { cool }을 캡처합니다. 그리고 매번 호출할 때마다 그 환경을 전달합니다. 적어도 제게는, 이것이 비교적 간단하게 구현할 수 있을 것처럼 들렸습니다. 적어도 성능을 유지하면서 하려면, 이것은 간단하지 않습니다.

여기에는 본질적인 절충점이 있습니다. 망가뜨리지 않으면서 가능한 한 클로저 캡처를 적게 하고 싶다는 점입니다. 어느 정도 작업과 테스트를 거친 뒤에는 이것을 맞추는 것이 다소 쉬워지지만, 매 반복마다 인스턴스화되어야 하는 루프나 자기 참조 같은 재미있는 시나리오는 쉽게 문제를 일으킬 수 있습니다. 여기서 자세히 들어가지는 않겠습니다. 대부분은 시맨틱 분석이 모든 것을 캡처하게 한 다음, 회귀 없이 필요한 것만 캡처하도록 정제하는 작업이기 때문입니다.

변수를 캡처하는 것은 CPU 사이클을 낭비할 뿐만 아니라 메모리도 낭비합니다. 앞으로 코드가 느리고 더 빨라질 가능성이 높을 때 경고해 주는 컴파일러 경고/린팅을 추가할 계획이 있는데, 클로저는 아마 그 큰 부분이 될 것입니다. 왜 지금 클로저가 들어가고 있는지 궁금하시다면, 계속 지켜봐 주세요 ;)