JavaScript 입문 5편 - 함수 만들기

똑같은 코드를 여러 번 쓰고 있다면? 함수로 만들어야 합니다. 함수는 코드를 재사용 가능한 덩어리로 만드는 거예요. 한번 만들어두면 필요할 때마다 불러 쓸 수 있죠.
저는 함수 이름 짓는 게 제일 어려웠어요. getUserData, fetchUserData, loadUserData… 뭐가 다른 거야? 지금은 “동사 + 명사” 패턴으로 통일해서 쓰니까 훨씬 낫더라고요.
함수가 뭔가요?
함수는 특정 작업을 수행하는 코드 묶음이에요.
// 함수 선언
function sayHello() {
console.log("안녕하세요!");
}
// 함수 호출
sayHello(); // 안녕하세요!
sayHello(); // 안녕하세요!
sayHello(); // 안녕하세요!
실행 결과:
한 번 만들어두면 몇 번이고 재사용할 수 있어요.
함수 선언 방법
1. function 키워드
function greet() {
console.log("환영합니다!");
}
greet(); // 환영합니다!
실행 결과:
2. 함수 표현식
const greet = function() {
console.log("환영합니다!");
};
greet(); // 환영합니다!
3. 화살표 함수 (ES6+)
const greet = () => {
console.log("환영합니다!");
};
greet(); // 환영합니다!
화살표 함수가 요즘 가장 많이 쓰여요. 짧고 간결하거든요.
매개변수와 인자
함수에 값을 전달할 수 있어요.
function greet(name) {
console.log(`안녕하세요, ${name}님!`);
}
greet("철수"); // 안녕하세요, 철수님!
greet("영희"); // 안녕하세요, 영희님!
실행 결과:
- 매개변수(parameter): 함수 선언 시 받을 값 (
name) - 인자(argument): 함수 호출 시 전달하는 값 (
"철수")
여러 매개변수
function add(a, b) {
console.log(a + b);
}
add(5, 3); // 8
add(10, 20); // 30
실행 결과:
기본값 설정
function greet(name = "손님") {
console.log(`안녕하세요, ${name}님!`);
}
greet("철수"); // 안녕하세요, 철수님!
greet(); // 안녕하세요, 손님님! (기본값 사용)
실행 결과:
반환값 (return)
함수가 결과를 돌려줄 수 있어요.
function add(a, b) {
return a + b; // 결과를 반환
}
let result = add(5, 3);
console.log(result); // 8
실행 결과:
return 이후의 코드는 실행되지 않아요.
function test() {
console.log("1");
return;
console.log("2"); // 실행 안 됨
}
test(); // 1만 출력
실행 결과:

화살표 함수 단축 문법
// 일반 형태
const add = (a, b) => {
return a + b;
};
// 한 줄이면 중괄호와 return 생략 가능
const add = (a, b) => a + b;
// 매개변수가 하나면 괄호도 생략 가능
const double = n => n * 2;
console.log(add(5, 3)); // 8
console.log(double(4)); // 8
실행 결과:
스코프 (유효 범위)
변수가 어디서 접근 가능한지를 결정하는 규칙이에요.
전역 스코프
let globalVar = "전역 변수";
function test() {
console.log(globalVar); // 접근 가능
}
test(); // 전역 변수
console.log(globalVar); // 전역 변수
실행 결과:
지역 스코프
function test() {
let localVar = "지역 변수";
console.log(localVar); // 접근 가능
}
test(); // 지역 변수
console.log(localVar); // 에러! 밖에서 접근 불가
블록 스코프 (let, const)
if (true) {
let x = 10;
const y = 20;
var z = 30;
}
console.log(x); // 에러! let은 블록 밖에서 접근 불가
console.log(y); // 에러! const도 마찬가지
console.log(z); // 30 (var는 블록 스코프 무시)
이래서 var 안 쓰는 거예요!
클로저 (Closure)
함수가 선언된 환경을 기억하는 거예요.
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
실행 결과:
count 변수가 함수 밖에서도 유지돼요. 이게 클로저입니다.
실용적인 예제:
function createGreeting(greeting) {
return function(name) {
return `${greeting}, ${name}!`;
};
}
const sayHello = createGreeting("Hello");
const sayHi = createGreeting("Hi");
console.log(sayHello("철수")); // Hello, 철수!
console.log(sayHi("영희")); // Hi, 영희!
실행 결과:
실전 예제
1. 계산기 함수
const calculator = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b
};
console.log(calculator.add(10, 5)); // 15
console.log(calculator.divide(10, 2)); // 5
실행 결과:
2. 배열 필터링
function filterEven(numbers) {
return numbers.filter(n => n % 2 === 0);
}
let nums = [1, 2, 3, 4, 5, 6];
console.log(filterEven(nums)); // [2, 4, 6]
실행 결과:
3. 검증 함수
function isValidEmail(email) {
return email.includes("@") && email.includes(".");
}
console.log(isValidEmail("test@gmail.com")); // true
console.log(isValidEmail("test")); // false
실행 결과:
4. 재사용 가능한 인사 함수
function createGreeter(greeting, punctuation = "!") {
return function(name) {
return `${greeting}, ${name}${punctuation}`;
};
}
const formal = createGreeter("Good morning", ".");
const casual = createGreeter("Hey");
console.log(formal("Mr. Kim")); // Good morning, Mr. Kim.
console.log(casual("철수")); // Hey, 철수!
실행 결과:
콜백 함수
다른 함수의 인자로 전달되는 함수예요.
function processArray(arr, callback) {
for (let item of arr) {
callback(item);
}
}
processArray([1, 2, 3], (num) => {
console.log(num * 2);
});
// 출력: 2, 4, 6
실행 결과:
배열 메서드에서 많이 씁니다.
let numbers = [1, 2, 3, 4, 5];
// map에 콜백 함수 전달
let doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
실행 결과:
자주 하는 실수
1. return 빠뜨리기
function add(a, b) {
a + b; // return 없으면 undefined 반환
}
console.log(add(5, 3)); // undefined
실행 결과:
2. 함수 호출 시 괄호 빠뜨리기
function greet() {
return "Hello!";
}
console.log(greet); // 함수 자체 출력
console.log(greet()); // "Hello!" (올바름)
실행 결과:
3. 화살표 함수에서 this 헷갈림
const obj = {
name: "철수",
sayHi: function() {
console.log(`Hi, ${this.name}`);
},
sayBye: () => {
console.log(`Bye, ${this.name}`); // undefined
}
};
obj.sayHi(); // Hi, 철수
obj.sayBye(); // Bye, undefined (화살표 함수는 this 바인딩 다름)
운영자 실전 노트
실제 프로젝트 진행하며 겪은 문제
- 여러 비동기 작업에서 콜백을 중첩해서 가독성 최악 → Promise 또는 async/await로 리팩터링
- 이벤트 핸들러에서 화살표 함수 사용 시 this가 window를 가리킴 → 일반 함수로 변경
이 경험을 통해 알게 된 점
- 콜백 지옥은 Promise.all()이나 async/await 패턴으로 평탄화할 수 있다
- 화살표 함수의 this는 렉시컬 스코프를 따르므로, 메서드나 이벤트 핸들러엔 일반 함수 사용
다음 단계
다음 글에서는 객체와 메서드를 배운다. 관련된 데이터와 함수를 하나로 묶어 관리하는 방법을 알아볼 예정이다.
함수는 작게 쪼갤수록 좋다. 한 함수가 20줄을 넘어가면 더 쪼갤 수 있는지 다시 본다. 그래야 나중에 수정할 때도 편하고, 테스트하기도 쉽다.
JavaScript 독학 가이드 시리즈:
← 블로그 목록으로