blog.pisik.club
article thumbnail
728x90


자바스크립트를 공부하다 보면 “함수를 어떻게 정의해야 할까?”라는 질문을 자주 접합니다. 어떤 경우에는 function 키워드를 이용한 전통적인 방식이 쓰이고, 또 다른 경우에는 const와 함께 익명 함수나 화살표 함수가 등장합니다. 얼핏 보면 결과가 똑같아 보이지만, 사실 내부 동작은 꽤 큰 차이가 있습니다.

이 차이를 제대로 이해하지 못하면 React 컴포넌트 안에서 이벤트 핸들러가 엉뚱하게 실행되거나, 비동기 코드에서 this가 예상과 다르게 동작하는 등의 문제가 생길 수 있습니다. 오늘은 함수 선언식(Function Declaration)함수 표현식(Function Expression)의 특징을 구체적인 예시와 함께 정리하고, 실제로 어떤 상황에서 어떤 방식을 쓰는 게 더 적합한지 깊이 살펴보겠습니다.

 


함수 선언 방식의 두 가지 축

자바스크립트에서 함수를 정의하는 방법은 크게 두 갈래입니다.

함수 선언식 (Function Declaration)

함수 선언식은 가장 전통적인 방식으로, function 키워드와 함수 이름을 사용합니다.

function sayHello() {
  console.log("Hello, world!");
}

 

특징:

  • 함수 이름 필수 → 호출 시점에 직관적.
  • 호이스팅(hoisting) 지원 → 정의보다 먼저 호출 가능.
  • 주로 전역적으로 쓰이는 유틸 함수나 초기화 로직에 적합.

예를 들어, 아래 코드는 정상적으로 실행됩니다.

greet(); // "Good morning!"

function greet() {
  console.log("Good morning!");
}

함수 표현식 (Function Expression)

함수 표현식은 함수를 “값”처럼 변수에 담는 방식입니다.

const sayHello = function () {
  console.log("Hello, world!");
};

혹은 ES6 이후에는 화살표 함수 문법을 더 많이 사용합니다.

const sayHello = () => {
  console.log("Hello, world!");
};

특징:

  • 익명 함수 또는 이름 있는 함수 모두 가능.
  • 호이스팅 불가 → 정의 전에 호출하면 오류 발생.
  • 블록 스코프 안에서만 유효.
  • 콜백 함수, 이벤트 핸들러, 동적으로 생성되는 함수에 적합.
sayHello(); // ReferenceError 발생

const sayHello = () => {
  console.log("Hello!");
};

호이스팅 차이: 선언식 vs 표현식

자바스크립트 엔진은 실행 전에 코드를 먼저 스캔하면서 변수와 함수를 메모리에 올립니다. 이 과정을 호이스팅이라고 부릅니다.

 

함수 선언식 전체 함수가 호이스팅 → 어디서든 호출 가능.
함수 표현식 변수 선언만 호이스팅 → 값(함수)은 나중에 할당됨.

 

즉, 함수 표현식은 일시적 사각지대(TDZ)라는 구간이 생겨서, 정의 전에 호출하면 에러가 납니다.


함수 표현식의 다양한 활용법

함수 표현식은 “단순히 변수에 함수를 담는 방식”을 넘어, 실무에서 훨씬 폭넓게 쓰입니다.

이름이 있는 함수 표현식

const factorial = function inner(n) {
  if (n <= 1) return 1;
  return n * inner(n - 1);
};

console.log(factorial(5)); // 120


장점:
재귀 호출 시 자기 자신을 참조 가능.
디버깅 시 스택 트레이스에 함수 이름이 표시 → 추적이 더 쉬움.

 

화살표 함수 표현식

화살표 함수는 this 동작이 독특합니다. 자신만의 this를 가지지 않고, 외부 스코프의 this를 그대로 가져옵니다.

const counter = {
  value: 0,
  start() {
    setInterval(() => {
      this.value++;
      console.log(this.value);
    }, 1000);
  },
};

counter.start();

만약 function()을 썼다면 this는 window나 undefined를 가리켰을 겁니다. 하지만 화살표 함수는 상위 스코프인 counter 객체의 this를 유지합니다. 이 덕분에 비동기 함수나 이벤트 핸들러에서 특히 유용합니다.

 

객체 메서드에서의 주의사항

객체 안에서 메서드를 정의할 때는 함수 표현식과 화살표 함수의 차이를 반드시 인지해야 합니다.

const user = {
  name: "민호",

  sayHi() {
    console.log(this.name); // "민호"
  },

  sayHello: function () {
    console.log(this.name); //  "민호"
  },

  sayBye: () => {
    console.log(this.name); //undefined
  },
};

user.sayHi();
user.sayHello();
user.sayBye();

화살표 함수는 객체의 메서드로 쓰기에 적합하지 않습니다. 내부에서 this가 필요하다면 반드시 일반 함수나 축약형 메서드 문법을 사용해야 합니다.

 


언제 어떤 방식을 써야 할까?

함수 선언식이 더 좋은 경우

  • 전역적으로 쓰이는 공통 유틸 함수
  • 코드 가독성이 중요한 초기화 함수
  • 선언적 흐름을 표현하고 싶을 때

함수 표현식이 더 좋은 경우

  • 이벤트 핸들러, 콜백 함수
  • 클로저(closure)를 활용할 때
  • 동적으로 생성되는 함수
  • React 컴포넌트 안에서 내부적으로만 쓰이는 핸들러

정리

자바스크립트의 함수 선언식과 함수 표현식은 단순한 문법 차이가 아닙니다.

실행 시점,호이스팅 여부,this 바인딩 방식,스코프 처리 이 모든 것이 다르게 동작합니다.

따라서 두 방식을 “무엇이 더 낫다”로 단정하기보다는 코드 맥락에 맞게 선택하는 안목이 중요합니다.

React에서 이벤트 핸들러를 작성하거나, 비동기 로직을 다룰 때는 함수 표현식(특히 화살표 함수)이 더 편리합니다. 반면, 전역 유틸리티 함수나 모듈 단위 함수는 선언식으로 작성하는 편이 가독성과 유지보수성이 뛰어납니다.

결국 자바스크립트 개발자로서 중요한 것은 “둘 다 능숙하게 쓸 수 있고, 언제 어떤 방식을 택해야 하는지 판단할 수 있는 능력”입니다.

728x90
profile

blog.pisik.club

@pisik

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!