SEB[JS/Node : 핵심개념, 문법]

부트캠프 18일차가 된 날이다. 오늘은 JS/Node의 핵심개념들과 문법들에 대해서 공부를 했다. 전에는 가볍게 알아보는 수준이었다면, 오늘은 조금 더 깊이 파고들어 학습을 하는 시간을 가졌다. 오늘 배운 개념들을 복습할 겸 정리를 시작해보겠다.

원시자료형과 참조자료형

일단 고정된 저장 공간을 차지하는 데이터는 모두 원시 타입(primitive) 데이터라고 생각하자!

원시 자료형

  • javascript에서 원시 타입의 데이터는 객체가 아니면서 메소드를 가지지 않는 6가지 타입을 말한다.
    string, number, bigint, boolean, undefined, symbol이 있는데 여기에는 null도 끼워줄 수도 있겠다. 저 6가지는 typeof를 통해 검사하면 저대로 출력이 되나 nullobject로 출력이 된다. 하지만 동작은 원시타입과 비슷하기 때문에 끼워줄 수도 있다.
  • 모두 하나의 정보(데이터)를 담고 있다. 즉, 변수에는 하나의 데이터만 보관이 가능하다.

  • 원시 자료형이 보관함인 변수에는 하나의 원시자료형만 들어갈 수 있다. 이는 참조자료형과 구분되는 특징히다.

참조 자료형

JS에서 원시 자료형이 아닌 것은 모두 참조 자료형이다.

참조 자료형이 저장되는 특별한 보관함. Heap!

  • 참조 자료형의 변수에는 데이터가 위차한 곳(메모리상 주소)을 가리키는 주소가 저장된다.
  • heap의 크기는 동적(dynamic) 하게 변한다
  • 데이터는 별도로 관리되고, 변수에는 주소가 저장되기 때문에 refernce type이라고 한다.

heap이 동적으로 크기가 변하는 이유

  • 대량의 데이터가 들어오는 경우, 고정된 데이터를 사용하는 것은 비효율적이다.
  • 데이터가 언제 늘어나고 줄어들지 모르기 때문에 별도의 저장공간을 마련하여 따로 관리한다.

원시 자료형과 참조 자료형의 특징

  • 할당 시에 원시 자료형변수에 값 자체가, 참조 자료형주소가 담긴다.
  • 원시 자료형의 보관함 크기고정, 참조 자료형동적으로 크기가 변한다.

스코프(scope)

'범위'의 의미를 가지고 있다. 더 자세하게 말하면 변수의 유효 범위라고 알면 된다.

스코프와 주요 규칙(변수의 접근 규칙)

  • 변수에는 접근할 수 있는 범위가 존재한다.
    여기에서는 중괄호(블록) 안에 선언됐는가, 바깥쪽에서 선언됐는가가 중요하다. 이 범위를 스코프라고 한다.

    • 바깥쪽 스코프에서 선언한 변수는 안쪽 스코프에서 사용가능하다.
    • 안쪽 스코프에서 선언한 변수는 바깥쪽 스코프에서 사용 불가능하다.
  • 스코프의 정의와 규칙

    • 변수 접근 규칙에 따른 범위
      • 안쪽 스코프에서 바깥쪽 스코프로는 접근 가능하지만, 그 반대는 불가능하다
      • 스코프는 중첩이 가능하다.
      • 가장 바깥쪽 스코프는 전역 스코프(Global Scope) 라고 하고, 그 외에는 지역 스코프(Local Scope)라고 한다.
      • 지역 변수가 전역 변수보다 더 높은 우선순위를 갖는다.

스코프의 종류와 let, var, const 키워드

스코프의 종류

  • 중괄호로 둘러싼 범위(block scope : 블록 스코프)
  • 함수로 둘러싼 범위(function scope : 함수 스코프)

같은 함수여도, 화살표 함수 를 사용하면 블록 스코프로 취급된다. function키워드를 사용하면 함수 스코프이다. 이것이 화살표 함수와 일반 함수의 가장 큰 차이점이다.

블록스코프와 var키워드

  • let키워드는 for문 안의 변수를 바깥에서 사용하면 ReferenceError가 발생한다.

  • var키워드는 for문 안의 변수를 바깥에서 사용하면 에러가 발생하지 않는다.

  • var 키워드는 block scope를 무시하고, function scope만 따른다!

var과 let 키워드

  • 변수를 정의하는 또 다른 키워드가 var이다

    • var 키워드는 블록 스코프를 무시하고, 함수 스코프만 따른다.
    • 블록 단위로 스코프를 구현했을 때, 훨씬 더 예측 가능한 코드를 작성할 수 있으므로, let 키워드를 사용하는 것이 좋다.
    • var 키워드를 사용하지 않는다해도, 함수스코프는 let으로 선언된 변수의 접근을 제한한다.
  • var 키워드보다 let 키워드가 더 안전한 이유

    • var 키워드는 재선언을 해도 에러가 없지만, let 키워드는 재선언을 방지한다

const 키워드

  • 변하지 않는 값, 상수(constant) 를 정의할 때 사용한다.
    • let 키워드와 동일하게, 블록스코프를 따른다
    • 값의 변경을 최소화하여 보다 안전한 프로그램을 만들 수 있다. 값을 새롭게 할당할 일이 없다면 const 키워드를 사용하는 것이 좋다.
    • 값을 재할당하는 경우, TypeError가 발생한다.

변수 선언에서 주의할 점

window 객체(browser only)

  • var로 선언된 전역변수 및 전역함수는 window객체에 속하게 된다. window는 전역영역을 담당한다.
    • 브라우저에는 window라는 객체가 존재한다.
      • 브라우저 창을 대표하는 객체
      • 하지만 브라우저 창과 관계없이 전역항목도 담고 있다.

전역변수는 최소화 (side effect를 줄이는 것)

  • 전역변수 : 어디서든 접근 가능한 변수
  • 편리한 대신, 다른 함수 혹은 로직에 의해 의도되지 않는 변경이 발생할 수 있다.

let, const를 주로 사용할 것

  • var은 블록스코프를 무시하며, 재선언해도 에러가 발생하지 않기 때문에, 같은 스코프에서 동일한 이름의 변수를 재선언하는 것은 버그를 유발할 수 있다.
  • 전역변수를 var로 선언하는 경우 문제가 될 수 있다. var로 선언한 전역변수가 window기능을 덮어씌운다면 내장기능을 사용할 수 없게 만들 수 있다.

선언없는 변수 할당 금지

  • 선언 키워드 없이 변수를 할당하면 안된다. 변수를 선언한 적이 없어도, 값을 할당하면 var로 선언된 전역 변수처럼 작동한다.
  • 실수를 방지하기 위해 strict mode를 사용 가능하다. js 파일 상단에 'use strict';를 기재하면 사용 가능하다.

클로저

  • MDN 정의 : 함수와 함수가 선언된 어휘적(lexical)환경의 조합이라 한다. 하지만 이건 잘 이해가 안된다.
  • 외부함수의 변수에 접근할 수 있는 내부함수라고 생각하면 더 쉽게 생각할 수 있다.

클로저 함수의 특징

  • 함수를 리턴하는 함수. 이것이 클로저의 형태를 만든다.
  • 외부함수의 변수에 접근가능한 내부함수이다.
    따라서, 함수를 리턴하는 것만큼이나, 변수가 선언된 곳이 중요하다.

클로저의 활용

  • 데이터를 보존하는 함수
    • 일반적인 함수는 함수 실행이 끝나면 함수 내부의 변수를 사용할 수 없지만, 클로저는 외부함수의 실행이 끝나도 외부함수 내 변수가 메모리상에 저장된다.
  • 정보의 접근 제한(캡슐화)

    • 클로저 모듈 패턴

      const makeCounter = () => {
      	let value = 0;
         return {
         	increase : () => {
             	value += 1;
             }
             decrease : () => {
             	value -= 1;
             }
             getVakye : () => value;
         }
      }
      const counter1 = makeCounter();

      여기에서 value라는 변수에 값을 새롭게 할당할 수는 없을 것이다. 이는 스코프 규칙에 의해, 어떤 경우에도 value는 직접수정이 불가능하기 때문이다. 대신, 리턴하는 객체가 제공하는 메소드를 통해 value 값을 간접적으로 조작가능하다.

  • 모듈화

    • 재활용 가능한 makeCount 함수(위를 예시로). 여러 개의 counter를 만들 수 있다.
    • 함수의 재사용성을 극대화하여, 함수 하나를 완전히 독립적인 부품형태로 분리하는 것을 모듈화라고 한다.
    • 클로저를 통해 데이터와 메소드를 같이 묶어서 다룰 수 있다. 즉, 클로저는 모듈화에 유리하다.

Spread / Rest 문법

spread/rest 문법

Spread 문법

  • 주로 배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때 사용한다.
    function sum(x,y,z) {
    	return x + y + z;
    }
    const numbers = [1, 2, 3];
    sum(...numbers);  // 6을 리턴

Rest 문법

  • 파라미터를 배열의 형태로 받아서 사용할 수 있다. 파라미터 개수가 가변적일 때 유용하다.
    function sum(...theArgs) {
    	return theArgs.reduce((pre, cur) => {
        	return pre + cur;
        });
    }
    sum(1,2,3);  // 6을 리턴
    sum(1,2,3,4); // 10을 리턴

배열에서 사용하기

  • Spread 문법은 배열에서 강력하다. 하지만 기존 배열을 변경하지 않아 immutable하다.

    • 배열 합치기

      let arr1 = [0, 1, 2];
      let arr2 = [3, 4, 5];
      arr1 = [...arr1, ...arr2];  // arr1 : [0, 1, 2, 3, 4,  5]
    • 배열 복사

      let arr1 = [0, 1, 2];
      let arr2 = [...arr1];
      arr2.push(4); // arr1 : [0, 1, 2], arr2 : [0, 1, 2, 4]   

객체에서 사용하기

  let obj1 = {foo : 'bar', x : 42};
  let obj2 = {foo : 'baz', y : 13};
  let clonedObj = {...obj1};  // {foo : 'bar', x : 42}
  let mergedObj = {...obj1, ...obj2}; // {foo : 'baz', x : 42, y : 13};

함수에서 나머지 파라미터 받아오기

  function myfun(a, b, ...args) {
  	console.log('a, ' + a);
    console.log('b, ' + b);
    console.log('args, ' + args);
  }
  myfun('one', 'two', 'three', 'four', 'five');
  // a, one
  // b, two
  // args, ['three', 'four', 'five'] <- 배열의 형태로

구조분해(Destructing)

구조 분해 할당은 spread 문법을 활용해서 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정이다.

  • 분해 후 새 변수에 할당

    • 배열

      const[a, b, ...rest] = [10, 20, 30, 40 ,50];
      // a : 10, b : 20, rest : [30, 40, 50]
    • 객체

      const{a, b, ...rest} = {a : 10, b : 20, c : 30, d : 40};
      //  a : 10, b : 20, rest : {c : 30, d : 40} 

      여기에서 const 안의 ab, cd라면 ab, cd는 undefined고, rest가 {a : 10, b : 20, c : 30, d : 40}가 된다.

이번 챕터와 3주차를 마치며...

이번 챕터는 JS/Node의 핵심개념과 문법에 대해 알아봤다. 분명 쉬운 부분도 있었고 어려운 부분이 존재했다. 특히 구조분해를 하는 부분에서 객체에 대한 것이었는데 잘 배웠다고 생각했는데 실습을 해보니 엉망진창이었다. 이는 내가 조금 더 보완을 해야할 것 같다. 그리고 이번 주는 css도 더 깊게 해보는 시간을 가졌는데 특히 나는 CSS로 레이아웃을 구성하는 것을 어려워했던 것 같다. 많이 사용해보지도 못했고. 뭔가 구성하는데 있어서 내가 잘 생각을 못해내는건지, 제대로 하지 않은건지 많이 어려움을 겪었다. 이번 주 챕터를 하면서 느낀 것은 내가 어려워 하는 것들은 확실히 경험해보지 못하고, 많이 사용하지 않았던 것에서 나왔었다. 그러므로 나는 이를 극복하기 위해 더 경험하고, 실습같은 것을 더 하면서 많이 사용하면서 사용방법을 익혀야 될 것 같다. 이번 주는 정말 모르는 부분이 꽤 많았던 주였다. 앞으로더 더 많이 모르는 것들이 많이 나올텐데 기죽지 말고 내껄로 잘 만들어보자..!

Reference

  • 코드스테이츠(CodeStates) 강의자료

좋은 웹페이지 즐겨찾기