Javascript IIFE 이해하기

IIFE(Immediately Invoked Function Expressions: “Iffy”라고 발음)는 즉시 호출 함수 표현식의 줄임말입니다.

iife

기본적인 형태는 다음과 같습니다.

1
2
3
4
(function () {
// Do fun stuff
}
)()

이것은 즉시 호출되는 익명 함수 표현식 입니다. 이것은 자바스크립트에서 때에 따라 중요하게 사용될 수 있습니다.

함수 선언(Declaration)과 표현(Expression)

IIFE를 설명하기 전에 함수의 선언(Function Declaration)과 함수의 표현(Function Expression)의 차이점에 대해 이해할 필요가 있습니다. Mozilla Developer Site의 함수에 대한 설명을 보면 함수 표현식은 선언과 동일한 문법을 가지고 단지 표현식에서는 함수명이 생략될 수 있다고만 기술하고 있습니다. 틀린말은 아니지만 사실 이 보다 좀 더 뚜렷한 형태와 동작의 차이점을 가지고 있습니다.

함수 선언(declaration)은 미리 자바 스크립트의 실행 컨텍스트(execution context)에 로딩 되어 있으므로 언제든지 호출할 수 있지만, 표현식(Expression)은 인터프리터가 해당 라인에 도달 하였을때만 실행이 됩니다.

즉, 함수 선언(declaration)을 조건(conditionally)에 따라 할당(assignment)하거나, 생성, 또는 괄호 연산자로 그루핑(grouping)하여 표현식으로 나타낼 수 있습니다. 다음 소스는 함수 정의(선언과 표현)의 차이를 간단히 보여주고 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
foo(); // success!
function foo() {
alert('foo');
}
foo(); // "foo" is not defined.
var foo = function() {
alert('foo');
};
alert(foo); // "foo" is not defined.
(function foo () {});
alert(foo); // "foo" is not defined.

IIFE를 설명하기 위한 function declaration과 function expression의 설명은 이정도만 하겠습니다.

즉시 호출 함수 표현식은 어떻게 작동하는가?

  • 괄호쌍이 익명의 함수를 감싸서 함수 선언(declaration)을 함수 표현식(expression)으로 표현될 수 있습니다. 그러므로, 단순한 익명의 함수를 global 스코프에 선언하지 않고 어디서든 익명의 함수 표현식을 가질 수 있습니다.
  • 따라서, 아래와 같은 표현식이 가능합니다.

    1
    2
    3
    4
    5
    // 괄호 사용 안함
    x = function () {};
    // 괄호 사용
    (x = function () {});
    // 변수 x에는 함수의 값이 할당됩니다. 괄호로 둘러쌓인 함수는 익명의 함수 표현식이 됩니다.
  • 이와 유사하게 이름을 부여하고, 즉시 호출된 함수 표현식으로 생성할 수 도 있습니다.

    1
    2
    3
    4
    5
    6
    (showName = function (name) {
    console.log(name || "No Name")
    }
    ) (); // No Name
    showName("Rich"); // Rich
    showName(); // No Name
  • showName 함수는 선언과 동시에 실행이 되며, 이름이 있으므로 나중에 호출 할수도 있습니다.

  • 하지만, 익명의 표현식은 나중에 다시 호출할 수 없습니다. 참조할 방법이 없기 때문입니다.
  • 익명의 함수를 괄호안에(group context) 위치시킬 경우, 전체 그룹을 평가(evaluate)하고 값을 리턴합니다. 결국, 리턴값은 익명 함수 자신입니다.
  • 마지막 두개의 괄호는 JS컴파일러에게 이 익명 함수를 바로 호출하라고 말합니다. 이것을 IIFE라고 부릅니다.

언제 IIFE를 사용하는가?

젼역 영역(Global Scope)를 오염 시키지 않기 위해서

IIFE를 사용하는 주된 이유는 변수를 전역(global scope)으로 선언하는 것을 피하기 위해서 입니다. 많은 JavaScript 라이브러리와 전문가들이 이 기법을 사용합니다. jQuery plugin개발자들 사이에서 특히 인기가 많습니다. JS어플리케이션의 Top-Level - main.js 또는 app.js와 같은 - 에서도 IIFE를 사용할 수 있습니다. 아래 코드는 지역 변수를 익명 함수로 위치시켜 외부와의 충돌을 방지할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// All the code is wrapped in the IIFE
(function () {
var firstName = “Richard”;
function init () {
doStuff (firstName);
// code to start the application
}
function doStuff () {
// Do stuff here
}
function doMoreStuff () {
// Do more stuff here
}
// Start the application
init ();
}) ();

필요한 경우 마지막 괄호안에 외부 객체나 변수를 넣어 익명의 함수에 전달할 수 도 있습니다.

조건문과 함께 사용하기

잘 알려지지 않았지만, 복잡한 로직을 다룰때 조건에 따라 함수정의를 달리 하여 설정하고 호출 할 수도 있습니다. 이 기법은 때론 유용할 수도 있겠으나, 대채로 사용하지 않길 바랍니다. 프로그램의 전반적인 가독성을 떨어트리고 버그를 양산할 수 있습니다. 꼭 사용해야 한다면 들여쓰기를 충분히 하여 코드를 읽기 쉽도록 유지하시기 바랍니다.

클로저에서 값의 중복 현상 해결

자바스크립트 클로저 쉽게 이해하기 에서 다루었던것 처럼, 순환문내에서 클로저 사용시 IIFE 기법을 사용해 참조에 의한 클로저의 오작동을 해결할 수 있습니다.

IIFE기법은 이제 많은 JS프레임워크들이나 오픈소스에서 쉽게 찾아볼 수 있습니다. JS코딩을 하면서 아직 이 기법에 대해 잘 모르거나 쓰고 있지만, 어떻게 작동하고 왜 사용하는지 모르고 있다면 이 글이 이해를 돕는데 조금이나마 도움이 되었길 바랍니다.

더 자세한 정보는 아래 참고 사이트의 글들을 참고 하시기 바랍니다.

12 Simple (Yet Powerful) JavaScript Tips
Functions and function scope
ECMA-262-3 in details