24. Scope

장운서·2021년 6월 9일
0

24. Scope

24-1. Scope

이번 시간은 scope 라는 개념을 배워보겠습니다.

scope은 JavaScript의 문법이 아닙니다.

JavaScript에서 scope이란, '변수가 어디까지 쓰일 수 있는지'의 범위를 의미합니다.

is not defined 라는 에러 메시지를 보셨나요?

변수가 아직 선언되지 않았다는 뜻입니다.

"아닌데! 변수는 let, const, var 등으로 선언할 수 있고, 나는 분명 선언했는데!" 하시겠지만 변수를 선언한 영역에(block에) 접근할 수가 없어서 컴퓨터가 변수가 선언 되었다는 사실을 알지 못해서 그랬을것입니다.

그래서 변수가 선언되지 않았다는 오류메시지를 출력하게 되는 것입니다. 어떤 변수는 여기저기서 쓸 수 있는 반면에, 어떤 변수는 특정 함수 내에서만 쓸 수 있었습니다.

이런 개념이 바로 scope입니다.


24-2. Block

scope을 더 파헤치기 전에 먼저 알아야할 개념은 block입니다.

그 동안에 functionif 문, for 문을 하면서 이미 block을 많이 경험했습니다.

block이란 중괄호({} , curly brace)로 감싸진 것을 block이라고 합니다.

function 의 내부는 하나의 block입니다.

function hi() {
  return 'i am block';
}

for 문도 하나의 block이고요

for (let i = 0; i < 10; i++) {
  count++;
}

if 문의 {} 도 하나의 block입니다.

if (i === 1) {
  let j = 'one';
  console.log(j);
}

{} (block)내부에서 변수가 정의되면 변수는 오로지 {} (block)내부에서만 사용할 수 있습니다.

{} (block)내부에서 정의된 변수는 local(지역) 변수라고 부릅니다.

아래의 코드는 문제가 있습니다. 그 동안 Assignment 하면서 한 번이라도 겪었던 문제 아닌가요?

function getResult() {
  let result = 10;
  
  return result;
}

// 자바스크립트 에러! 
// getResult 내부의 scope에 접근할 수 없다
console.log(result);

console.log(result) 에서 getResult 내부에 접근이 불가능하기 때문에 result 라는 변수의 존재를 알지 못합니다.

result 라는 변수는 getResult 함수의 {} (block)에서만 사용할 수 있습니다.

console.log(result); 를 주석처리해서 일단 오류를 제거해주세요.


24-3. Global(전역) Scope

scope은 변수가 선언되고 사용할 수 있는 공간입니다.

scope 외부(block밖)에서는 특정 scope의 변수에 접근할 수가 없습니다.

block밖인 global scope에서 만든 변수를 global variable(전역변수)라고 합니다.

코드 어디서든 접근 가능해서 변수값을 확인할 수 있습니다.

const color = 'red';
console.log(color);

function returnColor() {
  console.log(color);
  return color;
}

console.log(returnColor());

returnColor 함수 내에서, returnColor 함수 밖에 있는 color 라는 변수를 return 해주었습니다.

color 라는 변수는 global 변수이기 때문에 returnColor 함수의 block에서도 접근이 가능해서 'red' 를 반환한것입니다.


23-4. Scope의 오염

global 변수를 쓰면 여기 저기서 접근하기 쉬워서 좋다고 생각할 수 있지만, 너무 남용하면 프로그램에 문제를 일으킬 수 있습니다.

global 변수를 선언하면, 해당프로그램의 어디에서나 사용할 수 있는 global namespace를 갖습니다.

namespace라는 것은 변수 이름을 사용할 수 있는 범위라는 뜻입니다. scope이라고도 하고 특히 변수이름을 얘기할 때는 namespace라고도 합니다.

global 변수는 프로그램이 종료될때까지 계속 살아있습니다. 이 말은 local 변수는 {} - block이 끝나면 더 이상 변수가 살아있지 않고 쓸 수 없다는 말입니다.

global 변수가 계속 살아있어서 변수값이 계속 변한다면 해당 변수를 트래킹하기도 어렵고 이 변수는 어디에서 왜 필요한지 알려면 도대체 어디에서 let, const로 선언을 했는지 찾아 나서야 합니다.

아래는 scope이 오염된 대표적인 예입니다.

const satellite = 'The Moon';
const galaxy = 'The Milky Way';
let stars = 'North Star';

const callMyNightSky = () => {
  stars = 'Sirius';
  
  return 'Night Sky: ' + satellite + ', ' + stars + ', ' + galaxy;
};

console.log(callMyNightSky());
console.log(stars);
  • stars 이라는 global 변수가 있습니다.
  • callMyNightSky 함수에서 새로운 변수를 선언하고 싶었는데 깜빡하고 let 키워드를 작성하지 않았습니다.
  • callMyNightSky 을 호출하면 stars 변수에 "Sirius" 이 할당됩니다.
  • global 변수였던 stars 에 영향이 갔습니다!
  • 다른 함수에서 global 변수인 stars 을 사용하고 싶은데 값이 수정된 "Sirius" 으로 사용하게 됩니다.

앞으로 함수가 몇 십개 있을지도 모르는 상황에서 저렇게 global 변수를 남용 하다가는 어디서 어떻게 값이 수정될지 알 수 없어집니다.


24-5. 좋은 Scoping 습관

위와 같이 global 변수가 여기저기서 수정되면 안되기 때문에 변수들은 block scope으로 최대한 나눠놔야 합니다.

  • 타이트한 scope(tightly scoping)의 변수는 코드 품질을 올려줍니다!
  • 코드가 block 으로 명확하게 구분되기 때문에 코드 가독성이 올라갑니다.
  • 코드가 한줄 한줄 쭉 나열된 것이 아니라 각각의 기능별로 block을 나누면 코드가 이해하기 쉬워집니다.
  • 나중에 코드를 수정할 일이 있을 때, 코드를 오랜만에 보더라도 잘 나뉘어 있어서 유지보수가 쉬워집니다.
  • 프로그램이 끝날때까지 변수가 살아있는 것이 아니라서(block이 끝나면 local 변수의 삶이 끝나서) 메모리 절약도 됩니다.

즉, 한마디로 요약하면 global 변수는 쓰지 않도록 노력해야 하고, 최대한 {} 내에서 let, const 을 사용하여 변수를 새로 만들어서 쓰자는 말입니다.

이제 마지막 예제입니다!

이번에는 if 문의 {} 의 block scope을 보겠습니다.

function logSkyColor() {
  const dusk = true;
  let myColor = 'blue'; 

  if (dusk) {
    let myColor = 'pink';
    console.log(myColor); // pink
  }

  console.log(myColor); // blue 
}

console.log(myColor); // 에러!!
  • if 문에 {} 의 코드 block을 사용하였습니다. 여기에 myColor 라는 변수를 let 으로 선언하였습니다.
  • if 문 내에서는 "pink" 라고 할당 하였고, if 문 밖에서는 "blue" 라고 할당한 것에 주목해주세요.

사실 이 코드는 function 의 block, scope, if 문의 block, scope으로, 모두 block 을 잘 사용 하였는데도 scope namespace가 오염된 것입니다. 왜냐하면 같은 이름의 변수를 사용했기 때문입니다.

이렇게 새로운 block에서 변수를 쓸 때는 항상 다른 이름으로 변수를 선언해야한다는 것을 잊지 말아주세요.

 

Assignment

코드를 작성하는 맨 아래에 whatIs 라는 함수를 만들어 놓았습니다.
이번에는 무엇을 구현하는 Assignment가 아닙니다. 위에 내용이 잘 정리 되었는지 궁금하네요!

 

case 오른쪽에 설명해야 할 단어를 텍스트로 작성해놨습니다. description 변수에 해당 단어에 대한 설명을 딱 한 문장으로 작성해주세요.

  • 강의 내용을 참고 하셔도 되고 인터넷에서 검색해도 됩니다. 이해하신대로 가볍게 작성해주세요.
  • 그리고 처음보는 switch 문이 있습니다. switch 문이 무엇인지 궁금한 사람은 아래에서 읽고 사용법을 익혀주세요. 👉 스위치문
  • 궁금한 것이 있다면 stackoverflow에 질문을 올려주세요!
profile
방향성을 찾고싶은 프론트엔드개발자

0개의 댓글