자바스크립트 - 클로저

안녕하세요, 미래의 코딩 슈퍼스타들! ? 오늘 우리는 자바스크립트 클로저의 세계에 흥미로운 여정을 떠납니다. 그 이름이 조금 무서워 보일 수 있지만 걱정 마세요 - 이 튜토리얼이 끝나면 당신은 클로저의 전문가가 될 것입니다! 좋아하는 음료를 한 잔 마시고 편안하게 앉아 따라와 보세요!

JavaScript - Closures

클로저는 무엇인가요?

마법의 상자를 생각해 보세요. 그 안에 들은 모든 것을 기억하는 상자예요. 자바스크립트에서 클로저는 바로 그런 것입니다!

클로저는 외부(포함된) 렉시컬 스코프의 변수에 접근할 수 있는 함수로, 외부 함수가 반환된 후에도 그 값을 기억합니다. 마치 함수가 필요할 때마다 사용할 수 있는 작은 배낭을 메고 다니는 것 같아요.

간단한 예를 보겠습니다:

function outerFunction(x) {
let y = 10;
function innerFunction() {
console.log(x + y);
}
return innerFunction;
}

let closure = outerFunction(5);
closure(); // 출력: 15

이 예제에서 innerFunction은 클로저입니다. outerFunction이 실행이 끝난 후에도 xy의 값을 기억합니다.

렉시컬 스코핑

클로저에 더 깊이 다기 전에 렉시컬 스코핑을 이해해야 합니다. 이 이름은 복잡해 보이지만, 단순히 함수가 외부 스코프의 변수에 접근할 수 있다는 것을 의미합니다.

let name = "Alice";

function greet() {
console.log("Hello, " + name + "!");
}

greet(); // 출력: Hello, Alice!

이 예제에서 greetname 변수에 접근할 수 있어서 렉시컬 스코핑 덕분입니다. 마치 greet가 주변 환경을 볼 수 있는 것처럼요.

중첩 함수

클로저는 종종 중첩 함수와 관련이 있습니다. 예제를 보겠습니다:

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

let counter = outer();
counter(); // 출력: 1
counter(); // 출력: 2

이 예제에서 innerouter 안에 중첩되어 있습니다. 마법이 일어나는 이유는 inner가 외부 스코프의 count 변수를 기억하기 때문입니다.

반환 함수

자바스크립트의 멋진 점 중 하나는 함수가 다른 함수를 반환할 수 있다는 점입니다. 이는 클로저의 중요한 측면입니다.

function multiplier(x) {
return function(y) {
return x * y;
};
}

let double = multiplier(2);
console.log(double(5)); // 출력: 10
console.log(double(3)); // 출력: 6

이 예제에서 multiplierx의 값을 기억하는 함수를 반환합니다. 이 반환된 함수는 클로저입니다.

카운터의 딜레마

클로저가 해결할 수 있는 일반적인 문제를 보겠습니다:

function createCounter() {
let count = 0;
return {
increment: function() {
count++;
},
getCount: function() {
return count;
}
};
}

let counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 출력: 2

이 예제에서 클로저는 우리에게 사적인 변수(count)를 만들어주며, 제공된 메서드를 통해만 접근할 수 있습니다.

예제: 자바스크립트 클로저

우리는 이해를 더욱 확고히하기 위해 더 복잡한 예제를 보겠습니다:

function makeAdder(x) {
return function(y) {
return x + y;
};
}

let add5 = makeAdder(5);
let add10 = makeAdder(10);

console.log(add5(2));  // 출력: 7
console.log(add10(2)); // 출력: 12

이 예제에서 makeAdderx의 값을 기억하는 클로저를 생성합니다. 다양한 사전 설정된 값을 가진 여러 가지 추가 함수를 만들 수 있습니다.

예제

클로저의 또 다른 실용적인 예제를 보겠습니다:

function createGreeter(greeting) {
return function(name) {
console.log(greeting + ", " + name + "!");
};
}

let greetHello = createGreeter("Hello");
let greetHi = createGreeter("Hi");

greetHello("Alice"); // 출력: Hello, Alice!
greetHi("Bob");      // 출력: Hi, Bob!

이 예제는 클로저를 사용하여 맞춤형 함수를 만드는 방법을 보여줍니다.

클로저의 이점

클로저는 다음과 같은 몇 가지 이점을 제공합니다:

  1. 데이터 프라이버시
  2. 함수 팩토리
  3. 상태 유지

이를 표로 정리해 보겠습니다:

이점 설명 예제
데이터 프라이버시 클로저는 사적인 변수를 만들 수 있습니다 function counter() { let count = 0; return { increment: () => ++count, getValue: () => count }; }
함수 팩토리 사전 설정된 매개변수를 가진 함수를 생성합니다 function multiply(x) { return (y) => x * y; }
상태 유지 함수 호출 간 데이터를 유지합니다 function createGame() { let score = 0; return { addPoint: () => ++score, getScore: () => score }; }

그렇게 해서 우리는 클로저의 세계를 여행했습니다. 기본부터 고급 개념까지! 기억하시기 바랍니다, 클로저를 마스터하려면 연습이 필요합니다. 즉시 이해가 되지 않는다면 낙담하지 마세요 - 계속 코딩하고 실험을 해보세요, 그러면 곧 클로저의 힘을 제대로 활용할 수 있을 것입니다! ?‍♂️✨

Credits: Image by storyset