728x90
728x90
자바스크립트 클로저 완벽 가이드: 실무에서 만나는 문제 해결법 [예제 코드 포함]
"클로저는 자바스크립트 개발자라면 반드시 마주치게 되는 개념입니다. 면접에서도 자주 나오고, 실제 개발 과정에서도 수시로 마주치죠. 하지만 제대로 이해하지 못하면 메모리 누수나 성능 문제를 일으킬 수 있습니다. 이 글에서는 클로저의 개념부터 실무에서 마주치는 문제들과 그 해결 방법까지 상세히 다뤄보겠습니다."
📚 목차
1. 클로저의 개념과 기본 원리
클로저(Closure)는 함수와 그 함수가 선언된 렉시컬 환경의 조합입니다. 쉽게 말해, 함수가 자신이 생성될 때의 환경을 기억하는 것이죠.
1.1 기본 예제로 이해하기
function createCounter() {
let count = 0; // 프라이빗 변수
return function() {
return ++count; // 외부 스코프의 변수에 접근
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
이 코드에서 반환된 함수는 자신이 생성될 때의 count
변수를 계속 기억하고 있습니다. 이것이 바로 클로저의 가장 기본적인 예시입니다.
1.2 클로저가 유용한 이유
- 데이터 프라이버시
- 변수를 외부에서 직접 접근할 수 없게 캡슐화
- 정보 은닉 구현 가능
- 상태 유지
- 함수가 호출될 때마다 이전 상태 기억
- 함수형 프로그래밍에서 중요한 역할
- 모듈화
- 관련 기능을 하나의 모듈로 묶기 가능
- 전역 네임스페이스 오염 방지
2. 클로저의 동작 원리와 실행 컨텍스트
2.1 렉시컬 스코핑
const x = 'global';
function outer() {
const x = 'outer';
function inner() {
// inner 함수는 outer의 x에 접근 가능
console.log(x); // 'outer' 출력
}
return inner;
}
const innerFn = outer();
innerFn(); // 'outer' 출력
2.2 실행 컨텍스트와 스코프 체인 도식화
전역 실행 컨텍스트
│
├── x: 'global'
│
└── outer 함수 실행 컨텍스트
│
├── x: 'outer'
│
└── inner 함수 실행 컨텍스트
└── 스코프 체인으로 outer의 x에 접근
3. 실무에서 자주 발생하는 클로저 문제
3.1 메모리 누수 문제
function createLargeData() {
const largeData = new Array(1000000).fill('🐘');
return function() {
console.log(largeData.length);
};
}
// 이 경우 largeData는 계속 메모리에 남아있음
const dataLogger = createLargeData();
3.2 이벤트 리스너 메모리 누수
function setupHandler(element) {
const data = new Array(1000000);
element.addEventListener('click', function() {
// data 배열 전체가 메모리에 계속 남아있음
console.log(data.length);
});
}
4. 문제 해결 가이드
4.1 메모리 누수 방지하기
class ResourceManager {
#resources = new WeakMap();
createResource() {
const resource = new Array(1000000);
const wrapper = {
use: () => {
if (this.#resources.has(wrapper)) {
console.log('리소스 사용');
}
},
dispose: () => {
this.#resources.delete(wrapper);
}
};
this.#resources.set(wrapper, resource);
return wrapper;
}
}
// 사용 예시
const manager = new ResourceManager();
const resource = manager.createResource();
resource.use();
resource.dispose(); // 메모리 해제
5. 실전 활용 사례
5.1 React 커스텀 훅에서의 클로저
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
// 클로저를 활용한 카운터 로직
const increment = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return [count, increment];
}
// 사용 예시
function Counter() {
const [count, increment] = useCounter(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>증가</button>
</div>
);
}
6. 성능 최적화 전략
6.1 메모리 사용량 최적화
function createOptimizedResource() {
let resource = new WeakRef(new Array(1000000));
return {
use() {
const data = resource.deref();
if (data) {
console.log('리소스 사용 가능');
} else {
console.log('리소스 해제됨');
}
}
};
}
7. 자주 나오는 면접 질문
- 클로저란 무엇인가요?
- 함수와 그 함수가 선언된 렉시컬 환경의 조합
- 외부 변수를 기억하고 접근할 수 있는 함수
- 클로저의 장단점은 무엇인가요?
- 장점:
- 데이터 프라이버시
- 상태 유지
- 모듈화 가능
- 단점:
- 메모리 누수 가능성
- 성능 영향
- 장점:
- 클로저를 사용하는 실제 사례는?
- React의 훅
- 이벤트 핸들러
- 데이터 캐싱
마무리
클로저는 자바스크립트의 강력한 기능이지만, 제대로 이해하고 사용하지 않으면 성능 문제를 일으킬 수 있습니다. 이 글에서 다룬 개념과 해결 방법들을 실무에 적용하면서, 더 나은 코드를 작성하시기 바랍니다.
다음 시리즈 예고
- 자바스크립트 프로토타입 깊이 파헤치기
- 이벤트 루프와 비동기 처리의 모든 것
- this 바인딩 마스터하기
관련 자료
- 클로저 예제 GitHub 저장소
- 클로저 관련 코딩테스트 문제 모음
- MDN 클로저 문서
여러분은 실무에서 클로저와 관련하여 어떤 경험을 하셨나요?
댓글로 여러분의 경험과 해결 방법을 공유해주세요! 💬
다음 포스팅에서 다룰 주제를 투표해주세요:
- 프로토타입 체인 깊이 파헤치기
- 이벤트 루프 동작 원리
- 모듈 시스템 비교 분석
#JavaScript #클로저 #프론트엔드개발 #웹개발 #코딩테스트 #기술면접 #React
728x90
300x250
'Javascript' 카테고리의 다른 글
[Javascript; 자바스크립트] Promise.allSettled 완벽 가이드: 병렬 비동기 처리의 새로운 패러다임 (0) | 2024.10.29 |
---|---|
[Javascript; 자바스크립트] 배열 조작의 기본기: 자바스크립트 push, pop, shift, unshift 사용법 (0) | 2024.10.21 |
[Javascript; 자바스크립트] 자바스크립트에서 세미콜론 사용 가이드 (0) | 2024.09.09 |
[Javascript; 자바스크립트] 천 단위 쉼표 콤마 컴마 내장 함수 toLocaleString() (0) | 2023.06.29 |
[Javascript; 자바스크립트] 비밀번호 정규식 (0) | 2022.09.28 |