본문 바로가기
Script/JavaScript

[JavaScript] Chapter 35. 일반 함수 vs 익명 함수

by song.ift 2023. 1. 26.

자바스크립트는 유연한 언어이다. 따라서 다른 일반적인 언어(Java, C)와 다르게, 함수를 선언하고 사용하는데 있어 굉장한 자유로움이 주어진다. 이는 능숙한 사람에게는 굉장한 이점으로 주어질 수 있지만, 미숙한 사람에게는 넘어야 할 허들이 되기도 한다. 자바스크립트에서 함수 선언 방식은 기본적으로 일반 함수와 익명 함수로 나눌 수 있다.

 

1. 일반 함수 

일반적으로 다른 언어에서 사용하는 함수와 동일하다. 사용방식 또한 동일하며, 코드를 조금이라도 읽을 수 있는 사람이라면 매우 쉽게 이해할 수 있는 함수이다. 일반 함수는 다른 말로 함수 선언식이라고도 할 수 있다.

function 함수명(){
  함수 로직
}

// 예시
function SayHello(){
  console.log("hello!");
}

SayHello(); // 출력: hello!

일반 함수는 자바스크립트가 처음 읽힐 당시에 해석되므로, 함수가 쓰여진 위치가 상관없다.

이를 호이스팅이라고 하는데, 호이스팅이란 쉽게 말해 자바스크립트가 처음 읽힐 당시에 모든 객체(변수, 함수)의 선언부를 맨 위로 끌어올리는 것이다.

일반 함수는 함수 전체(함수명, 함수바디)가 통째로 호이스팅 되어 맨 위로 올라가기 때문에 위치 상관없이 읽을 수 있는 것이다.

SayHello(); // "hello!" 가 정상적으로 출력됨.

function SayHello(){
  console.log("hello!");
}

SayHello(); // "hello!" 가 정상적으로 출력됨.

// 호이스팅 된 모습
//
// function SayHello(){      <- 함수 선언이 먼저 일어나고,
//   console.log("hello!");
// }
//
// SayHello(); <- 첫 번째 SayHello();
// SayHello(); <- 두 번재 SayHello();

 

2. 익명 함수 

우선 익명함수 자체는 다음과 같은 형태를 가지고 있다. 일반 함수와 비교하여보면, 함수의 이름이 존재하지 않는다.

function() {
  console.log("hello!");
}

익명 함수는 재사용 하지 않는, 한번만 사용할 함수를 위한 개념으로, 따로 함수의 이름을 갖지 않는다. 리터럴(Literal) 방식으로 변수에 담겨 사용하는 함수이다. ("함수의 이름 != 변수" 임을 확실히 이해해야한다.)

리터럴(Literal) 방식이란 글자 뜻 그대로 "문자 그대로 읽히는 방식"을 의미하며, 일반적으로 변수에 데이터를 넣을 때 사용하는 방식이 리터럴 방식이다.

// 리터럴 방식

let a = 10;
const b = 20;

리터럴 방식으로 사용되는 익명 함수는, 변수에 저장되게 된다.

//익명 함수

const sayHello = function() {
  console.log("hello!");
}

sayHello(); // 출력: hello!

다시 한번 말하지만, 함수가 이름을 갖는 것과 변수에 저장되는 것은 다르다. 

이 차이점은 어디서 오냐면, 위에서 언급한 호이스팅의 개념에서 온다.

위의 일반함수의 경우, 함수 전체가 전부 맨 위로 올라가므로 함수를 호출하는 위치에 상관없이 사용될 수 있다고 했다. 

반면, 리터럴 방식으로 사용되는 익명 함수의 경우, 호이스팅 시 함수를 담는 변수의 선언부만 위로 올라가고, 익명 함수 자체는 변수가 호출되었을 때 실행되기 때문에, 선언부가 호출 위치보다 위에 있어야 한다. 코드로 보면 다음과 같다.

//익명 함수

sayHello(); // Uncaught ReferenceError: Cannot access 'sayHello' before initialization

let sayHello = function() {
  console.log("hello!");
}

sayHello(); // 위에서 에러가 났으니 출력이 나오지 않음

// 이 자바스크립트를 읽을 때(호이스팅 된 모습)
// 
// const sayHello;
//
// sayHello(); <- sayHello의 초기화가 진행되지 않았다.
// 
// sayHello = function(){
//   console.log("hello!");
// }
//
// sayHello(); <- 초기화는 진행된 후 불렸으니, 원래대로라면 출력 가능

 

3. 결론

1) 일반 함수는 전역적이며, 전체가 다 호이스팅 되므로 호출의 위치와 구현의 위치간에 연관관계가 없다. 또한, 재사용될 기능에 주로 사용된다.

2) 익명 함수는 선언부만 호이스팅되며 호출의 위치와 구현의 위치간에 순서가 알맞아야 하고, 한번만 사용하는 기능에 사용된다. 

위 말만 보면 익명 함수가 오히려 번거로운 것처럼 보일 수 있지만, 이는 메모리 관리에 효과적인 방안이 될 수 있다.

일반 함수는 자바스크립트를 초기에 읽어올 때 모두 호이스팅된다고 하였다.

만약, 전체 자바스크립트 내에서 단 한번만 쓰이는 함수가 일반 함수로 구현되어 있다고 가정해보자.

이 함수는 자신이 사용될 단 한번을 기다리며 불필요하게 메모리를 차지하고 있어야 한다. 메모리 사용량이 성능에 중요한 영향을 미칠 수 있는 웹 애플리케이션에서, 이는 메모리 낭비라고 볼 수 있다.

따라서 단 한번만 사용되는(재사용이 필요없는) 함수의 경우, 불필요한 시간동안 메모리를 차지하지 않도록 익명함수로 구현한다면, 정확히 해당 함수가 필요한 위치에서만 해당 함수가 구현되고 사라지면서 메모리를 아낄 수 있게 된다.

댓글