본문 바로가기
Programming/JavaScript

[JS] Scope(스코프)

by 공부합시다홍아 2024. 6. 14.

오늘은 JS 구문에서 스코프와 호이스팅의 개념에 대해서 공부를 해보려고 한다.

평소에 프론트엔드 부분에 대한 개발을 하다보면, 우리는 아래와 같은 장애를 확인할 수 있다.
Uncaught ReferenceError : confined is not defined at <anonymous>:4:13

이러한 에러가 발생하는 가장 큰 이유를 그저 박수 내부에 변수가 갇혀있다고로만 이해하고, 수정을 진행하였는데 오늘은 이러한 에러가 왜 발생하는 지 원인에 대해서 공부를 해보려고 한다.

JavaScript에는 scope라는 개념이 존재한다.
스코프는 크게 전역 스코프, 지역 스코프가 있는데 이해하기 쉬운 예로는 전역 변수, 지역 변수가 있다.
전역 변수의 경우는 특정 함수에 갇히지 않고, 참조가 가능하지만 지역 변수의 경우는 해당 함수 내에서만 사용이 가능하고 이를 사용하기 위해서는 getter,setter라는 생성자를 이용해 사용을 해줘야 한다.

전역 스코프 ( Global Scope )

이름만 봐도 나는 어디서든 사용이 가능해라고, 대놓고 표현하는 것 같다.
일단 개발을 하면서 느낀 점은 global이 붙으면 엄청난 확장의 개념이 따르고, 어디서나 사용이 가능하다라고 말해주는 것 같았다.

위 이미지에서 전체 박스는 전역 스코프 공간을 의미하지만, 노란색 박스는 지역 스코프 공간을 의미한다

변수 X 는 지역 스코프에서 참조가 가능하다.
전역 스코프에 존재하는 변수는 지역 스코프 내에서 참조될 수 있다.. 이렇게 전역 스코프에서 존재하는 변수를 우리는 전역 변수라고 이야기한다. 그렇다면 함수의 지역 스코프 내에 존재하는 변수 y는 어떨까요. 전역 스코프에서 참조될 수 있을까라는 의문이 드는게 정상이다라고 생각한다.

y는 전역 스코프에서 참조가 불가능하다.
지역 스코프 내에서 선언된 변수는 해당 지역에서만 존재할 수 있다. y와 같이 특정 지역 스코프 내에서 존재하는 변수를 지역 변수라고 이야기한다. 스코프가 정확하게 무엇인지, 어느 시점에 생성되는지에 대해서는 아래에서 알아볼 예정이다.


함수 스코프

JavaScript에서 지역 스코프를 생성하는 종류는 함수 레벨 스코프와 블록 레벨 스코프가 있다.
대부분의 언어는 블록 레벨 스코프를 따르지만, 스크립트는 과거 함수 레벨 스코프를 따랐었다.
현재는 let, const 키워드의 등장으로 인해 블록 레벨 스코프를 따를 수 있게 되었다.

함수 레벨 스코프란, 함수를 실행할 때 생겨나는 지역 스코프이다.

위의 예시가 바로 함수 스코프에 의해 생성된 지역 스코프인 것이다. ScopeTest라는 함수에 의해 생성된 스코프이므로,
y라는 변수는 해당 지역 스코프 내에서만 존재하는 것이다. 블록 레벨 스코프를 따르기 않았기 때문에 var 키워드만 사용하는 시기에는 지역 스코프 내에 갇히지 않은 변수가 다수 생성되었고, 전역 스코프로 해당 변수가 들어가게 되었다. 때문에 전역 변수의 선언을 남발하게 되며 불필요하게 과도한 메모리를 소모하는 문제를 겪을 수 밖에 없었다.
이러한 문제를 해결하기 위해 블록 레벨 스코프를 따르는 let 키워드와 const 키워드가 등작하게 되었다.

블록 스코프

함수 레벨 스코프는 함수를 실행할 때 생성되는 함수를 기준으로 하는 스코프인 반면에
블록 레벨 스코프는 코드 블록에 의해서 생성되는 스코프이다.

쉽게 설명을 하면 우리가 사용하는 if, for, white 문 내에서 사용하는 변수를 기억하면 된다.
해당 변수를 다른 곳에서 참조를 할 수 있는가? No 다. 해당 변수는 그 구문 내에서만 생성되고 이용이 가능하기 때문에 사용이 불가능하다. 이를 블록 스코프라고 표현한다.

위 사진에는 두 개의 블록 스코프가 존재한다.
하나는 for 구문 그리고 다른 하나는 if 구문이다.
for 문 내에는 a 그리고 b 라는 변수가 존재하고, 그 안의 if문에서도 a가 존재하지만, 동일한 이름의 변수이지만 for와 if는 서로 다른 영역이기 때문에 재선언이 아닌, 제 각 각의 변수인 것이다. 그래서 서로에게 영향을 끼치지 않는다

여기까지 이해했다면 조금의 의문이 생긴다.
for 구문에서 선언한 변수를 if에서 참조할 수 있지 않나?? 정답은 Yes 이다.
아래 이미지를 보면 이해가 가능하다.

그 이유는 스코프 체이닝 떄문이다.

자바 스크립트는 변수를 참조하는 코드를 만나게 됐을 때, 먼저 해당하는 불록 스코프 내에서 변수를 참조하고자 시도한다.
이때 탐색한 블록 스코프 내에 해당 변수가 존재하지 않는 경우, 상위 스코프로 올라가 다시 탐색을 진행하게 되는데,
이러한 과정을 스코프 체이닝이라고 한다.
그래서 if문에 의해서 생성된 블록 스코프 내에 a 라는 변수가 없었음에도 불구하고 에러가 발생하지 않았던 것이다.

그렇다면, 자바스크립트에서 어떻게 실행되는 지 확인하는 방법을 무엇이 있을까??
바로 실행 컨텍스트 debugger 를 사용하면 된다.

실행 컨텍스트 ( Debugger 사용 )

우리는 개발자 도구에서 debugger 기능을 사용할 수 있다.
아래 사진과 같인 debugger모드로 이동하고 싶은 부분에 "debugger"를 적은 후 코드를 실행시키는 방법이 있다.

혹은 개발자 도구 > source 탭에 접속을 하여 스크립트에서 디버그를 원하는 부분을 클릭해 확인하는 방법이 있다.

이때 15번째 줄을 보면, 파랑색으로 표시가 되는데, 이 부분이 BreakPoint 이다.
실행방법은 지정을 하고, 화면을 새로 고침하면 아래와 같이 실행이 된다.

그리고 아래 사진처럼 Scope 부분에서 구문을 한 줄 한 줄 확인해 어디서 에러가 발생하는지, 동작은 어떤 식으로 이루어지는 지 확인이 가능하다.

여기서 가장 상단에 버튼 5개가 나오는데, 두 번째 버튼을 한 번씩 클릭하면, 순서대로 동작을 하게된다.

그냥 스크립트 구문에 출력문을 한 줄 한 줄 적어서 디버깅을 하는 방법도 있지만, 개발자 도구를 활용하면 직관적이라서
더 좋은 거 같고, 굳이 디버깅 구문을 작성해주지 않아도 되는 편안함이 있는 거 같은 느낌도 있다.

그래서 이 방법은 개발자의 성향에 따라서 선택하면 되는 부분인 것 같다.

728x90

'Programming > JavaScript' 카테고리의 다른 글

[JS] HTTP 란 무엇일까  (0) 2024.06.14
[JS] 호이스팅  (0) 2024.06.14
[JS] To do List 구현  (0) 2024.06.13
[JS] Local Storage  (2) 2024.06.13
[JS] D-DAY 카운트 구현  (0) 2024.06.13