본문 바로가기
My Record/이론 및 공부

[펌][Javascript] function(){}() - IIFE란?

by 썸머워즈 2020. 10. 4.
반응형

출처 : https://findawayer.tistory.com/entry/IIE%EC%9D%98-%EC%9D%98%EB%AF%B8%EB%8A%94


자바스크립트에서 이런 구문을 보신 적이 있으신가요?

(function() {
    // 코드
})();

제가 처음 이런 구문을 봤을 적엔 의아스러웠습니다. 괄호가 여기저기 겹쳐 붙어 있는 걸로 보일 뿐, 대체 무슨 구문인가 하고요. jQuery에서 사용하는 $(function() { });의 또다른 버전인가 하는 생각조차 들었습니다. (그렇지 않습니다)


이것은 퓨어 자바스크립트에서 거의 언제나 사용하는, IIFE(Immediately-invoked function expression: 즉시 작동하는 함수식)라는 구문입니다. "이 안에 들어있는 코드를 바로 실행해라" 라는 표현으로 이해하시면 되겠습니다.

IIFE의 구조

예를 들어, write라는 이름의 함수가 있다고 하죠.

function write() {
  document.write("Test");
}

write();

위 예시처럼 write()라고 호출해 주지 않으면 write 함수는 실행되지 않습니다. 그런데 만약 write() 없이도 write 함수를 실행시키고 싶다면, 어떻게 해야 할까요?


(function write() {
  document.write("Test");
})

우선 write 함수를 괄호로 감싸줍니다. 이렇게 하면, 해석기는 이 함수(function)를 함수식(function expression)으로 취급합니다.
(함수식으로 만들지 않은 채 function() { }(); 처럼 호출할 수는 없습니다. 함수식으로의 전환은 일종의 우회 공정이죠.)


(function write() {
  document.write("Test");
})();

그리고 write();처럼 뒤에 ();를 붙여 함수식을 호출해 줍니다. 이렇게 짜여진 함수는 즉시 실행되는 함수식, 즉 IIFE가 되며, 우리는 document.write();가 올바르게 실행되었음을 확인할 수 있게 됩니다.

언제, 왜 IIFE를 사용하죠?

자바스크립트의 클로저 때문에 IIFE안에 사용된 변수, 함수들은 모두 블럭 바깥에 영향을 줄 수 없습니다. 위에서 예를 들었던 write 함수를 통해 테스트해 보죠.
(function write() {
  var txt = "Test";
  document.write(txt);
})();

write(); // ReferenceError: write is not defined.
console.log(txt); // ReferenceError: txt is not defined.
이런 특수성을 이용한 몇 가지 처리가 가능합니다.

코드 사이의 충돌을 예방

코드를 IIFE 블럭으로 감싸서 다른 코드와 변수나 함수명 등이 충돌하지 않도록 예방이 가능합니다. 아래에 예를 들어 보겠습니다.
(function() {
  var popup;
  var open = function(e) {
  });

  //.....

  open(popup);
})();

(function() {
  var modal;
  var open = function(e) {
  });

  //......

  open(modal);
})();
흔히 겹칠 수 있는 open이라는 이름이 두 개 코드 블럭 사이에 영향을 줄 수 없게 됩니다.
를 갖고 의도적으로 전역 변수나 함수를 만드는 것이 아닌 이상, 변수나 함수를 특정한 범위에 제한해 충돌을 방지하는 것이 바람직합니다.

가끔, 내 jQuery 코드는 완벽한데 실행이 되지 않을 때가 있을 것입니다. (티스토리상에서도 발견됩니다.) jQuery 이외의 라이브러리 중에서도 $ 키워드를 사용중일 경우, 충돌을 일으키고 있을 가능성이 있습니다. 이럴 때, 아래처럼 jQuery를 인자로 받는 IIFE 블럭으로 감싸주면,
(function($) {
  // 코드  
})(jQuery);
블럭 내의 $가 jQuery로 정의되면서 충돌을 방지할 수 있게 됩니다.

전역 변수, 전역 함수가 되지 않도록 방지

내가 사용한 변수 또는 함수가 모든 스코프에서 영향력을 갖는다는 것은, 커다란 버그 창고를 만들게 될 확률이 높습니다. 충분한 이유를 갖고 의도적으로 전역 변수나 함수를 만드는 것이 아닌 이상, 변수나 함수를 특정한 범위에 제한해 충돌을 방지하는 것이 바람직합니다.
(function() {
  function addItem() {
    //...
  }
})();
주의! 위 코드처럼 IIFE로 감싼 함수는, <a onclick="addItem"></a> 처럼 IIFE 바깥에서 호출할 수 없게 됩니다. 이렇게 하길 원하다면 작위적으로 window.addItem = addItem; 처럼 글로벌 네임스페이스에 내 함수를 수동으로 추가해 주어야 합니다.

변수의 값을 즉시 할당

말 그대로 "즉시 함수를 실행해" 리턴값을 변수에 할당하는 경우도 있습니다.
var root = (function() { return document.documentElement || document.body })();
console.log(root); // <html />

var root2 = function() { return document.documentElement || document.body };
console.log(root2); // function() { return ... }
위에서 보듯이, IIFE를 사용하지 않으면 함수의 리턴값이 변수에 할당되는 게 아니라, 함수 자체가 변수에 할당되어 버립니다.

자주 사용되는 특정한 키워드를 압축

아래는 자주 사용되는 키워드 압축용 IIFE 템플릿입니다.
(function(window, document, undefined) {
   //...
})(window, document);
위의 코드를 자바스크립트 압축기로 압축해 보면, 아래와 같은 코드가 출력됩니다.
(function(a, b, c) {
   //...
})(window, document);
매개변수로 받은 windowdocument 및 정의되지 않은 undefined를 a, b, c라는 토큰으로 지정해주기 때문에, 이 IIFE 블럭 내에 있는 모든 window 키워드는 a 라는 1글자로 대체 가능해집니다. 스크립트가 길면 길 수록, 이 방식으로 파일의 용량을 크게 줄일 수 있죠.

덤) 다양한 형태의 IIFE

함수를 괄호로 감싸는 대신, 다른 방식으로 함수 → 함수식을 유도하는 방법도 있습니다.

  • !function() { }
  • +function() { }
  • -function() { }
  • ~function() { }
  • void function() { }
  • return function() { }
  • new function() { }
  • 0, function() { }
  • 1 && function() { }
  • ...
자바스크립트 압축기에서 .min.js 파일을 생성하면 !function(){ 로 시작하는 코드가 출력되는 걸 흔히 보는데, 바로 이 IIFE의 일종입니다. (적은 비트를 사용하면서, 속도적으로도 문제가 없는 최적의 IIFE라고 생각하는 것이죠)

하지만 보통 관례적으로 (function() { })(); 형태를 많이 사용합니다. 가장 우아하고 직관적인 형태의 IIFE라는 이유로 말이죠.

개인적으론 의미적으로 void function() { }();가 가장 훌륭하다고 생각하지만, 다른 프로그래밍 언어를 사용하던 개발자에게 혼란을 줄 수 있기 때문에, 협업할 때는 사용하지 않고 있습니다.

덤) IIFE 앞에 ;를 붙이는 이유

가끔은 ; 로 시작하는 IIFE도 있습니다.
;(function(window, document, $, undefined) {
   
})(window, document, jQuery);
이것은 여러 스크립트 블럭이 호출되었을 때, 선행하는 다른 스크립트 블럭과 충돌하지 않도록 ;로 구분자를 넣어주었을 뿐 특별한 프로그래밍적 의미는 없습니다.


출처 : https://findawayer.tistory.com/entry/IIE%EC%9D%98-%EC%9D%98%EB%AF%B8%EB%8A%94


반응형


댓글

TOP