본문 바로가기

javaScript

스코프와 클로저

면접에서 종종 질문 당한다는?! 스코프와 클로저 대해 알아보자

스코프와 클로저는 서로 밀접히 연관된 개념인듯 하다.

한번 살펴보자.

 

스코프?

  • 변수 접근 규칙에 따른 유효 범위
  • 변수에는 접근할 수 있는 접근 범위가 존재한다.
  • 중괄호({ }) 안쪽에 변수가 선언 되었는가? 바깥쪽에 선언 되었는가?에 따라 스코프의 범위가 정해진다.
  • 기본적으로 안쪽에서 선언된 스코프는 바깥쪽 스코프에 접근할 수 없다.(inside -> outside X)
  • 스코프는 밖에서 안으로 접근이 가능하다.(outside -> inside O)
  • 스코프는 중첩이 가능하다.
  • 가장 바깥쪽 스코프를 전역 스코프(Global scope)라고 한다.
  • 전역 스코프를 제외한 모든 안쪽 스코프는 지역 스코프(local scope)라고 한다.
  • 전역 스코프에서 선언한 변수는 전역 변수
  • 지역 스코프에서 선언한 변수는 지역 변수
  • 지역 변수는 전역 변수 보다 더 높은 우선 순위를 갖는다.
  • 지역 스코프에서 전역 스코프에 접근하는 걸 '스코프 체인' 이라고 한다.
  • 스코프 체인은 scope의 가장 내부에서 scope chain을 따라 바깥쪽으로 검색을 하게 된다.

https://www.google.com/url?sa=i&url=https%3A%2F%2Fjstutorial.medium.com%2Fthe-visual-guide-to-javascript-variable-definitions-scope-abfb86edad&psig=AOvVaw1gWVh2LlB3L_4srLgFIdXr&ust=1667892882547000&source=images&cd=vfe&ved=0CA0QjRxqFwoTCMC5gq_Hm_sCFQAAAAAdAAAAABAD

 

 

클로저?

  • 클로저는 "함수와 함수가 선언된 어휘적(lexical) 환경의 조합을 말합니다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다." 라고 합니다.
  • 여기서의 키워드는 "함수가 선언"된 "어휘적(lexical) 환경"입니다. 특이하게도 자바스크립트는 함수가 호출되는 환경과 별개로, 기존에 선언되어 있던 환경 - 어휘적 환경 - 을 기준으로 변수를 조회하려고 한다.
  • “어휘적 환경" : 변수 및 함수 선언의 형태로 이해하면 된다.
  • 클로저 함수 : 함수를 리턴하는 함수
  • 클로저는 리턴하는 함수에 의해 스코프(변수의 접근범위)가 구분된다. 클로저의 핵심은 스코프를 이용해서, 변수의 접근 범위를 닫는(closure;폐쇄) 데에 있다. 함수를 리턴하는 것 만큼이나, 변수가 선언된 곳이 중요하다.
  • 외부 함수 & 내부 함수
const adder = x => y => {
	return x + y;
    }
  • 클로저는 “내부 함수는 외부 함수에 선언된 변수에 접근 가능하다”
  • 일반적인 함수는 함수 실행이 끝나고 나면 함수 내부의 변수를 사용할 수 없다.
  • 클로저는 외부 함수의 실행이 끝나도, 외부 함수 내 변수가 메모리 상에 저장된다.(어휘적 환경을 메모리에 저장하기 때문에 가능하다...?)
  • 데이터를 보존하는 함수이다.

adder(5)로 함수 실행이 끝나지만 이를 add5에 할당해서 외부 함수 내의 변수인 x 값을 사용할수 있다.

  • 클로저는 사용자를 통제하기 위해 사용하는데, 잘못 사용할 경우 메모리 낭비가 발생할 수 있으며, scope chain을 거슬러 올라가며 동작하기 때문에 성능 문제가 있을 수 있다.
const tagMaker = tag => content => '<${tag}>${content}</${tag}>'

cost divMaker = tagMaker("div");
divMaker('hello') // '<div>hello</div>'
divMaker('bye') // '<div>bye</div>'

const anchorMaker = tagMaker("a");
anchorMaker('go') // '<a>go</a>'
anchorMaker('class') // '<a>class</a>'
  • tagMaker("div")가 외부 함수의 tag 매개변수로 할당
  • divMaker('hello')가 내부 함수의 content 매개변수로 할당
  • 그래서 <div>hello</div>가 되는 것
  • 클로저는 이처럼 특정 데이터를 스코프안에 가두어 둔채로 계속 사용할 수 있게 해준다.
  • 클로저 함수: 클로저는 외부 함수의 컨텍스트에 접근할 수 있는 내부 함수를 뜻합니다. 외부 함수의 실행이 종료된 후에도, 클로저 함수는 외부 함수의 스코프, 즉, 함수가 선언된 어휘적 환경에 접근할 수 있습니다.
  • 클로저 사용 예시: 클로저를 통해 커링(currying, 함수 하나가 n개의 인자를 받는 대신 n개의 함수를 만들어 각각 인자를 받게 하는 방법), 클로저 모듈(변수를 외부 함수 스코프 안쪽에 감추어, 변수가 함수 밖에서 노출되는 것을 막는 방법) 등의 패턴을 구현할 수 있습니다.
  • 클로저의 단점: 일반 함수였다면 함수 실행 종료 후 가비지 컬렉션(참고 자료: MDN '자바스크립트의 메모리 관리') 대상이 되었을 객체가, 클로저 패턴에서는 메모리 상에 남아 있게 됩니다. 외부 함수 스코프가 내부 함수에 의해 언제든지 참조될 수 있기 때문입니다. 따라서 클로저를 남발할 경우 퍼포먼스 저하가 발생할 수도 있습니다.
  • 자바스크립트는 가비지 컬렉션을 통해 메모리 관리를 합니다. 객체가 참조 대상이 아닐 때, 가비지 컬렉션에 의해 자동으로 메모리 할당이 해제됩니다.

 

아! 

스코프는 변수의 접근 범위를 말하고, 스코프 체인은 스코프 내부에서 스코프 체인을 따라 가장 바깥쪽 외부까지 접근하는걸 말한다.

클로저는 함수를 리턴하는 함수인데, 내부 함수는 외부 함수에 선언된 변수에 접근 가능하다.