[JavaScript] 즉시 실행 함수(IIFE) 정리: 스코프 격리와 실전 사용법
즉시 실행 함수(IIFE, Immediately Invoked Function Expression)는 정의하자마자 곧바로 실행되는 함수 표현식을 의미한다.
과거에는 전역 스코프 오염을 막고, 임시 변수를 안전하게 숨기기 위한 용도로 매우 자주 사용되었다.
현대 자바스크립트에서는 let/const와 모듈(ESM)이 보편화되며 사용 빈도가 줄었으나, 특정 상황에서는 여전히 유용하게 쓰인다.
1. 즉시 실행 함수(IIFE)의 기본 형태
IIFE는 “함수 선언문”이 아니라 “함수 표현식”으로 만들어야 하며, 보통 함수 전체를 괄호로 감싸서 표현식으로 만든 뒤 ()로 즉시 호출한다.
가장 흔한 형태
1
2
3
(() => {
console.log("IIFE 실행"); // "IIFE 실행"
})();
1
2
3
4
5
6
7
(function () {
console.log("함수 키워드 IIFE"); // "함수 키워드 IIFE"
})();
(function () {
console.log("호출 괄호를 바깥으로"); // "호출 괄호를 바깥으로"
}());
2. 왜 IIFE를 쓰는가
IIFE의 핵심 목적은 한 번만 실행할 로직을 묶고, 그 안에서 만든 변수를 바깥에서 접근하지 못하게 숨기는 것에 있다.
전역 변수 오염 방지
1
<p class="result"></p>
1
2
3
4
5
6
7
8
9
10
(() => {
const secret = "외부에서 접근 불가";
const result = document.querySelector(".result");
if (result) result.textContent = secret;
console.log(secret); // "외부에서 접근 불가"
})();
console.log(secret); // ReferenceError (바깥에서는 접근 불가)
IIFE 내부의 const/let 변수는 IIFE 실행이 끝나면 바깥에서 직접 접근할 수 없다.
따라서 임시 변수, 설정값, 초기화 로직 등을 안전하게 묶을 수 있다.
3. 반환값을 활용하는 방식
IIFE는 즉시 실행되지만, 실행 결과를 반환하여 바깥 변수에 담아 사용할 수 있다.
초기화 결과를 한 번만 계산하기
1
2
3
4
5
6
7
8
9
const config = (() => {
const env = "prod";
const apiBase = env === "prod" ? "https://api.example.com" : "http://localhost:3000";
return { env, apiBase };
})();
console.log(config.env); // "prod"
console.log(config.apiBase); // "https://api..example.com"
- 한 번만 계산하고 재사용할 값을 만들 때 유용하다.
4. IIFE와 클로저: 상태를 숨겨서 유지하기
IIFE는 내부에 상태를 만들고, 그 상태를 참조하는 함수를 반환하여 외부에서 직접 수정할 수 없는 상태를 만들 수 있다.
이 방식은 클로저의 대표적 활용 예시 중 하나이다.
ex) 외부에서 직접 접근할 수 없는 카운터
1
2
<button class="btn">+1</button>
<p class="count"></p>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const counter = (() => {
let count = 0;
return {
inc() {
count += 1;
console.log(count);
return count;
},
};
})();
const btn = document.querySelector(".btn");
const out = document.querySelector(".count");
btn?.addEventListener("click", () => {
const v = counter.inc(); // 1, 2, 3 ... (클릭할 때마다 증가)
if (out) out.textContent = String(v);
});
count는 IIFE 내부에만 존재한다.외부에서는
counter.inc()같은 공개된 함수로만 변경할 수 있다.
5. (단골 예시) for + setTimeout에서 var 문제를 IIFE로 해결하기
var는 함수 스코프이므로 반복문에서 하나의 변수를 공유하는 문제가 생길 수 있다.
이때 IIFE로 현재 값을 인자로 전달하여 고정하면 원하는 출력이 가능하다.
var의 문제 상황
1
<button class="btn">실행</button>
1
2
3
4
5
6
7
8
const btn = document.querySelector(".btn");
btn?.addEventListener("click", () => {
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// console.log 결과: 3, 3, 3
});
IIFE로 값 고정하기
1
<button class="btn">실행</button>
1
2
3
4
5
6
7
8
9
10
const btn = document.querySelector(".btn");
btn?.addEventListener("click", () => {
for (var i = 0; i < 3; i++) {
((x) => {
setTimeout(() => console.log(x), 0);
})(i);
}
// console.log 결과: 0, 1, 2
});
IIFE가 실행되는 순간
i값이x로 복사되어 고정된다.이후 타이머 콜백은
x를 참조하므로 0, 1, 2가 출력된다.
현대 코드에서는 같은 문제를 let으로 해결하는 것이 더 간단하다.
다만 왜 var에서 문제가 생기는지 설명할 때 IIFE는 여전히 좋은 예시가 된다.
6. 현대 자바스크립트에서의 위치
현재는 다음 기능들이 널리 사용되므로, IIFE의 필요성이 과거보다 줄어든 편이다.
- let/const의 블록 스코프
- ES 모듈(파일 단위 스코프)
- 번들러/모듈 시스템에 의한 격리
그럼에도 다음과 같은 경우에는 IIFE가 여전히 실용적이다.
- “초기화 로직을 한 번만 실행”하고 그 결과를 저장하고 싶을 때
- “임시 변수를 외부에 노출하지 않고” 짧게 캡슐화하고 싶을 때
- 레거시 코드에서 var 스코프 문제를 설명하거나 최소 변경으로 해결해야 할 때
마무리
즉시 실행 함수(IIFE)는 함수를 정의하자마자 실행하여 스코프를 격리하고,
임시 변수와 초기화 로직을 안전하게 캡슐화하기 위한 패턴이다.
현대에는 let/const와 모듈이 대체하는 경우가 많지만 특정 상황에서는 여전히 유용하다.