[ JavaScript ] 즉시실행함수(IIFE)

exceed_96·2024년 2월 9일

JavaScript

목록 보기
13/18
post-thumbnail

JavaScript에는 화살표 함수, 일반함수, 콜백함수, 익명함수 등등 다양한 형태의 함수가 존재한다. 이외에 일반적인 형태나 동작을 하는 함수들이 존재하는데 이번 포스팅에서는 "정의와 동시에 실행"되는 즉시실행함수(IIFE)에 대해서 알아보자.


1. 즉시실행함수(IIFE)란?

즉시실행함수의 영문 표기법은 "Immediately Invoked Function Expression"의 약자로서 직역 그 자체로 "즉시 호출되는 함수 표현식"이라는 뜻이다.

그럼 여기서 즉시 호출된다는 건 무슨 말일까?

JavaScript에서 즉시실행함수는 "정의와 동시에 실행되는 함수"라고 말할 수 있다.

즉, 말 그대로 JavaScript Interpretor가 전체코드를 순회하면서 즉시실행함수를 만나면 해당 함수를 정의함과 동시에 실행을 시키는 것이다.



2. 즉시실행함수(IIFE) 형태

2.1 괄호 * 괄호

(function () {
  console.log("즉시 실행 함수 동작");
})();

(() => {
  console.log("즉시 실행 함수 동작(화살표 함수)");
})();

위와같이 익명함수를 괄호()로 감싸주어서 내부 코드가 함수의 선언문이 아닌 표현식인것처럼 나타낸다.

함수 선언문이 아닌 화살표 함수로도 즉시실행함수를 정의할 수 있다.


2.2 괄호안에 괄호

(function () {
  console.log("즉시 실행 함수 동작");
}());

위와같이 즉시실행함수 표시인 괄호()를 익명함수의 괄호를 바깥쪽에 이어주는게 아닌 함수 로직괄호 {}옆에다가 정의하여서 즉시실행함수로 표현하는 방법이다.

위 방법은 "Douglas Crockford"가 권장하는 표준표기법이며 첫번째 방법과 차이점은 괄호 ()위치의 차이이다.

"Douglas Crockford"는 JavaScript의 표준화와 개발, JSON의 설계자 중 한명이다.

위 두 방법은 모두 괜찮은 방법이므로 본인의 선호도에 따라 선택하면 된다.



3. 즉시실행함수는 익명함수로만 가능한걸까?

(function exampleFunc() {
  console.log("즉시 실행 함수 동작");
})();

즉시실행함수는 익명함수롬나 정의할 수 있는게 아닌 함수명을 지정해줘도 동작한다.

단, 여기서 알아야 할 점은 즉시실행함수는 일회성인 성격을 지닌 함수이다.

함수명을 정의한다는건 결국 여러군데에서 재사용하기 위해서 호출한다는 것인데 일회성인 즉시실행함수에는 다소 맞지 않은 정의이다.

물론 이 부분도 개발자의 선호도에 따라 선택할 수 있는 하나의 방법이지만 보통은 익명함수로 사용하는것이 대부분이다.

그럼 익명함수는 어떤식으로 활용할 수 있는걸까?



4. 즉시실행함수의 활용 예시

4.1 전역변수 충돌방지

(function() {
    const globalVariable1 = 10;
    const globalVariable2 = "Hello";
    console.log(globalVariable1); // 출력: 10
    console.log(globalVariable2); // 출력: "Hello"
})();

// 즉시 실행 함수 내부의 변수에 접근할 수 없다.
console.log(globalVariable1); // 오류: globalVariable1은 정의되지 않았습니다.
console.log(globalVariable2); // 오류: globalVariable2는 정의되지 않았습니다.

즉시실행함수는 해당 익명함수 안에 있는 변수들의 스코프를 제한하고 전역변수 충돌을 방지해준다.

이를 통해 불필요한 전역변수 생성을 막을 수 있다는 장점이 있다.

불필요한 전역변수의 예로는 일회성인 변수를 전역변수로 선언하는게 아닌 지역변수로 선언하여서 일회성 변수로 사용하는 것이다.

또한 외부로부터 해당 변수 접근을 막을 수 있다는 장점이 있다.


4.2 비동기 처리

await키워드는 보통 async키워드가 붙어있는 함수 안에서만 사용이 가능하다.

이럴 경우 await키워드가 필요없는 다른 로직도 해당 async함수 안에 정의해야 하는건 가독성 측면에서 좋지 않다.

(async () => {
    console.log("Start");

    // 비동기 작업 1
    const result1 = await fetch("https://api.example.com/endpoint1");
    console.log("Result 1:", result1);

    // 비동기 작업 2
    const result2 = await fetch("https://api.example.com/endpoint2");
    console.log("Result 2:", result2);

    // 비동기 작업 3
    const result3 = await fetch("https://api.example.com/endpoint3");
    console.log("Result 3:", result3);

    console.log("All tasks completed");
})();

위 예시에서는 즉시실행함수를 사용하여 async를 정의하고 호출하고 있다.

위와같이 하면 async함수를 별도의 함수 호출로 만들지 않고 일반코드실행 방식과 유사한 방식으로 사용할 수 있다.


5. 마치며

즉시실행함수 자체는 어려운 개념이 아니다. 주로 전역변수의 초기화에서 쓰이는 방법으로 알고 있는데 실질적으로 코드상으로 사용하는 케이스는 자주 못본거 같다.

다만 즉시실행함수 형태가 많이 사용하는 영역은 모듈과 라이브러리를 만들 때 많이 사용한다고 알고 있다.

보통 하나의 프로젝트에서는 수많은 모듈과 라이브러리가 사용되기 때문에 각 모듈과 라이브러리의 전역변수로 인한 전역 스코프 오염을 방지하고 모듈간의 의존성을 관리하기 위해 사용했다고 알 고 있다.

또 ES6이후에는 import, export, require과 같은 모듈을 가져오거나 내보낼 수 있는 내장기능이 생겼기 때문에 더욱 더 즉시실행함수의 사용빈도는 줄어드는 추세라고 생각한다.

다만, 즉시실행함수는 모듈과 라이브러리의 구성 말고도 일반적인 프로젝트에서도 효율적으로 사용할 수 있다고 생각한다.

전역변수 같은 경우는 솔직히 실제 프로젝트에서 큰 용도로 쓰이지는 않을거 같지만 비동기로직 처리에서는 일회성인 api call 함수를 즉시실행함수로 정의하는건 자원, 가독성 측면에서는 크게 도움이 될거 같다.(물론 자주 쓰일지는 모르겠지만..)



6. Reference

https://developer.mozilla.org/ko/docs/Glossary/IIFE
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-IIFE-%EC%A6%89%EC%8B%9C%EC%8B%A4%ED%96%89-%ED%95%A8%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D

profile
개발진행형

0개의 댓글