자바스크립트의 클로저(Closure)

홍태극·2023년 8월 7일
0

자바스크립트

목록 보기
1/3

자바스크립트 클로저(Closure)

자바스크립트를 좀 더 깊게 파다 보면 '클로저(Closure)'라는 개념을 만나게 되죠. 뭔가 좀 어려운 용어 같기도 하고... 이게 도대체 뭘까요? 🤔

클로저는 자바스크립트의 아주 흥미로운 특징인데요, 함수 안에서 만든 또 다른 함수(내부 함수)가 바깥 함수의 변수나 매개변수에 접근할 수 있게 해주는 거예요. 더 신기한 건, 내부 함수는 자기가 태어난 환경(외부 함수)의 변수들을 마치 사진 찍듯이 기억하고 있다가, 외부 함수 실행이 끝나고 사라진 뒤에도 계속 그 변수들을 사용할 수 있다는 점이에요! ✨

클로저는 기본적으로 함수와 그 함수가 태어난 환경(렉시컬 환경)의 조합이라고 생각하면 이해하기 쉬워요. 자바스크립트는 함수가 어디서 선언되었는지를 기준으로 사용할 수 있는 변수를 결정하는데 (이걸 렉시컬 스코핑이라고 해요), 클로저는 바로 이 특징 덕분에 가능하답니다.

🤔 클로저는 어떻게 작동하는 걸까요?

함수가 다른 함수 안에서 정의되고, 그 내부 함수가 밖으로 반환될 때 마법 같은 일이 일어나요. 내부 함수는 마치 '기억 가방'🎒을 챙겨서 나가는데요, 이 가방 안에는 자기가 태어난 환경(외부 함수)의 변수 정보들이 고스란히 담겨 있어요.

이렇게 함수와 그 함수의 '기억 가방'(스코프 정보)을 합쳐서 부르는 게 바로 클로저예요. 내부 함수가 외부 함수의 지역 변수를 참조할 때 클로저가 만들어지고, 외부 함수가 실행을 마친 후에도 내부 함수는 이 '기억 가방' 덕분에 외부 함수의 변수에 계속 접근할 수 있는 거죠.

🔢 클로저로 카운터 만들기 예제

말로만 들으면 좀 헷갈릴 수 있으니, 클로저를 활용한 간단한 카운터 예제를 한번 볼게요. 이게 클로저의 강력함을 보여주는 대표적인 예시거든요!

// 카운터를 만들어주는 함수
function createCounter(initValue) {
  let value = initValue; // 외부 함수의 지역 변수 (이걸 기억할 거예요!)

  // 내부 함수들 정의
  function plusOne() {
    value += 1; // 외부 함수의 value에 접근!
  }
  function minusOne() {
    value -= 1; // 외부 함수의 value에 접근!
  }
  function changeValue(_value) {
    value = _value; // 외부 함수의 value에 접근!
  }
  function getValue() {
    return value; // 외부 함수의 value에 접근!
  }

  // 내부 함수들을 객체에 담아서 밖으로 내보내기 (반환)
  // 이 함수들이 바로 클로저가 되는 거예요!
  return {
    plusOne,
    minusOne,
    changeValue,
    getValue
  };
}

// createCounter 함수를 실행해서 카운터 객체를 얻어요.
// 이때 createCounter 함수 자체는 실행이 끝났지만...
const { plusOne, minusOne, changeValue, getValue } = createCounter(0); // 초기값 0

console.log(getValue()); // 0 (초기값 잘 나오죠?)

plusOne(); // 내부 함수 plusOne 실행! createCounter의 value를 1 증가시켜요.
console.log(getValue()); // 1 (오! 값이 유지되고 바뀌었네요?)

changeValue(23); // 내부 함수 changeValue 실행! value를 23으로 바꿔요.
console.log(getValue()); // 23 (잘 바뀌었죠?)

createCounter 함수는 실행이 끝나서 사라졌는데도, 반환된 plusOne, minusOne, changeValue, getValue 함수들은 여전히 createCounter 안에 있던 value 변수를 기억하고 접근할 수 있어요. 이게 바로 클로저의 힘이죠! 마치 value 변수가 이 함수들만의 비밀 변수가 된 것 같아요. 🤫

🚀 클로저는 어디에 쓸 수 있을까요?

클로저의 이런 특징 덕분에 정말 다양한 곳에서 유용하게 활용될 수 있어요.

  • 데이터 은닉 (Data Hiding)
    위 카운터 예제처럼, 외부에서 직접 접근할 수 없는 '비공개 변수'를 만들 수 있어요. 객체 지향 프로그래밍의 캡슐화랑 비슷하죠? value 변수는 오직 반환된 함수들을 통해서만 제어할 수 있어요.

  • 상태 유지 (State Maintenance)
    함수가 실행될 때마다 초기화되지 않고, 이전 상태를 기억해야 할 때 클로저를 유용하게 쓸 수 있어요. 전역 변수를 쓰지 않고도 상태를 안전하게 관리할 수 있죠.

  • 코드 모듈화 (Code Modularization)
    관련된 함수와 데이터를 묶어서 독립적인 모듈처럼 만들 수 있어요. 재사용성도 높아지고요!

👉 화살표 함수에서도 클로저는 똑같아요!

"혹시 화살표 함수( => )를 쓰면 클로저가 다르게 동작하나요?" 라고 생각할 수도 있는데요, 아니에요! 화살표 함수에서도 클로저는 똑같이 적용된답니다. 화살표 함수도 자기가 태어난 환경(렉시컬 스코프)을 기억하는 렉시컬 스코핑 규칙을 따르거든요. (물론 this 키워드 동작 방식은 좀 다르지만, 클로저 자체는 같아요!)

// 화살표 함수로 곱셈 함수 만들기
let multiplier = factor => { // 외부 함수 (화살표 함수)
  // 내부 함수 (화살표 함수) 반환! 이 함수가 클로저가 돼요.
  return number => {
    // 외부 함수의 factor 변수를 기억하고 접근해요!
    return number * factor;
  };
};

let double = multiplier(2); // factor가 2인 클로저 함수 생성!
let triple = multiplier(3); // factor가 3인 클로저 함수 생성!

console.log(double(5)); // 10 (5 * 2)
console.log(triple(5)); // 15 (5 * 3)

multiplier 함수가 반환하는 내부 화살표 함수는 multiplier가 실행될 때 전달받은 factor 값을 정확히 기억하고 있죠? 클로저는 함수의 형태(function이든 =>든)와 상관없이 잘 동작해요!

✨ 마무리하며

클로저는 자바스크립트의 정말 중요하고 강력한 개념 중 하나예요. 처음엔 조금 어렵게 느껴질 수 있지만, 함수가 자신이 태어난 환경을 '기억'한다는 핵심 아이디어를 이해하면 코드를 보는 눈이 확 달라질 거예요!

혹시 면접 같은 곳에서 클로저에 대해 물어본다면, 이렇게 한번 설명해보세요. "클로저는 함수 안의 다른 함수가 바깥 함수의 변수들을 기억해서 계속 사용할 수 있게 해주는 기능이에요!" 라고요. 😉

클로저를 잘 활용하면 데이터를 안전하게 숨기고, 상태를 깔끔하게 관리하고, 코드를 더 효율적이고 모듈적으로 만들 수 있답니다. 꼭 한번 직접 코드로 만들어보면서 클로저와 친해져 보세요! 👍

0개의 댓글