자바스크립트 함수 기초 - JavaScript 시리즈 #4

자바스크립트 함수 기초

앞선 글에서 변수와 데이터 타입, 조건문과 반복문을 배웠다면, 이번엔 코드를 더 구조화하고 재사용할 수 있게 해주는 함수를 배워볼 거다. 함수는 자바스크립트에서 가장 중요한 개념 중 하나로, 코드를 묶어서 특정 작업을 수행하게 하고 필요할 때마다 호출할 수 있게 해준다. 이걸 잘 익히면 앞으로 복잡한 프로그램도 훨씬 쉽게 짤 수 있다.

내가 처음 코딩을 배울 때 함수를 몰라서 같은 코드를 반복해서 쓰곤 했는데, 함수를 배우고 나니 코드가 간결해지고 유지보수도 쉬워졌다. 이번 글에선 함수의 정의와 선언 방법, 매개변수와 반환값, 스코프와 클로저의 기본적인 개념을 다룰 거다. 천천히 따라오면서 직접 콘솔이나 HTML 파일에서 실행해보면 함수의 힘을 느낄 수 있을 거다. 함수는 단순히 코드를 줄이는 도구를 넘어, 프로그램의 논리를 체계적으로 정리하는 데 핵심적인 역할을 한다.

함수를 배우면 이전에 다뤘던 조건문과 반복문을 더 유연하게 사용할 수 있다. 예를 들어, 특정 조건에 따라 반복 작업을 해야 할 때 함수로 묶어서 호출하면 코드가 훨씬 깔끔해진다. 이번 포스팅에서 함수의 기본부터 실습까지 상세히 다룰 테니, 자바스크립트의 기본기를 한 단계 더 끌어올릴 준비를 하자.

함수란 무엇인가?

함수는 특정 작업을 수행하는 코드 블록을 이름으로 묶어서 필요할 때마다 호출할 수 있게 한 거다. 자바스크립트에서 함수는 코드를 재사용하고, 프로그램을 모듈화하며, 가독성을 높이는 데 필수적이다. 함수 없이 코드를 짜면 같은 작업을 반복해서 작성해야 하고, 나중에 수정할 때도 일일이 찾아 바꿔야 한다. 하지만 함수를 쓰면 한 번 정의해놓고 여러 번 호출할 수 있어서 효율적이다.

예를 들어, 숫자를 더하는 작업을 여러 번 해야 한다고 해보자. 함수 없이 매번 더하기 코드를 쓰는 대신, 함수로 만들어 놓으면 필요할 때마다 호출해서 쓸 수 있다. 이런 방식은 코드를 줄이는 것뿐만 아니라, 실수를 줄이고 유지보수를 쉽게 해준다. 내가 처음 함수를 배울 때 단순히 "코드를 묶는 거구나" 정도로 생각했는데, 쓰다 보니 프로그램의 전체 구조를 잡는 데도 큰 도움이 됐다.

자바스크립트에서 함수는 객체로 취급돼서 변수에 할당하거나, 다른 함수에 전달하거나, 함수에서 반환할 수도 있다. 이런 유연함 때문에 함수는 자바스크립트의 핵심적인 특징 중 하나로 꼽힌다. 이제 함수를 어떻게 정의하고 사용하는지 하나씩 알아보자.

함수 선언 방법

자바스크립트에서 함수를 선언하는 방법은 크게 세 가지가 있다: 함수 선언문, 함수 표현식, 화살표 함수다. 각각의 특징과 사용법을 예제와 함께 살펴보자.

1. 함수 선언문(Function Declaration)

가장 기본적인 함수 선언 방식으로, function 키워드를 사용한다. 구조는 간단하다:

function sayHello() {
    console.log("안녕하세요!");
}
sayHello(); // "안녕하세요!"

위 코드는 sayHello라는 함수를 정의하고 호출한다. 함수 선언문은 코드 어디서든 호출할 수 있는데, 이는 자바스크립트의 호이스팅(Hoisting) 덕분이다. 호이스팅 때문에 함수 선언문은 파일 맨 위로 끌어올려진 것처럼 동작한다:

sayHello(); // "안녕하세요!"
function sayHello() {
    console.log("안녕하세요!");
}

내가 처음 이걸 보고 신기했는데, 함수 선언문은 어디서 호출하든 문제없어서 편리하다. 하지만 나중에 변수 스코프와 관련된 문제를 피하려면 코드 순서를 잘 정리하는 게 좋다.

2. 함수 표현식(Function Expression)

함수를 변수에 할당하는 방식이다. 함수 자체는 이름이 없고(익명 함수), 변수로 호출한다:

const greet = function() {
    console.log("반갑습니다!");
};
greet(); // "반갑습니다!"

함수 표현식은 선언 후에만 호출할 수 있다. 호이스팅이 안 돼서 함수 선언문과 다르게 순서가 중요하다:

greet(); // 에러: greet is not defined
const greet = function() {
    console.log("반갑습니다!");
};

내가 이 방식을 좋아하는 이유는 변수처럼 함수를 관리할 수 있어서 코드가 깔끔해진다는 점이다. 특히 변수 스코프를 명확히 하고 싶을 때 유용하다.

3. 화살표 함수(Arrow Function)

ES6에서 추가된 간결한 선언 방식이다. =>를 사용해서 정의한다:

const sayHi = () => {
    console.log("안녕!");
};
sayHi(); // "안녕!"

화살표 함수는 더 짧고 간단해서 한 줄일 땐 중괄호와 return도 생략할 수 있다:

const double = x => x * 2;
console.log(double(5)); // 10

내가 화살표 함수를 처음 썼을 때 코드가 너무 간결해져서 놀랐다. 특히 짧은 콜백 함수에서 빛을 발한다. 하지만 this 바인딩이 다르게 동작해서 주의해야 한다(나중에 설명).

매개변수와 반환값

함수는 입력(매개변수)을 받아서 작업을 수행하고, 결과를 돌려줄(반환값) 수 있다. 이게 함수의 진짜 힘이다.

매개변수(Parameter)

함수를 호출할 때 전달하는 값을 매개변수로 받는다:

function add(a, b) {
    console.log(a + b);
}
add(3, 5); // 8

매개변수는 여러 개 쓸 수 있고, 기본값도 설정할 수 있다(ES6부터):

function greet(name = "익명") {
    console.log("안녕, " + name + "!");
}
greet("홍길동"); // "안녕, 홍길동!"
greet(); // "안녕, 익명!"

내가 처음 매개변수 배울 때 값을 안 넣으면 에러 나는 줄 알았는데, 기본값 덕분에 유연하게 쓸 수 있다.

반환값(Return Value)

return으로 결과를 돌려준다:

function multiply(a, b) {
    return a * b;
}
let result = multiply(4, 5);
console.log(result); // 20

return을 만나면 함수가 종료되고 값을 반환한다. 내가 처음엔 console.log만 썼는데, return을 쓰니까 함수 결과를 변수에 저장해서 재활용할 수 있었다.

함수 스코프와 변수

함수 안에서 선언한 변수는 함수 스코프를 가진다. 함수 밖에서 접근할 수 없다:

function test() {
    let localVar = "안녕";
    console.log(localVar); // "안녕"
}
test();
console.log(localVar); // 에러: localVar is not defined

하지만 함수 밖 변수는 함수 안에서 접근 가능하다:

let globalVar = "전역";
function test() {
    console.log(globalVar); // "전역"
}
test();

내가 처음 스코프 때문에 변수가 안 보일 때 당황했는데, 이걸 이해하니까 코드가 꼬이는 걸 막을 수 있었다.

클로저의 기본 개념

클로저는 함수가 외부 변수를 기억하는 현상이다. 간단한 예제를 보자:

function outer() {
    let count = 0;
    function inner() {
        count++;
        console.log(count);
    }
    return inner;
}
let counter = outer();
counter(); // 1
counter(); // 2

inner 함수가 count를 기억해서 계속 증가시킨다. 내가 처음 클로저 배울 때 신기했는데, 상태를 유지할 때 유용하다.

실습 예제

함수를 활용한 실습을 해보자:

function calculateGrade(score) {
    if (score >= 90) {
        return "A";
    } else if (score >= 80) {
        return "B";
    } else {
        return "C";
    }
}
console.log(calculateGrade(95)); // "A"
console.log(calculateGrade(85)); // "B"

function printNumbers(n) {
    for (let i = 1; i <= n; i++) {
        console.log(i);
    }
}
printNumbers(3); // 1, 2, 3

이렇게 조건문과 반복문을 함수로 묶으면 재사용성이 높아진다.

주의할 점

함수 안 변수는 외부에서 접근 못 하니 스코프 잘 확인하자. 화살표 함수에서 this가 다르게 동작하니 주의해야 한다. 매개변수 기본값을 설정할 때 순서도 중요하다.

결론

이번 포스팅에서 자바스크립트 함수의 기초를 다뤘다. 함수 선언, 매개변수, 반환값, 스코프, 클로저까지 배웠으니 이제 코드를 더 구조화할 수 있다. 다음 글에선 함수를 더 깊이 파고들어 고급 개념을 알아보자.

+ Recent posts