ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JS] 비동기 처리와 Callback
    FrontEnd/JavaScript 2022. 6. 17. 16:58

    비동기 처리와 Callback

    비동기적 프로그래밍

    동기적(Synchronous) vs 비동기적(Asynchronous)

    • 동기적 방식
      • 어떤 작업을 요청하면 시간과 관계없이 요청한 자리에 응답이 주어지는 방식
      • 한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 차례를 기다리는 것
      • 단일 스레드(싱글 쓰레드)라고 불림
      • ex. 음식점 테이블이 만석일 때 대기팀이 10팀일 경우, 동기적 방식으로 운영한다면 자리가 날 때 한 팀씩 착석을 하고 남은 팀은 꼼짝없이 음식점에서 기다려야 함
    • 비동기적 방식
      • 어떤 작업을 요청하면 응답이 주어질 때까지 기다리지 않고 응답에 관계없이 바로 다음 작업이 실행되는 방식
      • 요청과 동시에 응답이 주어지지 않음
      • 여러 작업을 동시에 처리할 수 있고 대기하는 과정에서 다른 함수 호출 가능
      • ex. 음식점 테이블이 만석일 때 대기팀이 10팀일 경우, 비동기적 방식으로 운영한다면 대기자 명단에 이름을 적고 다른 행동을 할 수 있고 자신의 차례가 되면 착석할 수 있음

    Javascript : 동기적이면서 비동기적인 언어(?)

    • 동기적, Blocking, single-threaded한 언어
    • 위의 특징은 하나의 연산 시에만 해당
    • 효율적인 프로그래밍을 위해 Javascript가 비동기적 방식으로 동작할 수 있는 방법 제시

    JavaScript의 비동기적 프로그래밍 구현 방식

    • Callback 함수
      • 특정 함수에 매개변수로 전달된 함수
        ex. 음식점 대기자 명단에 적어놓고 다른 행동(쇼핑 등)을 하다가 내 차례가 되어 전화가 왔을 때(= 콜백 함수가 호출되었을 때) 음식점에서 주문하여 음식을 먹을 수 있음(= 함수 실행)
      • callback 함수를 넘겨받은 함수는 callback 함수를 필요에 따라 즉시 실행하거나 나중에 호출 가능
      • callback 지옥
        • 콜백 함수를 익명함수로 전달하는 과정에서 또다시 콜백 안에 함수 호출이 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상
        • 주로 이벤트 처리나 서버 통신과 같은 비동기 작업을 제어하기 위해 사용되는데 이 경우 가독성이 떨어지고 코드 수정이 어려워짐

     

    • Promise
      • 비동기적으로 실행하는 작업의 결과(성공 or 실패)를 나타내는 객체
      • 비동기의 결과를 객체화 시킬 수 있는 특징
        (장점이기도 하다! 객체를 이용하여 js 메소드 사용 가능)
      • 기본적으로 콜백 함수와 같은 기능을 하며 콜백 지옥을 해결할 수 있음
      • Promise 생성자 함수의 인자로 들어오는 함수
        • executor()
          • 첫 번째 인자 : resolve()
          • 두 번째 인자 : reject()
      • Promise 상태
        • Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태
        • Fulfilled(이행) : 비동기 처리가 성공적으로 완료됨
          • resolve() 함수가 실행되고 Fulfilled 상태가 되며, then() 메서드를 이용한 체이닝이 가능
        • Rejected(실패) : 비동기 처리 실패 또는 오류
          • reject () 함수가 실행되고 Rejected 상태가 되며, 발생한 에러를 catch 메서드로 받아 처리 가능
          •  
      • new 연산자와 함께 호출하고 인자로 콜백을 받음
      • Promise는 Promise를 반환
      • Promise는 호출될 때 바로 실행되지만 그 안에 콜백은 resolve, reject 둘 중 하나가 호출되기 전에 then 또는 catch로 넘어가지 않음
      • resolve, reject로 성공 혹은 실패로 결과 값을 나타내어 다음 작업을 체이닝 가능(비동기 제어 가능)
      • then으로 작업을 이어가기 위해서는 resolve() 함수 호출
      • 작업을 중단 또는 err 처리를 위해서는 reject() 함수 호출 

     

    • Promise + async/await
      • 가장 최근 자바스크립트 문법에 추가된 비동기 처리 패턴
      • 가독성 보완
      • 비동기 작업을 수행하고자 하는 함수 앞에 async 예약어를 붙이고, 함수 내부에서 실질적인 비동기 작업이 필요한 위치마다 await을 표기
      • async 키워드가 붙은  Promise는 반드시 Promise를 반환해야 함
      • await 키워드가 붙은 Promise는 Promise가 아닌 resolve()에 들어간 인자 return
      • await의 의미는 말그대로 함수 실행이 끝날 때까지 기다려줘라! 라는 뜻
        awai 문은 Promise가 fulfill되거나 reject될 때까지 async 함수의 실행을 일시 정지하고, Promise가 fulfill 되면 async 함수를 일시정지한 부분부터 실행
      • 에러는 try-catch 문을 사용하여 처리

     

    Javascript Runtime : 브라우저

    • Javascript Engine : Google V8
      • 구성요소
        • Memory Heap : 메모리 할당이 일어나는 곳
          • 변수와 객체의 메모리 할당에 사용되는 비정형 메모리
        • Call Stack : 코드 실행에 따라 호출 스택이 쌓이는 곳
          • JS는 Single Threaded Programming Language -> Single Call Stac
          • 호출 스택이 하나이므로, 한 번에 한 가지 작업만 가능
          • 현재 프로그램 상 위치를 기록하는 자료구조
          • 실행 커서가 함수 안에 들어가면 해당 함수가 호출 스택의 가장 상단에 위치
          • 함수 실행이 끝나면 호출 스택에서 제거됨어떤 시점에 함수 호출 횟수가 호출 스택의 최대 허용치를 넘게 되면 브라우저가 에러 발생시킴싱글 쓰레드 환경에서 호출 스택에 처리 시간이 오래 걸리는 함수가 있으면 함수가 실행되는 동안 브라우저의 동작이 정지됨 (매끄럽지 못한 페이지 렌더링 동작)
      • JS Engine은 자체적으로 비동기 지원 X
      • JS Engine(V8)은 브라우저에서 제공하는 API를 이용해 네트워크 요청 
    • Web APIs
      • 브라우저에서 제공하는 APIs로 비동기 작업 수행
        • DOM(document)의 EventHandler
          • 마우스, 키보드 동작(click, keydown 등)
            • 페이지 로딩
        • 서버에 자원 요청 및 응답
          • AJAX(XMLHttpRequest) : HTTP 요청
            • fetch API
        • Timer
          • 타이머 API(setTimeout 등)
          • 애니메이션 API(requestAnimationFrame)
      • Web APIs는 비동기적으로 네트워크 요청
    • Task Queue
      • Web API 결과값을 쌓아두는 큐
        • ex. JS에서 setTimeout(a, 5000)을 호출하면 Web API는 타이머를 동작시켜 5초 후에 task queue에 a를 쌓음

    • Event Loop
      • 비동기 콜백 기능 수행
      • 기능 수행 조건
        • 자바스크립트 엔진 내 호출 스택이 비어있고,
        • 런타임 환경 내 이벤트 큐(task queue)에 실행 대기 중인 비동기 함수가 있을 경우
        • 대기중인 함수를 호출 스택에 푸쉬하는 기능 수행
      • 이벤트 루프의 역할
        • 호출 스택(call stack)과 Task Queue를 주시하는 것
          • 콜 스택이 비어있으면 큐의 첫 번째 콜백을 호출 스택에 쌓아 효율적 실행 가능
          • 콜 스택이 빌 때까지 기다렸다가 task queue에 있는 콜백을 호출 스택에 넣어줌

     

    • 비동기 작업 실행 순서
    1. JS 코드가 Call Stack에 쌓인 후 실행됨
    2. JS Engine이 비동기 함수를 Web API에 넘김
    3. Web API는 비동기 작업을 수행한 후 콜백 함수를 Event Loop를 통해 Task Queue에 넘김
    4. Event Loop는 Call Stack이 빌 때까지 기다렸다가 Task Queue에서 대기하고 있던 콜백 함수를 Call Stack으로 넘김
    5. Call Stack에 쌓인 콜백 함수가 실행된 후 Call Stack에서 제거됨

     

     

     

     

    Ajax / Axios / fetch / XMLHttpRequest

    Ajax(Asynchronous JavaScript And XML)

    • 빠르게 동작하는 동적인 웹 페이지 개발을 위한 기법
    • 웹 페이지 전체를 다시 로딩하지 않고 일부만 갱신 가능

     

    • XMLHttpRequest 객체
      • Ajax의 핵심 구성요소
      • Ajax에서 웹 브라우저가 서버와 데이터를 교환할 때 사용
    • 장점
      • jQuery를 통해 쉽게 구현 가능
      • error, success, complete의 상태를 통해 실행 흐름 조절 가능
    • 단점
      • jQuery를 사용해야 호환성이 보장되고 간편
      • promise 기반이 아님

    fetch API

    • 특징
      • XMLHttpRequest 대체 (비동기 http 요청을 더 편하기 하기 위해)
      • Promise 기반으로 동작 -> 콜백 지옥 탈출
    • 장점
      • JS 내장 라이브러리이기 때문에 import 없이 사용 가능
      • React Native의 경우 잦은 업데이트로 라이브러리가 쫓아가지 못하는 경우가 있는데 이를 방지
    • 단점
      • 응답 결과 Response 객체 -> JSON 또는 text로 변환 과정 필요
      • 구형 브라우저에서는 지원 X
      • 네트워크 에러 발생시 계속 대기 (response timeout X)
      • API 요청 취소 불가
    • 사용법
      • 기본적으로 첫 번째 인자에 요청 url이 들어가며 http 메소드 중 GET 으로 동작
      • fetch를 통해 ajax 호출 시 해당 주소에 요청을 보낸 다음, 응답 객체를 받음
      • GET : 존재하는 자원 요청
        • 옵션 인자가 필요 없음, default type
        • fetch(url)
      • POST : 새로운 자원 생성 요청
        • fetch(url, {method: “POST”, headers, body})
          • method : HTTP 메서드
          • headers : 데이터 객체 타입
          • body : 보내려는 데이터(요청 본문)로 string이나 FormData, BufferSource, Blob, UrlSearchParams
      • PUT : 존재하는 자원 변경 요청
        • fetch(url, {method: “PUT”, headers, body})
          • method : HTTP 메서드
          • headers : 데이터 객체 타입
          • body - 데이터 자체를  body로 대체
      • PATCH : 존재하는 자원 일부 변경 요청
        • fetch(url, {method: “PATCH”, header, body})
          • method : HTTP 메서드
          • headers : 데이터 객체 타입
          • body - 데이터의 일부를 value를 body로 대체
      • DELETE : 존재하는 자원 삭제 요청
        • fetch(url, {method: “DELETE});
          • 보낼 데이터가 없으므로 headers, body X
      • response 프로퍼티와 메서드
        • fetch를 통해 요청하고 서버로부터 응답을 받으면 .then을 통해 함수의 인자에 response 객체가 담김
        • response.status : http 상태 코드
        • response.ok : http 상태 코드가 200과 299 사이일 경우 true
        • response.body : 내용
        • response.text() : 응답을 읽고 텍스트로 반환
        • response.json() : 응답을 JSON 형태로 parsing

     

     

    Axios

    • 특징
      • 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리
      • Promise 기반으로 동작
      • React에서 주로 사용됨
    • 장점
      • 크로스 브라우징 기반으로 브라우저 호환성 Good
      • 자동으로 JSON 형식으로 변환
      • 요청 취소 및 타임아웃 설정이 가능
      • fetch에 존재하지 않는 기능이 더 많음
        • response timeout 처리 방법 등
    • 단점
      • 라이브러리 설치 필요
    • 사용법
      • GET : 입력한 url에 존재하는 자원에 대한 요청
        • 형태 : axios.get(url, [,config])
      • POST : 새로운 리소스 생성(create)
        • 형태 : axios.post(url, { data 객체 }, [,config])
      • DELETE : REST 기반 API 프로그램에서 데이터베이스에 저장되어 있는 내용을 삭제하는 목적으로 사용
        • 형태 : axios.delete(url, [,config]);
      • PUT : REST 기반 API 프로그램에서 데이터베이스에 저장되어 있는 내용을 삭제하는 목적으로 사용
        • 형태 : axios.put(url[, data[, config]]);

     

     

     

     

     

     

     

     

    출처 :

    https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous/Introducing

    https://hanamon.kr/javascript-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%9E%91%EB%8F%99-%EB%B0%A9%EC%8B%9D-%EB%B9%84%EB%8F%99%EA%B8%B0%EC%99%80-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84/

    https://velog.io/@eunoia/JavaScript-Asynchronous

    https://velog.io/@dev-mish-mash/Task-queue%EC%97%90-%EB%8C%80%ED%95%9C-%EC%98%A4%ED%95%B4-%EC%A0%95%EB%A6%AC

    https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/
    https://ghost4551.tistory.com/139

     

    댓글

Designed by Tistory.