함수는 '이름 붙은 코드 블록'이다
자바스크립트에서 어떤 로직을 하나로 묶어 이름을 붙이고 재사용하고 싶을 때 쓰는 게 바로 함수다. 가장 오래됐으면서도 가장 직관적인 방식이 함수 선언문(function declaration) 인데, function 키워드 뒤에 함수 이름을 붙이는 형태다.
코드를 위에서 아래로 하나씩 뜯어보면 이렇습니다.
function은 함수 선언문을 시작하는 키워드입니다.greet는 함수 이름이고요.(name)은 매개변수 목록 — 함수가 받는 입력값입니다.- 중괄호로 감싼 블록이 함수의 본문(body)입니다.
greet("Ada")는 함수 호출 입니다. JavaScript가name에"Ada"를 바인딩한 상태로 본문을 실행하죠.
함수를 정의한다고 해서 바로 실행되지는 않습니다. 호출해야 실행돼요.
매개변수(parameter)와 인자(argument)
매개변수(parameter) 는 함수를 정의할 때 괄호 안에 적는 이름을 가리키고, 인자(argument) 는 함수를 호출할 때 실제로 넘기는 값을 뜻합니다. 평소 대화에서는 둘을 섞어 써도 보통 알아듣지만, 에러 메시지를 읽을 때는 이 구분이 꽤 쓸모가 있습니다.
여기서 base와 exponent는 매개변수(parameter)이고, 2와 10은 인자(argument)입니다. 자바스크립트는 순서대로 바인딩합니다. 즉, 첫 번째 인자는 첫 번째 매개변수에, 그다음 인자는 그다음 매개변수에 전달됩니다.
다른 언어와 달리 자바스크립트는 인자 개수가 맞지 않아도 에러를 내지 않습니다. 모자라면 undefined가 들어가고, 남으면 조용히 무시해 버리죠. 유연하긴 하지만 가끔 함정이 되기도 합니다. 기본값(default parameter)이나 나머지 매개변수(rest parameter)는 이후 문서에서 다시 살펴보겠습니다.
return 문으로 값 돌려주기
console.log는 화면에 출력만 할 뿐이지만, return 문은 호출한 쪽에 값을 돌려줘서 그 값을 다시 활용할 수 있게 해줍니다.
return이 없으면 함수는 undefined를 반환합니다:
return을 만나면 함수는 그 즉시 종료됩니다. 그래서 본격적인 로직에 들어가기 전에 예외 케이스를 걸러낼 때는 보통 아래처럼 early return 패턴을 씁니다.
조기 리턴을 활용하면 본문이 if/else로 된 피라미드 덩어리가 되는 걸 막을 수 있습니다.
호이스팅: 선언하기 전에 호출해도 된다고?
다른 언어를 쓰다 자바스크립트로 넘어온 분들이 가장 당황하는 부분 중 하나입니다. 함수 선언문은 호이스팅 되거든요. 자바스크립트는 코드를 실행하기 전에 함수 선언을 해당 스코프의 맨 위로 끌어올립니다. 그래서 함수를 선언한 줄보다 위쪽에서 먼저 호출해도 문제없이 동작합니다:
이 코드는 문제없이 실행됩니다. 엔진은 실행에 앞서 스코프를 훑어 square를 함수로 먼저 등록해 두고, 그다음에야 문장을 위에서 아래로 한 줄씩 실행합니다.
이건 함수 선언문과 다른 방식(함수 표현식, 화살표 함수)의 실질적인 동작 차이입니다. 함수 표현식이나 화살표 함수는 변수처럼 호이스팅되기 때문에 이름 은 알려져 있어도 값은 해당 줄이 실행되기 전까지 할당되지 않습니다. 이 차이는 바로 이어서 더 자세히 다룹니다.
사실 대부분의 스타일 가이드는 함수를 호출하기 전에 먼저 정의하라고 권장합니다. 호이스팅은 어디까지나 안전장치일 뿐, 코딩 스타일로 의존할 만한 기능은 아닙니다.
함수 선언문 vs 함수 표현식 차이
함수 선언문 은 그 자체로 독립된 문장입니다. 반면 함수 표현식 은 값이 들어갈 자리에 등장하며, 보통 할당 연산자의 오른쪽에 오는 경우가 가장 많습니다.
둘 다 호출 가능한 함수를 만들어내지만, 몇 가지 차이가 있습니다.
- 함수 선언문은 통째로 호이스팅됩니다. 반면 함수 표현식은 할당된 변수의 호이스팅 규칙을 따릅니다(
const와let은 해당 줄이 실행되기 전까지 일시적 사각지대(TDZ)에 갇혀 있죠). - 선언문은 이름이 반드시 있어야 하지만, 표현식은 익명이어도 됩니다. 다만 이름을 붙여두면 스택 트레이스를 읽을 때 도움이 됩니다.
- 선언문은 아무 곳에나 쓸 수 있는 게 아닙니다. strict 모드에서
if블록 안에function foo() {}를 쓰면 엔진마다 동작이 제각각이니, 그럴 땐 함수 표현식을 쓰세요.
파일 최상단에 두는 보조 함수는 대부분 선언문이 자연스럽게 읽힙니다. 반대로 인자로 넘기거나 객체 프로퍼티에 할당하는 경우에는 함수 표현식(또는 화살표 함수)을 쓰는 게 일반적입니다.
함수 이름 짓기와 스타일
함수 이름은 그 함수가 무슨 일을 하는지에 대한 약속입니다. 몇 글자 더 들여서 설명력 있는 이름을 고르는 수고는, 누군가 그 코드를 처음 읽는 순간 바로 보상으로 돌아옵니다.
몇 가지 관례는 익혀두면 좋습니다.
- 함수 이름은 동사로 짓습니다:
fetchProfile,computeTotal,sendEmail. camelCase를 사용합니다 — 자바스크립트에서는 이게 표준입니다.- 불리언을 반환하는 함수는 보통
is,has,can으로 시작합니다:isValid,hasAccess,canEdit.
이렇게 지으면 함수를 호출하는 부분이 마치 문장처럼 자연스럽게 읽힙니다.
자바스크립트 함수 예제로 정리하기
지금까지 살펴본 요소들 — 매개변수, 조기 반환, 의미가 드러나는 이름 — 을 한 번에 모아 보겠습니다.
선언문 하나, 가드 절 하나, 명확한 return 하나. 앞으로 작성할 함수 대부분이 이 모양을 벗어나지 않습니다.
다음: 화살표 함수
함수 선언문이 기본기라면, 요즘 자바스크립트에서는 더 짧은 문법인 화살표 함수(arrow function)를 훨씬 자주 씁니다. 특히 콜백이나 한 줄짜리 함수에서 그렇죠. 생김새도 다르고 this를 다루는 방식도 다른데, 바로 다음 페이지에서 이 이야기를 이어가겠습니다.
자주 묻는 질문
자바스크립트에서 함수는 어떻게 선언하나요?
function 키워드 뒤에 함수 이름, 매개변수를 담는 괄호, 그리고 중괄호 블록을 적어주면 됩니다. 예를 들어 function greet(name) { return 'Hi, ' + name; } 이런 식이죠. 호출할 때는 greet('Ada')처럼 이름 뒤에 괄호를 붙이면 됩니다.
자바스크립트의 함수 호이스팅이란 무엇인가요?
함수 선언문은 코드가 실행되기 전에 해당 스코프의 최상단으로 끌어올려집니다. 그래서 함수가 정의된 위치보다 위쪽에서 호출해도 정상적으로 동작하죠. 단, 이건 function 선언문에만 해당됩니다. let이나 const에 할당한 함수 표현식이나 화살표 함수는 이런 식으로 호이스팅되지 않아요.
함수 선언문과 함수 표현식은 어떻게 다른가요?
함수 선언문은 function greet() {}처럼 그 자체로 하나의 문장이 되고, 호이스팅 대상입니다. 반면 함수 표현식은 const greet = function() {}처럼 함수를 변수에 할당하는 형태이고, 일반 변수의 호이스팅 규칙을 따릅니다. 선언문은 기본적으로 이름이 있지만, 표현식은 익명으로 쓰는 경우가 많아요.