IT/JavaScript

즉시 실행 함수(IIFE)

무녈 2022. 4. 24. 01:20

즉시 실행 함수

자바스크립트에는 특이한 함수 형태들이 존재하는 데, 그중 하나가 즉시 실행 함수라는 것이다.

자바스크립트의 다양한 함수 형태 중 즉시 실행 함수라는 것이 존재한다. 

즉시 실행 함수(IIFE, Immediately Invoked Function Expression)는 의미 그대로 정의와 함께 즉시 실행되는 자바스크립트 함수를 의미한다.

📌 즉시 실행 함수의 특징

즉시 실행 함수는 단 한 번만 호출되어 다시 호출할 수 없다.

// 익명 즉시 실행 함수 
(function () {
	statements
}());

즉시 실행 함수는 보통 함수 이름이 없는 익명 함수를 사용하는 것이 일반적이다. 함수 이름이 있는 기명 즉시 실행 함수 또한 존재하지만, 그룹 연산자 (...) 내의 기명 함수는 함수 선언문이 아니라 함수 리터럴로 평가되어 함수 이름은 함수 몸체에만 참조할 수 있는 식별자이므로 즉시 실행 함수를 다시 호출할 수 없다.

그렇기 때문에 보통 Self-Executing Anonymous Function으로 알려진 디자인 패턴을 사용하며, 크게 두 부분으로 구성된다. 

첫 번째는 괄호(())로 둘러싸인 익명 함수(Anonymous Function)이다. 두 번째 부분은 즉시 실행 함수를 생성하는 괄호 ()이다. 

이것을 통해 자바스크립트 엔진은 함수를 즉시 해석해서 실행할 수 있게 된다.

 

보통 즉시 실행 함수는 아래와 같은 형태로 사용된다.

// 익명 즉시 실행 함수 

(function () {
	let a = 3; 
    let b = 5; 
    return a * b;
}());

위에서 언급한 즉시 기명 함수를 생성한 뒤, 따로 함수를 호출하면 어떤 결과가 발생할까?

(function foo() {
	let a = 3; 
    let b = 5; 
    return a * b;
}());

즉시 기명 함수의 ReferenceError

즉시 실행 함수는 함수 리터럴에 해당하기 때문에 즉시 기명 함수를 따로 호출할 경우 ReferenceError가 발생하게 된다. 

📌즉시 실행 함수의 잘못된 사용

1. 즉시 실항 함수를 그룹 연산자(...)로 감싸지 않은 경우

즉시 실행 함수는 반드시 그룹 연산자 (...)로 감싸야한다. 그렇지 않으면 다음과 같은 에러가 발생한다.

function() {
	let a = 3; 
    let b = 5; 
    return a * b;
}();

SyntaxError

왜 이런 에러가 발생할까?

이는 함수 정의가 함수 선언문의 형식에 맞지 않기 때문이다. 함수 선언문은 함수 이름을 생략할 수 없기 때문이다.

2. 기명 함수를 정의하고, 그룹 연산자 없이 즉시 호출하는 경우

function foo() {
	let a = 3; 
    let b = 5; 
    return a * b;
}();

SyntaxError

2번의 경우에는 왜 이런 에러가 발생할까?

그 이유는 자바스크립트 엔진이 암묵적으로 수행하는 세미콜론 자동 삽입 기능에 의해 함수 선언문이 끝나는 위치, 즉 함수 코드 블록의 닫는 중괄호 뒤에 ";"이 암묵적으로 추가되기 때문이다.

 

아래와 같은 구조의 함수를 실행시킬 경우

function() {}();

 

아래와 같은 모습으로 실행이 되는 것이다.

function foo() {};();

그렇기 때문에 함수 선언문 뒤의 (...)는 함수 호출 연산자가 아니라 그룹 연산자로 해석이 되고, 그룹 연산자에 피연산자가 없기 때문에 에러가 발생한다.

 

그룹 연산자로 함수를 묶은 이유는 먼저 함수 리터럴을 함수 객체를 생성하기 위해서이다. 먼저 함수 리터럴을 평가해서 함수 객체를 생성할 수 있다면, 여러 가지 방법의 그룹 연산자 방식 중 선택하여 사용할 수 있다. 이중 첫 번째 방식을 가장 보편적인 방법이라고 한다.

(function () { // ...
}());

(function () { // ...
})();

!function () { // ...
}();

+function () { // ...
}();

즉시 실행 함수 실제 사용 예

const app = document.querySelector("#app");
const viewModel = {};
(function () {
function init() {
  Object.defineProperty(viewModel, "str", {
    get: function () {
      console.log("접근");
    },
    set: function (newValue) {
      console.log("할당", newValue);
      render(newValue);
    },
  });
}
function render(value) {
  app.innerHTML = value;
}
init();
})();

익명 실행 함수를 통해 init() 함수를 호출한다.

위에서 정의한 viewModel은 빈 객체를 할당하였다. 이는 init() 함수가 실행됨에 따라, viewModel 객체에 'str'이라는 프로퍼티의 정의를 내리게 된다. str 프로퍼티에 get과 set을 프로퍼티로 갖는 객체를 할당하여 즉시 실행 함수를 수행하였다. 뿐만 아니라 즉시 실행 함수가 실행된 후 set을 통해 새롭게 값을 할당해서 렌더링을 시킬 수 있다. 즉시 실행 함수를 실행하여 viewModel 객체에 할당된 프로퍼티 속성을 사용할 수 있게 된다.

 

📌 즉시 실행 함수는 도대체 왜 사용이 되는 걸까?

즉시 실행 함수는 전역 스코프에 불필요한 변수를 추가해서 오염시키는 것을 방지할 수 있을 뿐만 아니라 IIFE 내부 안으로 다른 변수들이 접근하는 것을 막을 수 있기 때문에 사용된다.

뿐만 아니라 즉시 실행 함수 내에 코드를 모아 두면 혹시 있을 수 있는 변수나 함수 이름의 충돌을 방지할 수 있다.

이러한 장점들로 인해 즉시 실행 함수를 사용한다. 

반응형