2 분 소요

즉시 호출 함수 표현식(IIFE)이란?

즉시 호출 함수 표현식(Immediately Invoked Function Expression, IIFE)은 정의되자마자 즉시 실행되는 자바스크립트 함수입니다. ES6 모듈 시스템이 등장하기 전, 개발자들은 IIFE를 사용하여 모듈 시스템을 구현하고 전역 네임스페이스 오염을 방지했습니다.

IIFE의 기본 구조

IIFE의 기본 문법은 다음과 같습니다:

;(function() {
    // 실행될 코드
})();

함수를 괄호로 감싸는 이유는 자바스크립트가 function 키워드로 시작하는 구문을 함수 선언문으로 해석하지 않고 함수 표현식으로 해석하도록 하기 위함입니다.

모듈 시스템 흉내내기

모듈 시스템이 없던 초기 자바스크립트에서는 IIFE를 사용하여 모듈과 같은 효과를 만들어냈습니다. 다음은 온도 변환 모듈을 IIFE로 구현한 예제입니다:

var waterTemperature = (function () {
    // 비공개 변수 - 외부에서 접근 불가
    var boilingPoint = 100;

    // 비공개 함수 - 외부에서 접근 불가
    function convertFahrenheitToCelcius(fahrenheit) {
        var celsius = ((fahrenheit - 32) * 5) / 9;
        return celsius;
    }

    // 공개 인터페이스 반환
    return {
        units: ["Celsius", "Fahrenheit"],
        isWaterBoiling: function (temperature, unit) {
            const celsius =
                unit === "Fahrenheit"
                    ? convertFahrenheitToCelcius(temperature)
                    : temperature;

            if (celsius >= boilingPoint) {
                return "물이 끓는 중";
            }

            return "물이 끓지 않음";
        },
    };
})();

// 사용 예제
console.log(waterTemperature.boilingPoint);        // undefined (접근 불가)
console.log(waterTemperature.units);               // ["Celsius", "Fahrenheit"]
console.log(waterTemperature.isWaterBoiling(50, waterTemperature.units[0])); // "물이 끓지 않음"

IIFE의 주요 특징

1. 즉시 실행

IIFE는 정의와 동시에 실행됩니다. 별도의 호출 없이 바로 실행되어 결과를 반환합니다.

2. 스코프 격리

IIFE 내부에서 선언된 변수와 함수는 외부 스코프에서 접근할 수 없습니다. 이를 통해 전역 네임스페이스 오염을 방지할 수 있습니다.

// 전역 변수 오염 방지
;(function() {
    var privateVariable = "외부에서 접근할 수 없음";
    
    function privateFunction() {
        console.log("비공개 함수");
    }
    
    // 이 변수들은 IIFE 외부에서 접근 불가
})();

console.log(typeof privateVariable); // "undefined"

3. 클로저 활용

IIFE는 클로저를 생성하여 비공개 변수와 메서드를 가진 모듈을 만들 수 있습니다.

var counter = (function() {
    var count = 0; // 비공개 변수
    
    return {
        increment: function() {
            count++;
            return count;
        },
        decrement: function() {
            count--;
            return count;
        },
        getCount: function() {
            return count;
        }
    };
})();

console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
console.log(counter.count); // undefined (접근 불가)

IIFE의 다양한 활용 사례

1. 초기화 코드 실행

;(function() {
    // 페이지 로드 시 한 번만 실행되는 초기화 코드
    console.log("애플리케이션 초기화 완료");
    
    // DOM 조작, 이벤트 리스너 등록 등...
})();

2. 매개변수를 받는 IIFE

var app = (function(window, document, $) {
    // window, document, jQuery를 지역 변수로 사용
    function initializeApp() {
        $(document).ready(function() {
            console.log("앱 초기화");
        });
    }
    
    return {
        init: initializeApp
    };
})(window, document, jQuery);

3. 네임스페이스 패턴

var MyApp = MyApp || {};

MyApp.utils = (function() {
    function formatCurrency(amount) {
        return "" + amount.toLocaleString();
    }
    
    function validateEmail(email) {
        const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return regex.test(email);
    }
    
    return {
        formatCurrency: formatCurrency,
        validateEmail: validateEmail
    };
})();

// 사용
console.log(MyApp.utils.formatCurrency(1000000)); // "₩1,000,000"
console.log(MyApp.utils.validateEmail("test@example.com")); // true

주의사항과 모범 사례

1. 반환값 명시

IIFE에서 무엇을 반환하는지 명확히 하고, 필요한 경우에만 전역 변수에 할당합니다:

// 좋은 예
var myModule = (function() {
    return {
        // 공개 메서드들
    };
})();

// 피해야 할 예 - 불필요한 전역 변수 생성
window.unnecessaryGlobal = (function() {
    return {};
})();

2. 의존성 주입

외부 라이브러리나 전역 객체를 매개변수로 전달하여 의존성을 명시적으로 관리합니다:

var myModule = (function($, window, document) {
    // jQuery, window, document를 안전하게 사용
    
    return {
        // 공개 인터페이스
    };
})(jQuery, window, document);

ES6 모듈과 비교

// IIFE 방식
var mathUtils = (function() {
    function add(a, b) {
        return a + b;
    }
    
    function multiply(a, b) {
        return a * b;
    }
    
    return {
        add: add,
        multiply: multiply
    };
})();

// ES6 모듈 방식
// mathUtils.js
export function add(a, b) {
    return a + b;
}

export function multiply(a, b) {
    return a * b;
}

// main.js
import { add, multiply } from './mathUtils.js';

댓글남기기