2carrot84
by 2carrot84
3 min read

Categories

  • lecture

Tags

  • Call Stack
  • Callback Queue
  • Event Loop
  • Hoisting
  • Lexical Scope
  • Node.js

지난번에 이어 ‘초격차 패키지 : 한 번에 끝내는 Node.js 웹 프로그래밍’라는 fastcampus 프로그래밍 강의 내용 정리 차 기록합니다.

외부 강의는 처음인데, 기존에 상세히 알지 못한 것과 대충 넘어간 것까지 꼼꼼히 집어줘서 좋은 강의라고 생각합니다.

이번 수업에 들은 ‘든든한 개발 환경 설정’, ‘Javascript 기초 이론’에 대한 내용입니다.

든든한 개발 환경 설정

강좌에서는 VS Code 를 이용한 개발 환경 구성을 하고 있으나, 본인은 IntelliJ 를 사용하여 몇 가지 안 맞는 부분이 있었습니다.
예를 들면 typescript 를 이용한 js 타입 자동 체크 등

  • tj/n : node version 관리를 위한 CLI tool
  • node 설치 및 npm 설치 및 사용
  • Formatting, Linting : 코드 품질 및 습관을 여러 사람이 일관되게 유지할 수 있음
    • Formattion 은 소스 코드 포맷 및 컨벤션
    • Linting 은 소스의 Best Practice 잡아주는 목적
  • package.json : 프로젝트 의존성을 관리
    • ^2.2.1 -> 실제 2.2.1 버전이 설치되지 않을 수 있다는 의미
  • package-lock.json : 실제 설치된 파일 버전이 표시됨
    • npm 은 해당 파일을 보고 package 관리
  • node-modules : 프로젝트가 의존하는 패키지들
    • .bin 실행할 수 있는 binary 지원
  • Typescript 로 js 타입 에러 체크
    • 일반적으로 type check 가 진행되는 시점은 compile 과정이나, js 는 compile 이 없어 실제 수행되는 중에만 에러 확인 가능
      • script는 동적 타입 언어로써, 변수에 어떤 값이 할당될지 예측이 어렵다.
    • Typescript : js 에 Type 정의가 얹혀진 형태
    • @Type/node : node 에서 사용되는 Type

실행한 쉘

npm install --save-dev prettier

npm install --save-dev eslint
npm install --save-dev eslint-config-airbnb-base eslint-plugin-import
npm install --save-dev eslint-config-prettier
npm install --save-dev eslint-plugin-node  

npm install --save-dev typescript
npm install --save-dev @types/node

Javascript 기초 이론

js 실행 모델의 종류 : Event Loop, Call Stack, Callback Queue

  • event loop 모델은 여러 스레드를 사용
    • main thread : 우리가 작성한 js 코드가 실행되는 스레드
    • 한 node.js 프로세스 에서 메인 스레드는 하나이며, 한 순간에 한줄씩만 실행! > 동시성 이슈 해소
    • 그러나, 그 외의 일(File I/O, networking ..)을 하는 워커 스레드는 여러개 존재
  • Call Stack : 지금까지 호출된 함수들의 stack
    • event loop가 다음 callback 을 처리하려면, call stack 이 비어있을때만 가능하다.
  • Callback Queue : callback (함수와 인자) 들이 쌓이는 Queue
    • callback 은 브라우저나 node 가 event 발생 시 메인스레드에 이를 알려주기 위해 사용
    • event 예. 파일처리 완료, network 작업 완료, 타이머 호출 등

Quiz. Hey! 는 몇번 출력될까?

setInterval(() => {
  console.log('Hey!')
  while(true) {}
}, 1000)

정답은 1번
1초 한번씩 setInterval에 의해 console.log 를 callback queue 에 담기지만,
while(true) {} 에 의해 call stack 이 비워 지지 않아, callback queue 에 쌓인 callback 함수는 실행되지 않는다. (Event Loop Blocking)

non-blocking I/O & offloading

Node 서버의 메인 스레드가 하나 임에도 빠른 동작을 할 수 있는 이유 메인 스레드는 코드 실행, 그외 업무는 Node 가 실행 - offloading

Event Loop

  1. callback queue 에서 호출된 callback 을 꺼낸다
    • queue 에 쌓인게 없을 경우 callback 이 호출될때 까지 대기
  2. 해당 callback 이 끝날때 까지 call stack 을 사용
  3. call stack 을 비운다 (모두 실행)

1 ~ 3번 과정을 계속 반복하여 실행

Hoisting

  • var : 변수 선언시 scope 의 최상단으로 hoisting 된다
    // 구현 소스
    console.log(x)  // undefined
    var x = 1
    
    // 실제 코드
    var x   // hoisting
    console.log(x)  // undefined
    x = 1
    
  • 기타
    console.log(x)  // error: Uncaught ReferenceError: x is not defined
    x = 1
    

Quiz. 아래 두 코드의 결과는?

function foo() {
    return 'foo'
} 
console.log(foo())
console.log(foo())
function foo() {
    return 'foo'
} 

두 코드의 결과는 같다 (두번째 코드에서 에러가 나지 않는다)
var 뿐만 아니라 function도 hoisting 대상이기 때문

functoion, lexical scope

  • lexical scope : {} 안쪽에서는 바깥 쪽({} 위) 변수에 접근할 수 있다.

예제 1

function foo() {
    var x = 'Hello!'
    console.log(x)  // Hello!
} 
console.log(x)  // error: Uncaught ReferenceError: x is not defined
var x = 'Hello!'
function foo() {
    console.log(x)  // Hello!
} 
console.log(x)  // Hello!

예제 2

var x = 1
if(true) {
    var x = 2
}
console.log(x)  // 2

var는 block scoping 대상이 아님

let x = 1
if(true) {
    let x = 2
}
console.log(x)  // 1

let, const는 block scoping 대상

마무리

그동안 실무를 하면서도 몰랐거나, 크게 고민하지 않았던 부분에 대해서 많이 알게되는 시간이네요.

그간 실무에 사용하는 언어에 대해 정말 모르고 그냥 일만 했구나 하는 반성을 해봅니다..🤦🏻‍♂️

그럼 이만. 🥕👋🏼🖐🏼