๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • What would life be If we had no courage to attemp anything?
Language/JavaScript

JavaScript - AJAX, Asynchronous (๋น„๋™๊ธฐ)

by DevIseo 2022. 5. 3.

*๏ธโƒฃAJAX

  • Asynchronous JavaScript And XML (๋น„๋™๊ธฐ์‹ JavaScript์™€ XML)
  • ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๊ธฐ ์œ„ํ•ด XMLHttpRequest ๊ฐ์ฒด๋ฅผ ํ™œ์šฉ
  • JSON, XML, HTML ๊ทธ๋ฆฌ๊ณ  ์ผ๋ฐ˜ ํ…์ŠคํŠธ ํ˜•์‹ ๋“ฑ์„ ํฌํ•จํ•œ ๋‹ค์–‘ํ•œ ํฌ๋งท์„ ์ฃผ๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
    • [์ฐธ๊ณ ] AJAX์˜ X๊ฐ€ XML์„ ์˜๋ฏธํ•˜๊ธด ํ•˜์ง€๋งŒ, ์š”์ฆ˜์€ ๋” ๊ฐ€๋ฒผ์šด ์šฉ๋Ÿ‰๊ณผ JavaScript์˜ ์ผ๋ถ€๋ผ ๋Š” ์žฅ์  ๋•Œ๋ฌธ์— JSON์„ ๋” ๋งŽ์ด ์‚ฌ์šฉํ•จ

|ํŠน์ง•

  • ํŽ˜์ด์ง€ ์ „์ฒด๋ฅผ reload(์ƒˆ๋กœ ๊ณ ์นจ)๋ฅผ ํ•˜์ง€ ์•Š๊ณ ์„œ๋„ ์ˆ˜ํ–‰๋˜๋Š” โ€œ๋น„๋™๊ธฐ์„ฑโ€
    • ์„œ๋ฒ„์˜ ์‘๋‹ต์— ๋”ฐ๋ผ ์ „์ฒด ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ์ผ๋ถ€๋ถ„๋งŒ์„ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Œ
  • AJAX์˜ ์ฃผ์š” ๋‘๊ฐ€์ง€ ํŠน์ง•์€ ์•„๋ž˜์˜ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์คŒ
  1. ํŽ˜์ด์ง€ ์ƒˆ๋กœ ๊ณ ์นจ ์—†์ด ์„œ๋ฒ„์— ์š”์ฒญ
  2. ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ณ  ์ž‘์—…์„ ์ˆ˜ํ–‰

|XMLHttpRequest ๊ฐ์ฒด

  • ์„œ๋ฒ„์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋ฉฐ ์ „์ฒด ํŽ˜์ด์ง€์˜ ์ƒˆ๋กœ ๊ณ ์นจ ์—†์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์˜ฌ ์ˆ˜ ์žˆ์Œ
  • ์‚ฌ์šฉ์ž์˜ ์ž‘์—…์„ ๋ฐฉํ•ดํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ํŽ˜์ด์ง€ ์ผ๋ถ€๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Œ
  • ์ฃผ๋กœ AJAX ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์‚ฌ์šฉ
  • ์ด๋ฆ„๊ณผ ๋‹ฌ๋ฆฌ XML๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์Œ
  • ์ƒ์„ฑ์ž
    • XMLHttpRequest()

|XMLHttpRequest ์˜ˆ์‹œ

  • console์— todo ๋ฐ์ดํ„ฐ๊ฐ€ ์ถœ๋ ฅ๋˜์ง€ ์•Š์Œ
  • ๋ฐ์ดํ„ฐ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  console.log() ๋ฅผ ๋จผ์ € ์‹คํ–‰ํ–ˆ๊ธฐ ๋•Œ๋ฌธ
//์˜›๋‚ ์— ์“ฐ๋Š” ๋ฐฉ์‹์ž„..
const request = new XMLHttpRequest()
const URL = '<https://jsonplaceholder.typicode.com/todos/1/>'

request.open('GET',URL)
request.send()

const todo = request.response
console.log(`data: ${todo}`)

*๏ธโƒฃAsynchronous JavaScript

|๋™๊ธฐ์‹

  • ์ˆœ์ฐจ์ , ์ง๋ ฌ์  Task ์ˆ˜ํ–‰
  • ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„ ์‘๋‹ต์„ ๋ฐ›์•„์•ผ๋งŒ ๋‹ค์Œ ๋™์ž‘์ด ์ด๋ฃจ์–ด์ง (blocking)
  •  

<button>๋ฒ„ํŠผ<button>
<script>
	const btn = document.querySelector('button')
	btn.addEventListener('click', function() {
		alert('you click me!')
		const pElem = document.createElement('p')
		pElem.innerText = 'sample text'
		document.body.appendChild(pElem)
	})
</script>

๋ฒ„ํŠผ ํด๋ฆญ ํ›„ alert ๋ฉ”์„ธ์ง€์˜ ํ™•์ธ ๋ฒ„ํŠผ ๋ˆ„๋ฅผ ๋•Œ ๊นŒ์ง€ ๋ฌธ์žฅ์ด ๋งŒ๋“ค์–ด ์ง€์ง€ ์•Š์Œ!

|๋น„๋™๊ธฐ์‹(Asynchronous)

  • ๋ณ‘๋ ฌ์  Task ์ˆ˜ํ–‰
  • ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„ ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ๋™์ž‘์ด ์ด๋ฃจ์–ด์ง (non-blocking)
  •  

const request = new XMLHttpRequest()
const URL = '<https://jsonplaceholder.typicode.com/todos/1/>'

request.open('GET',URL)
request.send()

const todo = request.response
console.log(`data: ${todo}`)
  • ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค์Œ ์ฝ”๋“œ ์‹คํ–‰.
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ณ€์ˆ˜ todo์— ์‘๋‹ต ๋ฐ์ดํ„ฐ ํ• ๋‹น๋˜์ง€ ์•Š๊ณ  ๋นˆ ๋ฌธ์ž์—ด ์ถœ๋ ฅ
  • JavaScript๋Š” single threaded๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘

|์™œ ๋น„๋™๊ธฐ์‹์„ ์‚ฌ์šฉํ•˜๋Š”๊ฐ€? === โ€œ์‚ฌ์šฉ์ž ๊ฒฝํ—˜โ€

โ€ข ๋งค์šฐ ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋™๋ฐ˜ํ•˜๋Š” ์•ฑ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
โ€ข ๋™๊ธฐ์‹ ์ฝ”๋“œ๋ผ๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜จ ๋’ค ์•ฑ์ด ์‹คํ–‰๋จ
	โ€ข ์ฆ‰, ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ๊นŒ์ง€๋Š” ์•ฑ์ด ๋ชจ๋‘ ๋ฉˆ์ถ˜ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž„
	โ€ข ์ฝ”๋“œ ์‹คํ–‰์„ ์ฐจ๋‹จํ•˜์—ฌ ํ™”๋ฉด์ด ๋ฉˆ์ถ”๊ณ  ์‘๋‹ตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณต
โ€ข ๋น„๋™๊ธฐ์‹ ์ฝ”๋“œ๋ผ๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ณ  ์‘๋‹ต ๋ฐ›๋Š” ๋™์•ˆ, ์•ฑ ์‹คํ–‰์„ ํ•จ๊ป˜ ์ง„ํ–‰ํ•จ
	โ€ข ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋™์•ˆ ์ง€์†์ ์œผ๋กœ ์‘๋‹ตํ•˜๋Š” ํ™”๋ฉด์„ ๋ณด์—ฌ์คŒ์œผ๋กœ์จ ๋”์šฑ ์พŒ์ ํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณต
โ€ข ๋•Œ๋ฌธ์— ๋งŽ์€ ์›น API ๊ธฐ๋Šฅ์€ ํ˜„์žฌ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰๋จ

|Threads๋ž€?

  • ํ”„๋กœ๊ทธ๋žจ์ด ์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ์ผ ํ”„๋กœ์„ธ์Šค
  • ๊ฐ thread(์Šค๋ ˆ๋“œ)๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์ž‘์—…๋งŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
  • ์˜ˆ์‹œ) Task A โ†’ Task B โ†’ Task C
    • ๋‹ค์Œ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ ์•ž์˜ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์–ด์•ผ ํ•จ
    • ์ปดํ“จํ„ฐ CPU๋Š” ์—ฌ๋Ÿฌ ์ฝ”์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ผ์„์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

|โ€œJavaScript๋Š” single threaded ์ด๋‹ค.โ€

  • ์ปดํ“จํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ CPU๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„ main thread๋ผ ๋ถˆ๋ฆฌ๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ๋งŒ ์ž‘์—… ์ˆ˜ํ–‰
  • ์ฆ‰, ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” Call Stack์ด ํ•˜๋‚˜์ธ ์–ธ์–ด๋ผ๋Š” ์˜๋ฏธ
  • ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด JavaScript๋Š”
  1. ์ฆ‰์‹œ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋Š” ์ด๋ฒคํŠธ๋“ค์„ **๋‹ค๋ฅธ ๊ณณ(Web API)**์œผ๋กœ ๋ณด๋‚ด์„œ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•˜๊ณ ,
  2. ์ฒ˜๋ฆฌ๋œ ์ด๋ฒคํŠธ๋“ค์€ ์ฒ˜๋ฆฌ๋œ ์ˆœ์„œ๋Œ€๋กœ **๋Œ€๊ธฐ์‹ค(Task queue)**์— ์ค„์„ ์„ธ์›Œ ๋†“๊ณ 
  3. Call Stack์ด ๋น„๋ฉด **๋‹ด๋‹น์ž(Event Loop)**๊ฐ€ ๋Œ€๊ธฐ ์ค„์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ(์ œ์ผ ์•ž์˜) ์ด๋ฒคํŠธ๋ฅผ Call Stack์œผ๋กœ ๋ณด๋ƒ„

|Concurrency model

  • Event loop๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ๋™์‹œ์„ฑ ๋ชจ๋ธ(Concurrency model)
  1. Call Stack
  2. ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค ํ•ด๋‹น ์š”์ฒญ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” Stack(LIFO) ํ˜•ํƒœ์˜ ์ž๋ฃŒ ๊ตฌ์กฐ
  3. Web API (Browser API)
    1. JavaScript ์—”์ง„์ด ์•„๋‹Œ ๋ธŒ๋ผ์šฐ์ € ์˜์—ญ์—์„œ ์ œ๊ณตํ•˜๋Š” API
    2. setTimeout(), DOM events ๊ทธ๋ฆฌ๊ณ  AJAX๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์‹œ๊ฐ„์ด ์†Œ์š”๋˜๋Š” ์ผ๋“ค์„ ์ฒ˜๋ฆฌ
  4. Task Queue (Event Queue, Message Queue)
    1. ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋œ callback ํ•จ์ˆ˜๊ฐ€ ๋Œ€๊ธฐํ•˜๋Š” Queue(FIFO) ํ˜•ํƒœ์˜ ์ž๋ฃŒ
    2. main thread๊ฐ€ ๋๋‚œ ํ›„ ์‹คํ–‰๋˜์–ด ํ›„์† JavaScript ์ฝ”๋“œ๊ฐ€ ์ฐจ๋‹จ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€
  5. Event Loop
    1. Call Stack์ด ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
    2. ๋น„์–ด ์žˆ๋Š” ๊ฒฝ์šฐ Task Queue์—์„œ ์‹คํ–‰ ๋Œ€๊ธฐ ์ค‘์ธ callback ํ•จ์ˆ˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
    3. Task Queue์— ๋Œ€๊ธฐ ์ค‘์ธ callback ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” callback ํ•จ์ˆ˜๋ฅผ Call Stack์œผ๋กœ push
console.log('Hello SSAFY!') 
setTimeout(function(){
    console.log('I am from setTimeout')
}, 10000)

console.log('Bye SSAFY!')
Call Stack์— ๋จผ์ € console.log('Hello SSAFY!') ๊ฐ€ ๋“ค์–ด๊ฐ€ ์‹คํ–‰๋œ ํ›„ ๋น„์›Œ์ง„๋‹ค.
๊ทธ ํ›„ setTimeout()์ด ๋“ค์–ด๊ฐ€์ง€๋งŒ, setTimeout()์˜ ๊ฒฝ์šฐ 
AJAX๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์‹œ๊ฐ„์ด ์š”์†Œ๋˜๋Š” ์ผ๋“ค์„ Web API๋กœ ๋ณด๋‚ธ๋‹ค.
๊ทธ๋ฆฌ๊ณ  Call Stack์— console.log('Bye SSAFY!')์ด ์‹คํ–‰๋œ ํ›„ ๋น„์›Œ์ง„๋‹ค.
Web API๋กœ ๋ณด๋‚ด์ง„ setTimeout()์€ Task Queue๋กœ ๋ณด๋‚ด์ง€๋Š”๋ฐ, 
Event Loop๊ฐ€ Call Stack์— console.log('Bye SSAFFY!')๊ฐ€ ์‹คํ–‰ํ›„ ๋น„์›Œ์ง€๋Š” ๊ฑธ ํ™•์ธ ํ›„ 
Call Stack์— setTimeout()์„ pushํ•ด์ค€๋‹ค.
//์‹คํ–‰๊ฒฐ๊ณผ
Hello SSAFY!
Bye SSAFY!
I am from setTimeout

|Zero delays

  • ์‹ค์ œ๋กœ 0ms ํ›„์— callback ํ•จ์ˆ˜๊ฐ€ ์‹œ์ž‘๋œ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ์•„๋‹˜
  • ์‹คํ–‰์€ Task Queue์— ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… ์ˆ˜์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋ฉฐ ํ•ด๋‹น ์˜ˆ์‹œ์—์„œ๋Š”callback ํ•จ์ˆ˜์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ฒ˜๋ฆฌ๋˜๊ธฐ ์ „์— โ€˜Hiโ€™์™€ โ€˜Byeโ€™๊ฐ€ ๋จผ์ € ์ถœ๋ ฅ๋จ
  • ์™œ๋ƒํ•˜๋ฉด delay(์ง€์—ฐ)๋Š” JavaScript๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œ ์‹œ๊ฐ„์ด๊ธฐ ๋•Œ๋ฌธ(๋ณด์žฅ๋œ ์‹œ๊ฐ„์ด ์•„๋‹˜)
  • ๊ธฐ๋ณธ์ ์œผ๋กœ setTimeout ํ•จ์ˆ˜์— ํŠน์ • ์‹œ๊ฐ„ ์ œํ•œ์„ ์„ค์ •ํ–ˆ๋”๋ผ๋„ ๋Œ€๊ธฐ ์ค‘์ธ ๋ฉ”์‹œ์ง€์˜ ๋ชจ๋“  ์ฝ”๋“œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•ด์•ผ ํ•จ

|์ˆœ์ฐจ์ ์ธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌํ•˜๊ธฐ

  • Web API๋กœ ๋“ค์–ด์˜ค๋Š” ์ˆœ์„œ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š๊ณ , ์–ด๋–ค ์ด๋ฒคํŠธ๊ฐ€ ๋จผ์ € ์ฒ˜๋ฆฌ๋˜๋Š๋ƒ๊ฐ€ ์ค‘์š” (์ฆ‰, ์‹คํ–‰ ์ˆœ์„œ ๋ถˆ๋ช…ํ™•)
  • ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ˆœ์ฐจ์ ์ธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ 2๊ฐ€์ง€ ์ž‘์„ฑ ๋ฐฉ์‹
  1. Async callbacks โ€ข ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰์„ ์‹œ์ž‘ํ•  ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ ์ธ์ž๋กœ ์ง€์ •๋œ ํ•จ์ˆ˜ โ€ข ์˜ˆ์‹œ) addEventListener() ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ž
  2. promise-style โ€ข Modern Web APIs์—์„œ์˜ ์ƒˆ๋กœ์šด ์ฝ”๋“œ ์Šคํƒ€์ผ โ€ข XMLHttpRequest ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ตฌ์กฐ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ํ˜„๋Œ€์ ์ธ ๋ฒ„์ „

๋Œ“๊ธ€