Hiun Kim (๊น€ํฌ์–ธ) ๐Ÿ“ archives

Node.js Internals

July 02, 2016

2014๋…„๊ฒฝ ์ฒซ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์–ธ์–ด์ธ PHP๋ฅผ ํŒŒ๋ณด๋ฉด์„œ PHP๊ฐ€ general-purpose language(๋ฒ”์šฉ์ ์ธ ์–ธ์–ด)๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ์˜คํžˆ๋ ค MySQL ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์ „์—ญ์— ๋‚ด์žฅํ•œ ๊ฒƒ์„ ๋ณด๋ฉด DSL์ ์ธ ํŠน์ง•๋„ ๊ฐ–์ถ”๊ณ  ์žˆ๋‹ค ์ƒ๊ฐํ•œ๋‹ค. ๋ฌผ๋ก  ์–ธ์–ด์˜ ์‚ฌ์šฉํ™˜๊ฒฝ์ด๋‚˜ ๋ชฉ์ ์„ ์ œํ•œํ•˜๊ณ  ๋งŽ์€ assumption(๊ฐ€์ •)๋“ค์„ ์„ค์น˜ํ•œ๋‹ค๋ฉด ํ•ด๋‹น domain(๋ถ„์•ผ)์—์„œ ์ƒ์‚ฐ์„ฑ์€ ์˜ฌ๋ผ๊ฐ„๋‹ค, ํ•˜์ง€๋งŒ ๊ธฐ๋Šฅ์˜ elastic(ํ™•์žฅ์„ฑ)๋ฉด์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ธฐ ์‰ฝ๋‹ค. ๋•Œ๋ฌธ์— ์ด์ œ general-purpose language๋กœ ๋„˜์–ด๊ฐ€์•ผ๋  ๋•Œ๊ฐ€ ๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

Python๊ณผ JavaScript์ค‘ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€, ์›น ๋ถ„์•ผ์— ์žˆ๊ธฐ๋•Œ๋ฌธ์— JavaScript๋กœ ์„ ํƒ์„ ํ•˜์˜€๋‹ค. ์ง€๊ธˆ์ƒ๊ฐํ•ด๋ณด๋ฉด ๋‘˜ ๋‹ค ๊ดœ์ฐฎ์€ ์„ ํƒ์ด์˜€๋˜๊ฒƒ ๊ฐ™๋‹ค. Python์€ ๋ฐ์ดํ„ฐ๊ณผํ•™์—๋„ ๋งŽ์ด ์“ฐ์ด๊ณ  ๋ฌด์—‡๋ณด๋‹ค JavaScript๋ณด๋‹ค bold(ํƒ„ํƒ„)ํ•œ ๋Š๋‚Œ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ธฐ์ˆ ์ ์ธ ์ด์œ ๋Š” ์•„๋‹ˆ์ง€๋งŒ, Google ๊ฒ€์ƒ‰ ์—”์ง„์ด๋‚˜, Dropbox๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ์„œ๋น„์Šค์—๋„ ์ ์šฉ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ผ ๊ฒƒ์ด๋‹ค.

Node.js์˜ ๋‚ด๋ถ€๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” JavaScript์— ๋Œ€ํ•œ ๊ฐ„๋‹จํ•œ ๋ฐฐ๊ฒฝ๊ณผ, ์–ธ์–ด์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ํ•œ๋‹ค๋ฉด ๋”์šฑ ๋„์›€์ด ๋ ๊ฑฐ๋ผ ์ƒ๊ฐํ•ด, ๊ฑฐ๊ธฐ์„œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๊ธฐ๋กœ ํ•˜์˜€๋‹ค.

์งง์€ ์—ญ์‚ฌ

JavaScript๋Š” ECMASCript๋ผ๋Š” ํ‘œ์ค€์ด ์กด์žฌํ•˜๊ณ , ํ‘œ์ค€์˜ specification(๋ช…์„ธ)๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ Google์˜ V8, Firefox์˜ SpiderMonkey, Microsoft์˜ ChakraCore์™€ ๊ฐ™์ด implementation(๊ตฌํ˜„์ฒด)์ด ์กด์žฌํ•œ๋‹ค. ๋ฐ˜๋ฉด Python์€ Python Software Foundation์ด๋ผ๋Š” single-source๋กœ ๋ถ€ํ„ฐ ์–ธ์–ด๊ฐ€ ๊ฐœ๋ฐœ๋œ๋‹ค, ๋ฌผ๋ก  ๊ณต์‹์ ์ธ implementation์ด ํ•˜๋‚˜๋ฟ์ด๋‹ˆ ํ‘œ์ค€์€ ํ•„์š”์—†์„๊ฒƒ์ด๋‹ค.

1995๋…„, ๋‹น์‹œ ์›น๋ธŒ๋ผ์šฐ์ ธ๊ณ„์˜ ์„ ๋„์ž์˜€๋˜ NetScape๊ฐ€ JavaScript๋ฅผ ๋ฐœํ‘œํ•˜์˜€๊ณ , 96๋…„ ๋ธŒ๋ผ์šฐ์ ธ์— ํƒ‘์žฌํ•˜์ž, Microsoft๋Š” JavaScript์˜ dialect(๊ณ ์œ ํ•œ ํŠน์ง•์ด ์žˆ๋Š” ํŠน์ • ์–ธ์–ด์˜ โ€˜ํ˜ธํ™˜ ์–ธ์–ดโ€™)๋กœ JScript๋ฅผ ๊ฐœ๋ฐœํ•˜์˜€๋‹ค. ํ‘œ์ค€ํ™”๋ฅผ ์œ„ํ•ด NetScape๋Š” JavaScript๋ฅผ Ecma International์— ํ‘œ์ค€์œผ๋กœ ๋“ฑ๋กํ•˜์˜€๊ณ , Netscape์™€ Microsoft๋Š” ํƒ€ํ˜‘์„ ํ†ตํ•ด ECMAScript๋ผ๋Š” ์ด๋ฆ„์„ ๋งŒ๋“ค์—ˆ๋‹ค.

V8 JavaScript Compiler

2008๋…„ Google์ด V8์ด๋ผ๋Š” ์ƒˆ๋กœ์šด JavaScript implementation์„ ์ถœ์‹œํ•˜์˜€๊ณ , V8์€ ๋‹ค๋ฅธ implementation, ์ฆ‰ JavaScript engine๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ JavaScript code๋ฅผ ๋ฐ”๋กœ machine code๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์ข‹์€ ์„ฑ๋Šฅ์„ ํ™•๋ณดํ•˜์˜€๋‹ค. ์ด๋Ÿฌ ํ•œ ์„ฑ๋Šฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ 2009๋…„ Ryan Dahl์€ Node.js๋ฅผ ๊ฐœ๋ฐœํ•œ๋‹ค.

Node.js

Node.js๋ฅผ Google Trend๋กœ ๊ฒ€์ƒ‰ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, ์‚ฌ๋žŒ๋“ค์˜ ๊ด€์‹ฌ์ด ๊พธ์ค€ํžˆ ์ƒ์Šนํ•˜๋Š”๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. Node.js in Google Trend

์ตœ๊ทผ Node.js๋Š” Command-line interface(์ปค๋งจ๋“œ๋ผ์ธ)ํˆด๋กœ๋„ ๋งŽ์ด ์‚ฌ์šฉ๋˜์ง€๋งŒ, ์—ญ์‹œ ๊ฐ€์žฅ ๋†’์€ ์ธ๊ธฐ๋ฅผ ์–ป๊ณ  ์žˆ๋Š”๊ฒƒ์€ network-based application์ด๋‹ค. Node.js๋Š” ํ™ˆํŽ˜์ด์ง€์—๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์†Œ๊ฐœ๋˜์–ด์žˆ๋‹ค.

As an asynchronous event driven JavaScript runtime, Node is designed to build scalable network applications. (Node.js๋Š” ๋น„๋™๊ธฐ, ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์˜ JavaScript๋Ÿฐํƒ€์ž„์œผ๋กœ ํ™•์žฅ์„ฑ์žˆ๋Š” ๋„คํŠธ์›Œํฌ ์‘์šฉํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•˜๋Š”๋ฐ ์ ํ•ฉํ•˜๋‹ค.)

09๋…„ ๋“ฑ์žฅ์‹œ ๋ถ€ํ„ฐ ๊พธ์ค€ํ•˜๊ฒŒ ๊ด€์‹ฌ์„ ๋ฐ›๊ณ  ์„ฑ์žฅํ•ด์˜จ ๋ฐฐ๊ฒฝ์—๋Š” ์‚ฌ๋žŒ๋“ค์ด Node.js์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์ด์œ , ์ฆ‰ scalableํ•œ network application์„ ๋งŒ๋“œ๋Š”๋ฐ ์žˆ์–ด์„œ์˜ ๊ฐ•์  2๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

1.Asynchronous I/O(๋น„๋™๊ธฐ I/O)๋ฅผ ์ด์šฉ ํ•œ ๋†’์€ throughput
2.Asynchronous Programming(๋น„๋™๊ธฐ ํ”„๋กœ๊ทธ๋ž˜๋ฐ)์— ์ ํ•ฉํ•œ evaluation strategy(์ฝ”๋“œ ์‹คํ–‰ ๋ฐฉ์‹)

Asynchronous I/O

I/O๋Š” input/output์˜ ์•ฝ์ž์ด๋‹ค. I/O๋ผ๋Š” ๋ง์€ ์ผ๋ฐ˜์ ์ด๊ธฐ ๋•Œ๋ฌธ์— CPU, RAM, Disk, Network์™€ ๊ฐ™์€ computing resource์ค‘ ์–ด๋Š๊ฒƒ ์—๋„ ์ ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด addition(๋”ํ•˜๊ธฐ)๋ฅผ ํ•˜๋ ค๋ฉด ํƒ€์ž… ์ฒดํฌ์™€ ์‹ค์ œ ๋”ํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด IA32์™€ ๊ฐ™์€ instruction์„ CPU๋กœ ๋˜์ง€์ง€๋งŒ ์ด๊ฒƒ์€ I/O๋ผ๊ณ  ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค. โ€˜Hello Worldโ€™๋ผ๋Š” string์ด ์ €์žฅํ•œ ๋ฉ”๋ชจ๋ฆฌ์กฐ๊ฐ ์—ญ์‹œ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ ‘๊ทผ ์†๋„๊ฐ€ ๋งค์šฐ ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋˜ํ•œ CPU์™€ RAM์€ ํ”„๋กœ๊ทธ๋žจ ๊ทธ ์ž์ฒด๋ฅผ ์‹คํ–‰ํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ž์›์ด๊ธฐ๋•Œ๋ฌธ์— ์ ‘๊ทผ์ด ๋งค์šฐ ๋นˆ๋ฒˆํ•˜๋ฉฐ ์ด ๋‹ค์Œ์— ์–ธ๊ธ‰ํ•  ์ง„์งœ I/O๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ์‚ฌ์šฉ์„ ํ•˜์ง€ ์•Š์œผ๋ฉด ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ์ž์ฒด๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์ง„์งœ I/O๋กœ ์ทจ๊ธ‰๋ฐ›๋Š”๊ฒƒ์€ Disk, Network๊ฐ€ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ž์›๋“ค์€ ์•ž์˜ ์ž์›๋“ค๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ ‘๊ทผ ์†๋„๊ฐ€ ๋Š๋ฆฌ๊ธฐ๋•Œ๋ฌธ์— ์ ‘๊ทผ๋น„์šฉ์ด ๋†’์€ ์ž์›์— ์†ํ•œ๋‹ค.

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋”ฐ์ง€๋ฉด, ์‚ฌ์šฉ์ž์™€์˜ HTTPํ†ต์‹ ์ด๋‚˜, MySQL์— ๋Œ€ํ•œ ์ž‘์—…๋“ฑ์ด network I/O์— ์†ํ•˜๋ฉฐ, jpegํŒŒ์ผ์„ ์„œ๋น™ํ•˜๊ฑฐ๋‚˜ ์ ‘๊ทผ ๋กœ๊ทธ๋ฅผ ํŒŒ์ผ์— ์ €์žฅํ•˜๋Š”๊ฒƒ์€ disk I/O์— ์†ํ•œ๋‹ค.

Asynchronous I/O๋Š” ์ „ํ˜€ ํŠน๋ณ„ํ•œ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์–ธ์–ด์™€ ๋Ÿฐํƒ€์ž„์—์„œ ๋น„๋™๊ธฐ(asynchronous)์™€ ๋™๊ธฐ(synchronous)์˜ ์ฐจ์ด์ ์€ ํŠน์ • API ์ฝœ์— ๋Œ€ํ•œ request(์š”์ฒญ)์™€ response(์‘๋‹ต)์˜ procedural pair(์ˆœ์ž์ ์ธ ์ง์ง“๊ธฐ)์—ฌ๋ถ€์ด๋‹ค.

์œ ๋‹‰์Šค์—์„œ ๋กœ์ปฌ๋””์Šคํฌ์˜ ํŒŒ์ผ์„ ์ฝ๋Š” API์ธ read์˜ ๊ฒฝ์šฐ ๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค, read ํ•จ์ˆ˜๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๊นŒ์ง€ ๋‹ค๋ฅธ readํ•จ์ˆ˜๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค. ์ด ๊ฒฝ์šฐ ๋™๊ธฐ API๋Š” ์•„๋ฌด๋Ÿฐ ๋น„ํšจ์œจ์„ฑ์„ ๊ฐ€์ง€์ง€ ์•Š๋Š”๋‹ค, ๋ฐ˜๋Œ€๋กœ ๋งํ•ด ๋น„๋™๊ธฐ API๋Š” ์•„๋ฌด๋Ÿฐ ์ถ”๊ฐ€ ํšจ์šฉ์ด ์—†๋‹ค, ๊ทธ ์ด์œ ๋Š” API์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ™์€ ๋จธ์‹ ์—์„œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋ฒฝ๋Œ 10์ž๋ฃจ๋ฅผ ๊ฐ™์€ ๊ฐ„๊ฒฉ์„ ๊ฐ€์ง„ ์„ธ ์ง€์  A์—์„œ B๋ฅผ ๊ฑฐ์ฒ˜ C๋กœ ์˜ฎ๊ธฐ๋Š”๋ฐ synchronousํ•˜๊ฒŒ ๋ณธ๋‹ค๋ฉด ํ•œ์ž๋ฃจ์”ฉ A->C๋กœ 10๋ฒˆ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์ด๊ณ , asynchronousํ•˜๊ฒŒ ๋ณธ๋‹ค๋ฉด ํ•œ์ž๋ฃจ์”ฉ A->B๋กœ ์˜ฎ๊ธฐ๊ณ  B->C๋กœ 10๋ฒˆ ์˜ฎ๊ธฐ๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์ด ์ผ์˜ ์–‘์€ ๋™์ผํ•˜๋‹ค, ์˜คํžˆ๋ ค asynchronousํ•˜๊ฒŒ ๋ฒฝ๋Œ์„ ์˜ฎ๊ธธ๊ฒฝ์šฐ ๋ฒฝ๋Œ์ž๋ฃจ๋ฅผ ์˜ฎ๊ธฐ๊ธฐ์œ„ํ•ด ๋˜๋Œ์•„๊ฐ€๋Š” ๋น„์šฉ, ์ฆ‰ process scheduling๋น„์šฉ์ด ์ž‡๊ธฐ๋•Œ๋ฌธ์— ๋” ๋น„ํšจ์œจ์ ์ด๋‹ค.

ํ•˜์ง€๋งŒ B์ง€์ ์— ์ผ์ •์‹œ๊ฐ„๋งˆ๋‹ค ๋ฐฐ๊ฐ€ ์šดํ–‰๋˜๋Š” ๊ฐ•์ด ์žˆ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ฆ‰ ๋ฌผ๊ฑด์„ ์˜ฎ๊ธฐ๋Š”๋ฐ ์žˆ์–ด์„œ, ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ ๋‹ค๋ฅธ ์š”์†Œ๋กœ๋ถ€ํ„ฐ dependency(์˜์กด์„ฑ)๊ฐ€ ์ƒ๊ธด ๊ฒƒ์ด๋‹ค. ์‘์šฉ์†Œํ”„ํŠธ์›จ์–ด๋Š”๊ฑฐ ๋Œ€๋ถ€๋ถ„ ๊ทธ๋Ÿฐ ์ƒŒ๋“œ์œ„์น˜ ์‹ ์„ธ์ด๋ฉฐ, JavaScript๊ฐ€ ๋ฐ”๋กœ ๊ทธ๋ ‡๋‹ค. ์œ„๋กœ๋Š” ์‚ฌ์šฉ์ž์˜ UI์— ๋Œ€ํ•œ ์ผ์ด, ์•„๋ž˜๋กœ๋Š” AJAX์š”์ฒญ์— ๋Œ€ํ•œ ์ผ์ด ์ž‡๋‹ค.

์‚ฌ๋žŒ๋“ค์€ ํŒŒ์ผ์„ ๋„คํŠธ์›์œผ๋กœ ์ „์†กํ•˜๋Š”๋ฐ ์žˆ์–ด์„œ๋Š” ๊ธฐ๋‹ค๋ฆด์ˆ˜ ์ž‡์ง€๋งŒ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋Š”๊ฒƒ์€ ๋‹น์—ฐํ•˜๊ฒŒ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. ๋งŒ์ผ AJAX์š”์ฒญ์ด ์ง„ํ–‰์ค‘์ผ๋•Œ ๋ฒ„ํŠผ์ด ๋ˆŒ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ทธ๊ฑด ๋ง์ด ์•ˆ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ๋•Œ๋ฌธ์— JavaScript๋Š” ์ž‘์—…๋Ÿ‰์ด ๋งŽ๋‹ค(a.k.a CPU๋ฅผ ๋งŽ์ด ์“ด๋‹ค)๊ธฐ ๋ณด๋‹จ, ์ ์€ ์ž‘์—…์ด๋ผ๋„ ๋™์‹œ์ ์œผ๋กœ ํ• ์ˆ˜์žˆ๋Š” ๋ฉˆ์ถ”์ง€ ์•Š๋Š”(non-blocking) ๋Ÿฐํƒ€์ž„์ด ํ•„์š”ํ•œ๊ฒƒ์ด๊ณ  ์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒ ๋””์ž์ธ๋˜์—ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์—ฐ์œ ์— ์˜ํ•ด, ์ฆ‰ ์ž‘์—…๋Ÿ‰์ด ์ ๊ธฐ๋•Œ๋ฌธ์— JavaScript์—”์ง„์€ single-threaded(๋‹จ์ผ ์Šค๋ ˆ๋“œ)์ด๊ณ , ๋ฉˆ์ถ”๊ธฐ ์•Š๊ธฐ์œ„ํ•ด asynchronous I/O๋ฅผ ๊ฐ€์ง„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿผ ์šฐ๋ฆฌ์˜ ์˜๋ฌธ์€ 2๊ฐ€์ง€๊ฐ€ ๋œ๋‹ค.

1.Asynchronous I/O๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘๋˜๋Š”๊ฐ€?
2.Sync๊ธฐ๋ฐ˜์˜ Operating System์—์„œ ์–ด๋–ป๊ฒŒ ํšจ์œจ์ ์ธ Asynchronous I/O๋ฅผ ๊ตฌํ˜„ํ• ์ˆ˜ ์žˆ๋Š”๊ฐ€?

Asynchronous I/O Mechanism

synchronous๋ฐฉ์‹์˜ ๋ฐ˜๋Œ€๋ผ๊ณ  ๋ณด๋ฉด๋œ๋‹ค, ์ฆ‰ request๋ฅผ ํ•˜๊ณ  response๊ฐ€ ์˜ค๊ธฐ์ „์—๋„ ๋‹ค๋ฅธ ์š”์ฒญ์„ ๋ฐ›์•„๋“ค์ผ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋ฌผ๋ก  response์™€ request๊ฐ„์˜ pair๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋”ฐ๋กœ ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ๋ถ€๋ถ„์ด ์ถ”๊ฐ€์ ์œผ๋กœ ์†Œ๋ชจ๋˜๋‚˜ CPU utilisation ์ตœ๋Œ€ํ™” - idle ์ตœ์†Œํ™”๊ฐ€ ํ›จ์”ฌ ๋” ํฐ ๋ฆฌ์†Œ์Šค ์ ˆ์•ฝ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•œ๋‹ค.

์•„๋ž˜๊ทธ๋ฆผ์—์„œ overlapped๋œ ๋ถ€๋ถ„๋งŒํผ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•œ๊ฒƒ์ด๋ผ๊ณ  ๋ณด๋ฉด๋œ๋‹ค, ์ฆ‰ ๊ทธ๋งŒํผ CPU๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๊ฒƒ์ด๋ผ๊ณ  ํ• ์ˆ˜ ์žˆ๊ณ  ์ด๊ฒƒ์ด asynchonous I/O์˜ ์žฅ์ ์ด๋‹ค.

Asynchronous I/O

๋ฐฉ๊ธˆ์ „, request์™€ response์˜ pair์— ๋Œ€ํ•ด์„œ ์–ธ๊ธ‰ํ•œ ์ ์ด ์žˆ๋‹ค. asynchronousํ™˜๊ฒฝ์—์„œ pair๊ฐ€ ์ง€์ผœ์ง€์ง€ ์•Š๋Š” ์ƒํ™ฉ์€ ํŒŒ์ผ a, b์— ๋Œ€ํ•œ read request์— ๋Œ€ํ•ด 2๊ฑด์˜ response๊ฐ€ ๋Œ์•„์˜ค๋Š”๊ฒƒ์ด๋‹ค, ๋ฌธ์ œ๋Š” ๊ทธ ์ค‘ ์–ด๋–ค๊ฒƒ์ด a์ด๊ณ  b์ธ์ง€ ๊ตฌ๋ถ„ํ• ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ํŒŒ์ผ ํฌ๊ธฐ๊ฐ€ ๊ฐ™๋‹ค๋ฉด ์ฒซ๋ฒˆ์งธ response๋ฅผ a๋กœ ํŠน์ •ํ• ์ˆ˜๋Š” ์žˆ๊ฒ ์œผ๋‚˜, a์˜ ํŒŒ์ผ ํฌ๊ธฐ๊ฐ€ b๋ณด๋‹ค ํฌ๋‹ค๋ฉด b๋จผ์ € ์‘๋‹ต์ด ์˜ฌ์ˆ˜๋„ ์žˆ๊ณ  ๋ฌด์—‡๋ณด๋‹ค ์š”์ฒญ์ด ์ˆ˜์‹ญ ์ˆ˜๋ฐฑ๊ฐœ๋ผ๋ฉด ์š”์ฒญ๊ณผ ์‘๋‹ต์˜ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜๋Š”๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ฌผ๋ก  synchroniseํ™˜๊ฒฝ์—์„œ๋Š” blocking์ด ๋˜๊ธฐ๋•Œ๋ฌธ์— pair์— ๋Œ€ํ•œ ์šฐ๋ ค๋Š” ์—†๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์€ read์ฝœ์ด ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ๋ฅผ asynchronousํ™˜๊ฒฝ์—์„œ ์‹คํ–‰ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž,

var contentA = read('a.txt');
var contentB = read('b.txt');
console.log(contentA, contentB);

console.log๋ผ๋Š” ํ•จ์ˆ˜์— contantA, contentB๋ผ๋Š” 2๊ฐœ์˜ dependency๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ, ํ•จ์ˆ˜๋Š” dependency์˜ ๊ฐ’2๊ฐœ๊ฐ€ ์ „๋ถ€ ๋‚˜์˜จ ๋‹ค์Œ์— ์‹คํ–‰๋˜๋Š”๊ฒƒ์ด ๋งž์„๊ฒƒ์ด๋‹ค, ๊ทธ๋Ÿฌ๋‚˜ ์œ„์—์„œ ์•„๋ž˜๊นŒ์ง€ ์ฝ”๋“œ๋ฅผ proceduralํ•˜๊ฒŒ ์‹คํ–‰ํ•  ๊ฒฝ์šฐ console.logํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ํƒ€์ด๋ฐ์— dependency๋“ค์ด ๊ตฌํ•ด์ง€์ง€๋Š” ์•Š์„๊ฒƒ์ด๋‹ค. ์ฆ‰, ํ˜„์žฌ์˜ proceduralํ•œ evaluation strategy๋ฅผ ๊ฐ€์ง„ ํ˜„์žฌ์˜ ์ฝ”๋“œ์—์„œ๋Š”, while loop์„ ๋Œ๋ฉด์„œ pooling๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š”๋“ฑ ์šฐ๋ฆฌ๊ฐ€ ์ˆ˜๋™์ ์œผ๋กœ ํ™•์ธํ•˜๋Š”๊ฒƒ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

JavaScript๋Š” event๋ผ๋Š” ๊ฐœ๋…์„ ๋„์ž…ํ•˜์—ฌ console.logํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ํƒ€์ด๋ฐ, ์ฆ‰ dependency 2๊ฐœ๊ฐ€ ์ •ํ•ด์ง€๋Š” ์‹œ์ ์„ ์•Œ๋ ค์ฃผ์–ด์„œ, ์šฐ๋ฆฌ๊ฐ€ ๊ทธ ๋‹ค์Œ ์ž‘์—…์„ ์ง„ํ–‰ํ• ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค.

Event๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ, JavaScript์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ callback function์„ ์‚ฌ์šฉํ•œ๋‹ค.[1]

var contentA, contentB; 

read('a.txt', contentAHandler) //1.read a.txt and pass handler function

var contentAHandler = (result) => { //2.read a.txt finished
    contentA = result;
    read('b.txt', contentBHandler); //3.read b.txt and pass handler function
}

var contentBHandler = (result) => { //4.read b.txt finished
    contentB = result;
    console.log(contentA, contentB); //5.print result
}

read๋ผ๋Š” ์ž‘์—…์„ ์œ„ํ•ด์„œ๋Š” UNIX API๊ฐ€ ๋ฐœ์ƒ์‹œํ‚ค๋Š” event๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ, JavaScript๋Š” ์ด event์˜ ์ฒญ์ทจ์ž์ด๋‹ค. ์ฆ‰ event๋ฅผ ๋ฐœ์ƒ์ผœ - ๊ฒฐ๊ณผ์ ์œผ๋กœ event handler function์„ ์‹คํ–‰์‹œํ‚ค๋Š” ํƒ€์ด๋ฐ์€ UNIX API๊ฐ€ ์ •ํ•œ๋‹ค. JavaScript๋Š” ๊ทธ ํƒ€์ด๋ฐ์— event handler function์„ ์‹คํ–‰ํ•ด ๋‹ฌ๋ผ๊ณ  readํ•จ์ˆ˜์— argument(์ธ์ž)๋กœ ๋˜์ง€๋Š” ๊ฒƒ์ด๋‹ค.

JavaScript๊ฐ€ UNIX API๋ฅผ ์ง€์›ํ•˜์ง€๋Š” ์•Š๊ธฐ ๋•Œ๋ฌธ์—, Node.jsํ•˜๋ถ€์˜ C++ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ์ด ํ•ด๋‹น ์ž‘์—…์„ ๋Œ€์‹  ์‹คํ–‰ํ•˜๊ณ , Node.js runtime์ด JavaScript์ฝ”๋“œ์™€ C++ํ™•์žฅ ํ”„๋กœ๊ทธ๋žจ๊ฐ„์˜ ์—ฐ๊ฒฐ์„ ๊ด€๋ฆฌํ•œ๋‹ค. ๋”ฐ๋ผ์„œ Node.js๋Š” JavaScriptํ”„๋กœ์ ํŠธ์ด๊ธฐ๋„ ํ•˜์ง€๋งŒ, ์ „์ฒด๋กœ ๋ณด๋ฉด ๊ต‰์žฅํžˆ ํฐ C++ํ”„๋กœ์ ํŠธ์ด๋‹ค.

๋ฐฉ๊ธˆ C++๋ผ๊ณ  ํ•˜์˜€๋Š”๋ฐ, C++๋Š” JavaScript์™€ ๋‹ค๋ฅด๊ฒŒ ๊ธฐ๋ณธ์ ์œผ๋กœ asynchronose runtime์€ ์•„๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ synchronose๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š” C++, ๋” ๋‚˜์•„๊ฐ€ Operating System์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋Š” Node.js๊ฐ€ ์–ด๋–ป๊ฒŒ ํšจ์œจ์ ์ธ asynchronose I/O์„ ๊ตฌํ˜„ํ• ์ˆ˜ ์žˆ๋Š”๊ฐ€?

Node.js Internals

๊ฒฐ๋ก ์ ์œผ๋กœ ๋งํ•˜๋ฉด Node.js์˜ muilti-thread๊ธฐ๋ฐ˜์ด๋‹ค.

event loop์€ single-thread์ด์ง€๋งŒ, Node.js์˜ I/O call์„ ์ฒ˜๋ฆฌํ•˜๋Š” ํ•˜๋ถ€ ๊ตฌ์กฐ๋Š” multi-thread๊ธฐ๋ฐ˜์ด๋‹ค.

Node.js Internals

์ด ํ•˜๋ถ€๊ตฌ์กฐ๋Š” libuv๋ผ ๋ถˆ๋ฆฌ๋ฉฐ, thread pool์„ ์‚ฌ์šฉํ•ด thread๋ฅผ ์žฌ์‚ฌ์šฉ ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ, ํšจ์œจ์„ฑ์„ ๊ทน๋Œ€ํ™” ํ•œ๋‹ค. ์ด ์žฌ์‚ฌ์šฉ์ด sync๊ธฐ๋ฐ˜์˜ OS์—์„œ ํšจ์œจ์ ์ธ asynchronose I/O๋ฅผ ๋งŒ๋“œ๋Š” ์›๋™๋ ฅ์ธ ์…ˆ์ด๋‹ค.

๋•Œ๋ฌธ์— Node.js๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ์—๋Š” ์„ฑ๋Šฅ์ ์ธ ์ธก๋ฉด๋„ ์กด์žฌํ•˜์ง€๋งŒ, event loop์€ Node.js๋งŒ์˜ ์ „์œ ๋ฌผ์ด ์•„๋‹ˆ๋ฉฐ, libuv๋Š” ๋‹ค์–‘ํ•œ ์–ธ์–ด์˜ ํ•˜๋ถ€๊ตฌ์กฐ๋กœ์จ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ๋‹ค. ๋•Œ๋ฌธ์— Asynchronous I/O๋ฅผ ์ด์šฉ ํ•œ ๋†’์€ throughput์€ Node.js๋งŒ์˜ ์žฅ์ ์€ ์•„๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ Node.js๊ฐ€ ๊ทธ๋“ค๊ณผ์˜ ์œ ๋‹ˆํฌ ํ•จ์„ ๊ผฝ์œผ๋ผ ํ•œ๋‹ค๋ฉด ๋ฐ”๋กœ, asynchronous Programming์— ์ ํ•ฉํ•œ evaluation strategy์ด๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด์˜ ๊ฒฝ์šฐ synchronous๊ธฐ๋ฐ˜์˜ ์–ธ์–ด์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜•ํƒœ๋กœ asynchronous ๋Ÿฐํƒ€์ž„์„ ๊ตฌํ˜„ํ•˜์˜€์ง€๋งŒ, Node.js๋Š” ๊ธฐ๋ฐ˜ ๋ถ€ํ„ฐ asynchronousํ•˜๊ธฐ๋•Œ๋ฌธ์— ์–ธ์–ด์˜ ํ‘œํ˜„๋ ฅ์—์„œ ๋”์šฑ ์œ ์—ฐํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ ๋‹ค.

Evaluation strategy๋Š” Programming language์˜ implementation detail์— ๋”ฐ๋ผ์„œ ๊ฒฐ์ •๋˜๋Š”๋ฐ, callback function๊ณผ ๊ฐ™์€ ๋ถ€๋ถ„์ด ์ผ๋ก€์ด๋‹ค. ์ด ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋Š” ์ถ”ํ›„ ์ถ”๊ฐ€ํ•  ์˜ˆ์ •์ด๋ฉฐ, ์ด๋ฒˆ ๊ธ€์—์„œ ๊นŠ๊ฒŒ ๋‹ค๋ฃจ์ง€ ๋ชปํ•œ thread pool๋„ benchmark๊ณผ ๋”๋ถˆ์–ด ์ถ”ํ›„์— ๋‹ค๋ค„๋ณผ ์˜ˆ์ •์ด๋‹ค.


« ๋น„๋™๊ธฐ์˜ ํ•ต์‹ฌ Easy, safe watermarking and resizing with pixelmator on OS X »