티스토리 뷰
[JavaScript] IIFE(Immediately Invoked Function Expression)
til-odin 2025. 3. 23. 16:2300. TL;DR
- 즉시 실행 함수(IIFE)는 함수를 정의하고 바로 실행하는 패턴을 말합니다.
- 주로 전역 변수 오염을 막고, 독립적인 스코프를 만들기 위해 사용됩니다.
01. IIFE란?
즉시 실행 함수(Immediately Invoked Function Expression)는 함수를 정의함과 동시에 즉시 실행하는 패턴입니다.
이 패턴은 ES6 모듈이 도입되기 전, 모듈화 개념이 없던 자바스크립트 환경에서 전역 스코프 오염을 방지하고 캡슐화된 로직을 만들기 위해 자주 사용되었습니다.
즉시 실행 함수는 반드시 함수 표현식(Expression) 형태로 정의되어야 합니다. (함수 선언문은 즉시 실행할 수 없습니다.)
02. 표현식(Expression)이란?
표현식(Expression)은 값이 되는 코드입니다.
- 리터럴
- 그 자체로 값(
"hello",42,true)입니다.
- 그 자체로 값(
- 표현식
- 계산을 통해 값을 만드는 코드입니다.
함수 선언문과 함수 표현식의 구분이 중요합니다:
- 함수 선언문
- 독립적인 문장으로 해석되며 값으로 평가되지 않습니다.
- 함수 표현식
- 값으로 평가되고 변수나 상수에 할당될 수 있습니다.
예시
// 함수 선언문 (값으로 평가되지 않음, 호이스팅 됨)
function test() {}
// 함수 표현식 (값으로 평가됨, 변수에 할당 가능)
const test = function() {};
즉시 실행 함수가 표현식을 사용하는 이유는 자바스크립트에서 표현식만 즉시 평가 호출이 가능하기 때문입니다.
03. 기본 문법과 실행 흐름
03.01. 일반적인 문법
(function() {
console.log('이 코드는 즉시 실행됩니다.');
})();
실행 흐름
- 익명 함수가 정의됨
- 첫 번째 괄호: 익명 함수를 표현식으로 평가하도록 만듦
- 마지막 괄호: 평가된 표현식(익명 함수)을 실행
03.02. 괄호를 마지막에 감싸는 형식
(function() {
console.log('이 코드는 즉시 실행됩니다.');
}());
실행 흐름
- 익명 함수가 정의 됨
- 함수 정의 직후 붙은 괄호 ( )가 정의된 익명 함수를 즉시 실행
- 전체를 감싼 괄호 ( )가 즉시 실행된 함수 호출 전체를 하나의 표현식으로 평가
03.02.01. 표현식 평가 순서에 대한 명확한 이해
자바스크립트에서 즉시 실행 함수(IIFE)의 평가와 실행 순서는 간단히 다음과 같이 이해할 수 있습니다:
먼저 이 코드 예시를 다시 봅시다:
(function() {
// 실행 코드
}());
이 코드가 실행되는 과정은 크게 다음 두 단계로 나뉩니다:
표현식으로 함수 정의하기
- 일반적으로 자바스크립트에서 함수는 두 가지 방법으로 정의할 수 있습니다:
- 함수 선언문(Statement):
function myFunc() { } - 함수 표현식(Expression):
var myFunc = function() { }
- 함수 선언문(Statement):
- 즉시 실행 함수(IIFE)의 경우 함수 선언문이 아닌 표현식으로 정의되어야 합니다.
그런데 자바스크립트는function() { }형태만 보고는 표현식으로 인식하지 않습니다. - 따라서 이 익명 함수를 강제로 표현식으로 만들어 주기 위해 괄호
( )로 감싸는 것입니다.
(function() { /* 코드 */ });
이 순간 자바스크립트 엔진은 이 함수를 "표현식"으로 평가하게 됩니다.
함수 호출하기
- 이렇게 표현식으로 평가된 함수 뒤에 다시 괄호
()를 붙여주면, 이 함수가 곧바로 호출됩니다.
(function() { /* 코드 */ }());
여기에서 뒤에 오는 괄호는 바로 앞에서 평가된 함수 표현식을 호출(call) 하는 괄호입니다.
즉, 정리하면:
- 바깥쪽 괄호
()가 우선적으로 내부의 코드를 표현식으로 만들어줍니다. - 자바스크립트 엔진은 내부의 익명 함수를 표현식으로 인식(평가)합니다.
- 평가된 함수 표현식에 이어서 붙는 괄호
()로 즉시 호출(실행)합니다.
이 과정을 직관적으로 이해하려면 다음과 같은 느낌으로 생각하면 쉽습니다:
"자바스크립트 엔진은
()안의 코드를 표현식(Expression) 이라고 간주하고, 표현식 평가가 완료된 직후에 이어지는()괄호를 만나자마자 즉시 호출(Call) 한다."
03.03. 연산자를 활용한 즉시 실행 방법과 주의점
연산자(+, -, ~, !)를 사용하여 함수 선언문을 표현식으로 바꿔 즉시 실행할 수도 있습니다.
⚠️ 이 방식은 리턴되는 값을 연산자를 통해 변경되기 때문에 추천하지 않습니다.
- ❗ 함수 리턴 값이 존재할 때는 리턴된 결과 값에 해당 연산자가 적용됩니다.
- 리턴 값이 없으면(
undefined) 해당 연산자 규칙에 따라 값이 결정됩니다.
예시:
// 숫자 문자열을 반환하는 경우
const result = -function() {
return '123';
}();
console.log(result); // 숫자 -123 (문자열 '123'이 숫자형으로 변환되고 -로 값으로 변경)
// 리턴 값이 없는 경우
const result2 = !function() {
console.log('no return');
}();
console.log(result2); // true (undefined → 논리 NOT으로 true로 변환)
각 연산자의 특성
| 연산자 | 설명 | 리턴값이 없을 때(undefined) |
|---|---|---|
! |
논리 부정, boolean 변환 | true |
+ |
숫자 변환 | NaN |
- |
음수로 숫자 변환 | NaN |
~ |
비트 NOT 연산 | -1 |
⚠️ 주의사항: 연산자 방식은 리턴 값이 중요할 경우 명확히 이해한 경우에만 사용합니다.
04. 괄호(()) 연산자의 동작 원리
04.01. 함수 호출로서의 괄호
(function greet(name) {
console.log('Hello, ' + name);
})('수원');
// 출력: Hello, 수원
IIFE 에서 함수를 표현식으로 변경하여 즉시 실행할 수 있도록 사용할 수 있습니다.
04.02. 표현식 평가로서의 괄호
(1); // 1
(1 + 2 - 10); // -7
표현식 평가 후 최종값 반환에 사용됩니다.
04.03. 그룹 연산자로서의 괄호
(2 * (10 - 5)); // 10;
표현식의 연산 우선순위를 명확히 지정합니다.
05. 실무 예제
05.01. 전역 변수 오염 방지
전역 스코프를 오염키지 않고 전역 변수 선언을 최소화 하기 위한 패턴에 사용됩니다.
(function() {
var count = 0; // 외부에 노출되지 않음
function increment() {
count++;
}
increment();
})();
위 코드는 외부에서 count에 접근 불가능하게 만들어 전역 변수를 보호합니다.
05.02. 즉시 실행 결과를 변수에 저장(초기 설정)
초기 설정값을 즉시 생성하여 변수에 저장할 때 사용됩니다.
const config = ((envName) => {
const envMap = {
production: {
apiUrl: 'http://api.com',
serviceUrl: 'http://service.com',
},
dev: {
apiUrl: 'http://dev.api.com',
serviceUrl: 'http://dev.service.com',
},
}
return {
...(envMap[envName] ?? envMap.production)
}
})(process.env.NODE_ENV);
// 사용:
console.log(config.apiUrl); // http://api.com
05.03. 싱글톤(Singleton) 객체 생성
싱글톤 패턴으로 하나의 인스턴스를 즉시 생성하고자 할 때 사용할 수 있습니다.
const Logger = (function () {
let instance;
const createInstance = () => {
return {
log(message) {
console.log(`[LOG]: ${message}`);
}
};
}
return {
getInstance: () => {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
// 사용:
const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();
logger1.log('첫 번째 로그'); // [LOG]: 첫 번째 로그
logger2.log('두 번째 로그'); // [LOG]: 두 번째 로그
console.log(logger1 === logger2); // true (같은 인스턴스)
05.04. 특정 함수만 외부로 노출
모듈의 내부 구현을 숨기고 필요한 메서드만 공개할 때 유용합니다.
const counter = (() => {
let count = 0;
const increment = () => {
return ++count;
}
const decrement = () => {
return --count;
}
const reset = () => {
count = 0;
}
return { increment, reset };
})();
// 사용:
console.log(counter.increment()); // 1
counter.reset();'FrontEnd > javascript' 카테고리의 다른 글
| [JavaScript] 바이트 코드 (0) | 2025.03.31 |
|---|---|
| [JavaScript] 자바스크립트 생성자 함수 (0) | 2025.03.26 |
| [JavaScript] Shadow DOM (0) | 2025.03.21 |
| [JavaScript] 자바스크립트 메모리 관리 - 스택, 힙, 변수 (0) | 2025.03.21 |
| Bitwise Operation (0) | 2025.03.21 |
- Total
- Today
- Yesterday
- library mode
- JIT
- 바이트 코드
- vee-validate
- npm ci
- useasyncdata
- nuxt
- JavaScript
- bundler
- interning
- string
- deep dive
- string table
- react
- premitive
- pakage-lock.json
- primitive
- TypeScript
- 모노레포 스크립트
- webpack
- double-linked-list
- refrerence
- prototype
- vue
- react-router
- scoped slot
- uselazyasyncdata
- pnpm 명령어
- object literal
- ViTE
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
