node.js

Johnywhisky·2021년 7월 28일
0

NodeJS

목록 보기
1/1
post-thumbnail

구직 사이트를 돌아보다 가장 먼저 깨닫게 된 게 있다.
python-django 보다 javascript-node.js를 사용하는 회사가 더 많다는 것이다.

취준생으로써 node 찍먹정돈 해볼 필요성을 깨달았다.

NODE.JS

노드란 무엇일까?

Node.js(이하 노드)를 정의할 때 3가지 키워드를 많이 얘기한다. 1. 비동기(Asynchronous), 2. 이벤트 기반(event-driven), 3. Javascript 런타임 환경 이다. 하나씩 차례대로 알아보자.

1. 비동기 Asynchronous


위 사진을 보면 동기와 비동기의 차이를 직관적으로 볼 수 있다. 동기(synchronous)는 어떤 API가 한 번의 요청(request)와 응답(response)을 처리할 때 서버는 다른 일을 할 수 없는 상태에 놓이게 된다. 즉 1번 task를 모두 끝낸 뒤 2번, 3번, 이후 task 순서대로 request를 처리(sequential I/O)하는 것이다.
하지만 이에 반해 비동기(Asynchronous)는 동기방식과는 다르게 API에 순서에 상관없이 일처리를 할 수 있는 비순차 입출력(non-sequential I/O) 환경이 마련된다. 그렇기 때문에 일의 처리(완료) 순서도 빨리 끝나는 작업의 결과가 먼저 출력되는 것을 알 수 있다.

// task 1
console.log("Sync node.js run start")
const meSync = {
    laundry: () => {
    console.log('세탁기 돌리기 시작')
    let percentage = 25

    while (percentage !== 100) {
        console.log(`${percentage}% 완료`)
        percentage += 25
    }

    console.log(`${percentage}% 빨래 완료`)
    },
    dishes: () => console.log('설거지 하기'),
    toilet: () => console.log('화장실 청소 하기'),
}

const doWorkSync = () => {
    meSync.laundry()
    meSync.dishes()
    meSync.toilet()
}
// task 2
doWorkSync()
// task 3
console.log("Sync node.js run end")

동기적 처리 방식의 쉬운 예시는 다음과 같다. meSync라는 object를 만들고 실행하면 결과는 다음과 같다.

Sync node.js run start
세탁기 돌리기 시작
25% 완료
50% 완료
75% 완료
100% 빨래 완료
설거지 하기
화장실 청소 하기
Sync node.js run end

task 1, 2, 3순서대로 코드가 실행된 것을 확인할 수 있다. 세탁기 작업을 모두 완료한 후에 설거지를 하고 화장실 청소도 수행하는 것이다. 세탁기를 돌리는 도중에 설거지도 하고 화장실 청소도 할 수 있는데도 이렇게 일을 처리하는 것은 정말이지 얼마나 비효율 적이란 말인가?! 그렇다면 비동기 처리는 어떻게 다를까?

//task 1
console.log("Async node.js run start")
const meAsync = {
    laundry: () =>
    new Promise((resolve, reject) => {
        console.log('세탁기 돌리기 시작')
        let percentage = 25

        const intervalId = setInterval(() => {
            console.log(`${percentage}% 완료`)
            percentage += 25

            if (percentage === 100) {
                clearInterval(intervalId)
                console.log(`${percentage}% 빨래 완료`)
                resolve()
                }
            }, 100)
        }),
    dishes: () => console.log('설거지 하기'),
    toilet: () => console.log('화장실 청소 하기'),
}

const doWorkAsync = async () => {
    await meAsync.laundry()
    meAsync.dishes()
    meAsync.toilet()
}
// task 2
doWorkAsync()
// task 3
console.log("Async node.js run end")

코드 실행 결과는 다음과 같다.

Async node.js run start
세탁기 돌리기 시작
Async node.js run end
25% 완료
50% 완료
75% 완료
100% 빨래 완료
설거지 하기
화장실 청소 하기

Promise나 async, awaitm setInterval 등 위의 동기 처리 방식에서는 보지 못한 코드가 조금 있다. 이런 함수들이 만들어낸 가장 큰 차이점은 결과에서 볼 수 있듯이 코드 가장 밑 줄에 표현해둔 console.log(task 3)가 먼저 실행되고 doWorkAsync()(tast 2)함수가 실행된 것이다!! 이 점이 동기식과 비동기 방식의 차이이다. promise나 async, await와 같은 것은 다음에 자세히 공부해봐야겠다.
(잠깐! 그럼 이건 세탁기를 돌리면서 동시에 설거지, 화장실 청소한건 아니잖아!! 참고로 meAsync.dishes()meAsync.toilet()doWorkAsync 함수 밖으로 빼면 다른 결과가 도출된다. 결과는 직접 확인!)

2. 이벤트 기반 Event-driven

사실 나에게는 비동기보다 더 이해하기 어려운 키워드가 이벤트 기반이었다. 하지만 스스로 내린 결론을 얘기해보자면,

  • Evevt
    이벤트에는 클릭(.on("click"))이나 네트워크 요청(request) 등이 있다.
  • Event-driven
    이벤트 기반 시스템에서는 특정 이벤트에 대한 콜백 함수(callback function)을 지정한다.

결국 이벤트 기반이란 키워드는 비동기 방식과 떨어질 수 없는 것 같다. 하나의 이벤트를 비동기적으로 처리하는 것이 노드의 아이덴티티인 것이다. 쉬운 예시를 들어보자면 클라이언트 1과 2가 순차적으로 request를 보냈을 때 클라이언트 1과 2 중 먼저 동작이 종료되는 request에 대한 response를 전송하는 것이다.

여담으로 사용하는 모듈과 코딩 방식에 따라 싱글 스레드로도 충분히 멀티 스레드와 같은 환경을 만들어줄 수 있고, 멀티 스레드를 싱글 스레드처럼 사용할 수도 있다.(다만 성능의 차이가 있겠지만) 여기서 노드는 싱글 스레드 환경에서 비동기 이벤트 기반의 처리 방식으로 빠른 앱을 설계할 수 있게 된다.

3. 자바스크립트 런타임 환경 Javascript runtime environment

자바스크립트로 만든 프로그램을 컴퓨터에서 실행할 수 있는 환경

그렇다면 자바스크립트 런타임 환경이란 어떤 의미일까? 먼저 런타임은 특정 언어로 만든 프로그램을 실행할 수 있는 환경을 의미한다. 구글의 V8 엔진이 등장하기 전까지 기존의 자바스크립트는 브라우저 단에서 구동되는 언어였기 때문에 컴퓨터가 이해할 수 있는 언어가 아니었다. V8 엔진의 등장과 함께 자바스크립트는 더이상 브라우저 뿐만아니라 컴퓨터가 이해할 수 있게 컴파일되어 브라우저를 벗어나 사용할 수 있게 되었다.

Chrome V8 엔진은 자바스크립트를 바이트코드(bytecode)로 컴파일하고 실행하는 방식을 사용하는 C++ 오픈 소스 자바스크립트 엔진이다. 이름에 걸맞게 구글에서 시작되었고, 지금은 우리의 자랑스러운 삼성 전자도 개발 그룹에 포함되어있다.(국뽕 충전!)

결론!

노드(Node.js)는 비동기(Asynchronous) 이벤트 기반(event-driven) Javascript 런타임 환경 이다

profile
안녕하세요 :) 1년 차 Pythonist 백엔드 개발자 윤서준입니다.

0개의 댓글