일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 성능개선
- git
- reduce
- Where
- 야놀자x패스트캠퍼스
- sqld 자격증 시험
- 퍼블리셔 이직후기
- sqld 55회
- 부트캠프
- 국비지원
- 야놀자 fe 1기
- 패스트캠퍼스 부트캠프
- 프론트엔드부트캠프후기
- Filter
- 리액트오류
- firebase rules
- js CRUD
- 패스트캠퍼스
- TypeScript
- 국비지원취업
- css 꿀팁
- promise 비동기처리
- Firebase
- map
- react hook
- 부트캠프 취업후기
- foreach
- 2024 sqld
- 프론트엔드개발자
- github
- Today
- Total
Tech is created to fix problem
[Javascript 알짜개념] 가비지 컬렉션, 클로저 함수 본문
가비지 컬렉션 (GC, Garbage Collection, 쓰레기 수집)
- 자바스크립트의 메모리 관리 방법으로 자바스크립트 엔진이 자동으로 데이터가 할당된 메모리에서 더 이상 사용되지 않는 데이터를 해제하는 것을 말한다.
- 가비지 컬렉션은 개발자가 직접 강제 실행하거나 컨트롤할 수 없다.
예시를 통해 알아보자
let a = { x:1 }
let b = a
b.x = 2
console.log(b); //{ x:2 }
console.log(a); //{ x:2 }
가비지 컬렉션이 메모리를 순회하다가 M2 를 발견했을 때 더 이상 사용되지 않는 데이터로 판단이 되면 제거한다.
클로저
- 함수가 선언할 때의 유효범위(렉시컬 범위)를 기억하고 있다가 함수가 외부에서 호출될 때 그 유효범위의 특정 변수를 참조할 수 있는 개념을 말한다.
function createCount(){
// 전역변수에 있는 것보다 여기에 넣어주는 것이 가독성도 좋음
let a = 0
return function(){
return a+= 1
}
}
const count = createCount()
console.log(count()) // 1
console.log(count()) // 2
console.log(count()) // 3
count라는 함수는 클로저 개념이 적용되었다.
내부 함수 return 함수는 외부 함수인 createCount() 함수의 변수에 접근할 수 있어서
그 값을 기억하고 유지하는 것이 클로저의 동작 원리이다.
Q. 클로저의 개념은 언제 많이 사용되는가???
클로저는 함수와 함수와의 관계에서 사용한다. IIFE 즉시실행함수에서 많이 쓰인다.
Q. 함수 최상단 영역 안에서 변수가 끌어올려지는 것으로 이해하면 되는가??
클로저를 호이스팅 개념으로 이해하는 것은 옳지 않다.
호이스팅은 선언된 시점과 관련이 있는데, 클로저는 시점과 관련 없이 "범위"에 대한 개념이기 때문에
함수가 정의된 렉시컬 스코프를 유지해서 외부 변수에 접근할 수 있게 한다!!라고 이해하는 것이 좋다.
메모리 누수
- 더 이상 필요하지 않은 데이터가 해제되지 못하고 메모리를 계속 차지하는 현상이다
메모리 누수가 생기는 예 1) 불필요한 전역 변수 사용
window.hello = 'Hello world!'
window.furaha = {name : 'furaha', age : 27}
전역객체에 등록된 속성은 사용되지 않는다 할지라도 가비지 컬렉션에서 데이터를 해제하지 않는다.
왜? 윈도우 객체는 항상 브라우저에 존재하고 있기 때문에 그 속성 데이터가 사용되고 있다고 판단한다.
그래서 전역객체에 속성을 등록하는 것은 추천하지 않는다.
메모리 누수가 생기는 예 2) 분리된 노드 참조
const btn = document.querySelector('button')
const parent = document.querySelector('.parent')
btn.addEventListener('click', () => {
console.log(parent)
parent.remove()
})
btn 을 클릭해서 parent를 제거했음에도 콘솔에는 parent 노드가 지속적으로 출력된다.
클릭 전에 parent 변수를 할당했기 때문에, 메모리 주소는 제거된 것이 아니기 때문에 계속 출력되는 것.
즉 메모리상에는 남아있는 상태.
어떻게 수정??
전역변수가 아닌 지역변수로 설정!!!
버튼을 클릭할 때마다 이미 parent 노드는 없기 때문에 parent라는 변수는 null 데이터로 반환됨.
const btn = document.querySelector('button')
btn.addEventListener('click', () => {
const parent = document.querySelector('.parent')
console.log(parent)
parent.remove()
// 6번째 line 은 parent && parent.remove() 로 수정하면 됨
})
메모리 누수가 생기는 예 3) 해제하지 않은 타이머
let a = 0
setInterval(() => {
a += 1
}, 100)
setTimeout(() => {
console.log(a)
}, 1000)
//수정 후
let a = 0
const intervarId = setInterval(() => {
a += 1
}, 100)
setTimeout(() => {
console.log(a)
clearInterval(intervarId)
}, 1000)
setInterval 을 clearInterval과 꼭 같이 사용해주어야 한다.
그렇지 않으면 계속 메모리 할당이 이루어져서 낭비가 됨.
메모리 누수가 생기는 예 4) 잘못된 클로저 사용
const getFn = () => {
let a = 0
return name => {
a += 1
console.log(a)
return `Hello ${name}~`
}
}
const fn = getFn()
console.log(fn('Heropy')) // 1 \n Hello Heropy~
console.log(fn('Neo')) // 2 \n Hello Neo~
console.log(fn('Lewis')) // 3 \n Hello Lewis~
출력된 결과 1,2,3 a의 값이 필요 없는데 클로저 개념이 적용되고 있음
메모리 누수 및 성능이 굉장히 떨어질 수 있음
느낀 점)
작업할 때, 메모리를 고려하면서 작업한 적이 많이 없는 것 같다ㅜ
메모리가 낭비되지 않는 최대한의 효율적인 코드에 대해 많이 고민을 해야 할 것 같고
한 가지 바로 적용해 볼 것은 '변수'를 어디에 선언하는가!! 너무 전역변수를 남발하지 말아야겠다고 느꼈다
'JS 개념정리' 카테고리의 다른 글
[Javascript 알짜개념] 프로토타입, ES6 Class 문법 (0) | 2023.08.07 |
---|---|
[Javascript 알짜개념] 함수, 호이스팅, this (0) | 2023.08.06 |
[Javascript 알짜개념] 콜 스택, 테스크 큐, 이벤트 루프 (0) | 2023.08.06 |
[Javascript 알짜개념] 불변성과 가변성, Symbol, BigInt (0) | 2023.08.03 |
[Javascript 알짜개념] 정규표현식 기본 문법과 패턴 연습 (0) | 2023.08.03 |