그럼에도 불구하고

👨‍💻

[CleanCode] 변수에 대하여 본문

JavaScript/Clean code

[CleanCode] 변수에 대하여

zenghyun 2023. 5. 24. 15:20

CleanCode를 작성하기 위한 과정 중 변수에 대해 알아보겠습니다.

 

목차

     

     

    [ var를 지양하자 ]

    📌 var : 함수 단위 스코프

     

    📌 let & const : 블록 단위 스코프 

    let과 const의 경우 블록 단위 스코프와 + TDZ (Temperal Dead Zone)으로 안전한 코드 작성이 가능합니다.

     

     

    https://despiteallthat.tistory.com/46

     

    [JavaScript] 변수 선언 / 변수 호이스팅 / 값의 할당

    오늘은 변수 선언 / 변수 호이스팅 / 값의 할당에 대해 알아보자 [ 변수 선언 ] 변수 선언(variable declaration)이란 변수를 생성하는 것을 말한다. 좀 더 자세히 말하면 값을 저장하기 위한 메모리 공

    despiteallthat.tistory.com

    https://despiteallthat.tistory.com/64

     

    [JavaScript] 스코프(scope)란?

    오늘은 스코프(scope)에 대해 알아보자 [ 스코프(scope) ] 스코프(유효범위)는 자바스크립트를 포함한 모든 프로그래밍 언어의 기본적이며 중요한 개념이다. 하지만, 자바스크립트의 스코프는 다른

    despiteallthat.tistory.com

     

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var name = '이름';
    var name = '이름2'
    var name = '이름3'
    var name = '이름3'
     
    // 값은 다른데 변수명은 일치한다. 
     
    console.log(name);  // 가장 마지막에 할당한 변수 값이 나온다.  
     
     
    // var는 재할당을 넘어 재선언(중복선언)까지 가능함 
     
     
     
    cs

     

    위의 코드는 굉장히 간단한 코드이지만, 다양한 문제점을 보여주고 있습니다.

     

    첫 번째로 값은 다른데 변수명이 일치합니다. 그로 인해 console.log(name); 은 가장 마지막 name 변수에 초기화 된 이름 3을 출력하게 됩니다. 

     

    그리고 var는 재할당을 넘어 재선언(중복선언)까지 가능합니다. 

     

     

    다음 예시를 보겠습니다. 

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var global = '전역';
     
    if (global === '전역') {
        var global = '지역';
     
        console.log(global); // 지역
    }
     
    console.log(global); // 지역 
    cs

     

    var는 함수 레벨 스코프를 갖고 있기 때문에 if문 안에서 global이라는 이름의 변수를 선언하고 console.log로 출력을 확인하면 if문안의 global과 바깥의 global은 모두 '지역'이라는 값을 출력합니다.  

     

    이는 실제로 코드를 작성하다 보면 무궁무진하게 길어지는 코드 속에서 개발자가 미쳐 놓친다면 얘기치 못한 결과를 초래할 수 있습니다. (생각만 해도 어질어질 ) 

     

    위의 예시를 const만 이용해도 아래와 같은 결과가 나옵니다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const global = '전역';
     
    if (global === '전역') {
        const global = '지역';
     
        console.log(global); // 지역
    }
     
    console.log(global); // 전역 
    cs

     

    [ 전역 공간 사용 최소화 ]

    📌 전역 공간 사용을 최소화 하자

     

    아래 예시를 보겠습니다. 

     

    💡 index.html 

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script src="./test3.js"></script>
    <script src="./test4.js"></script>
    <body>
        
    </body>
    </html>
    cs

     

     

    💡 test3.js 

     

    1
    2
    3
    4
    5
    6
    7
    var globalVar = 'global';
     
    console.log(globalVar);
    console.log(window);
     
    var setTimeout = 'setTimeout';
     
    cs

     

    💡 test4.js

     

    console.log(globalVar); setTimeout(() => { console.log('1초'); }, 1000);

     

    test3.js와 test4.js는 비교적 짧은 코드이지만 벌써부터 문제점이 보이시나요?

     

    위의 코드에는 생각보다 큰 문제점이 있습니다. 

     

    우선 test3.js에서 선언한 globalVar의 값 'global'은 test4.js에서 출력이 가능합니다. 

     

     

    console.log(window)를 출력해 보면  globalVar는 전역 변수로 선언되어 window에서 확인할 수 있습니다. 

     

    이를 통해 전역 변수를 선언했을 때 파일을 나누면 코드의 구역도 나뉘는 것이 아니며, 어디서나 접근이 가능하다는 것을 알 수 있습니다.

     

    또한, test3.js에서 선언한 setTimeout 변수로 인해 test4.js의 setTimeout 메서드는 동작하지 않습니다.

     

     

    전역 번수는 이렇게 큰 문제를 야기합니다. 

     

    그렇다면 이런 문제점을 해결하기 위해서 어떻게 해야 할까요?

     

    1. 전역 변수는 애초에 만들지 않는다.

    2. 지역 변수만 만든다.

    3. Window, Global에 접근하며 조작하지 않는다.

    4. 즉시 실행 함수, 모듈, 클로즈 활용을 고민하자 

     

    [ 임시 변수 제거하기 ]

    ※ 임시 변수란? 

    간단하게 말하자면 어떤 Scope안에서 전역 변수처럼 활용되는 변수를 말합니다.

     

    📌 예시 1

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function getElements() {
        const result = {}; // 임시 객체  CRUD 
     
        result.title = document.querySelector('.title');
        result.text = document.querySelector('.text');
        result.value = document.querySelector('.value');
     
        return result; 
    }
    cs

     

    여기서 result는 이 함수 공간 안에서는 전역변수나 다름이 없습니다. 

     

    위와 같은 코드는 어떤 문제점이 있을까요? 

     

    첫 번째로 명령형으로 가득한 로직이 나오게 됩니다. 

    두 번째로 추가적인 코드를 작성하게 하는 유혹을 당하게 만듭니다. 

     

     

     

    1
    2
    3
    4
    5
    6
    7
    function getElements() {
        return {
            title : document.querySelector('.title'),
            text : document.querySelector('.text'),
            value : document.querySelector('.value'),
        }; 
    }
    cs

     

    보는 시각에 따라 달리 평가할 수 있겠다만, 제가 보기에는 지금의 코드가 더 직관적이고 깔끔하다고 생각합니다. 

     

    📌 예시 2

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function getDateTime(targetDate) {
      let month = targetDate.getMonth();
      let day = targetDate.getDate();
      let hour = targetDate.Hours();
     
      month = month >= 10 ? month : "0" + month;
      day = day >= 10 ? day : "0" + day;
      hour = hour >= 10 ? hour : "0" + hour;
     
      return {
        month,
        day,
        hour,
      };
    cs

     

    위의 코드는 입력받은 시간을 통해 month, day, hour를 각각 구하고, 10이 넘는다면 0을 붙여주는 코드입니다. 

     

    아래와 같이 바꾸는 것을 어떨까요? 

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function getDateTime(targetDate) {
      let month = targetDate.getMonth();
      let day = targetDate.getDate();
      let hour = targetDate.Hours();
     
      return {
        month: month >= 10 ? month : "0" + month,
        day: day >= 10 ? day : "0" + day,
        hour: hour >= 10 ? hour : "0" + hour,
      };
    }
    cs

     

    좀 더 명확하고 직관적으로 보이지 않나요?

     

    임시 변수룰 쓰는 것은 코드를 작성할 때 간단하고, 편하게 작성할 수 있게 합니다. 

    최소한의 기능으로 나누는 것이 아닌 하나의 코드에서 많은 일을 수행하게 하기 때문입니다. 

     

    이는 초기 개발자들이 가장 많이 하는 실수라고 합니다!! ( 그간 제가 작성한 코드를 돌아보며 나는 그렇게 작성하고 있지는 않았는지 돌아보는 계기가 되었습니다. ) 

     

    그렇다면 임시 변수를 쓰지 않기 위한 해결책으로는 어떤 것이 있을까요? 

     

    1. 함수를 나눈다. 

     

    2. 값을 바로 반환한다. 

     

    3. 고차 함수를 사용한다.

     

    4. 선언형 코드로 바꾸자. 

     

    등이 있습니다. 

     

    [ 호이스팅 ]

    호이스팅은 선언과 할당이 분리된 것을 말합니다. 

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var global = 0
     
    function outer() {
        console.log(global); // undefined
        var global = 5
     
        function inner() {
            var global = 10
     
            console.log(global); // 10 
        }
     
        inner(); 
     
        global = 1;
     
        console.log(global); // 1
    }
     
    outer();
    cs

     

    https://despiteallthat.tistory.com/71

     

    [JavaScript] 변수 호이스팅

    지난번에 다뤄본 변수 호이스팅을 변수별로 알아보자 [ 변수 선언의 실행 시점과 변수 호이스팅 ] console.log(score); // undefined var score; // 변수 선언문 위의 예제에서는 변수 선언문보다 변수를 참조

    despiteallthat.tistory.com

     

    변수뿐만 아니라 함수도 호이스팅이 되기 때문에 함수를 만들 때는 함수 표현식으로 만드는 것이 좋습니다.

     

    1
    2
    3
    4
    5
    const sum = function () {
        return 1 + 2;
    }
     
    console.log(sum());
    cs

    'JavaScript > Clean code' 카테고리의 다른 글

    [CleanCode] 분기다루기  (0) 2023.05.30
    [CleanCode] 경계 다루기  (0) 2023.05.25
    [CleanCode] isNaN? is Not A Number?  (0) 2023.05.24
    [CleanCode] undefined와 null의 차이  (0) 2023.05.24
    [CleanCode] 타입 검사  (0) 2023.05.24
    Comments