비동기 통신

Jemin·2023년 5월 16일
0

Computer Science

목록 보기
5/31
post-thumbnail

동기, 비동기 통신이란?

기본적으로 하나의 컴퓨터는 각각의 자원을 하나씩만 가지기 때문에 프로그래밍 세계에서는 각 개별 기능들이 동기적으로(순차적으로) 수행되는 것이 더 자연스럽다.

자바스크립트는 싱글스레드로 작동되는 프로그래밍 언어이기 때문에 동시에 두 개의 함수가 실행될 수 없다. 따라서 작업의 효율을 높이기 위해 비동기 처리가 필요하다.

비동기 통신

비동기 통신은 데이터나 요청을 동기적으로 처리하는 것이 아니라, 작업을 백그라운드에서 비동기적으로 처리하는 방식이다. 비동기 통신은 웹 개발에서 많이 사용되며, 네트워크 요청, 파일 입출력, 데이터베이스 조회 등 다양한 작업에 적용된다. 이를 통해 웹 애플리케이션은 응답 대기 시간을 최소화하고, 사용자 경험을 향상시킬 수 있다.

비동기 통신의 주요 개념 & 기술

  1. 콜백(Callback): 비동기 작업이 완료되면 호출되는 함수로서, 비동기 작업의 결과를 처리하거나 다음 동작을 지정한다. 콜백 함수는 비동기 함수의 인자로 전달되어 실행된다.

  2. Promise: 콜백 지옥(Callback Hell)을 해결하기 위한 비동기 처리 패턴이다. Promise는 비동기 작업의 결과를 나타내는 객체로서, 성공(resolve) 또는 실패(reject) 상태를 가진다. 비동기 작업의 결과가 나중에 완료될 수 있다.

  3. async/await: 비동기 작업을 동기적인 코드처럼 작성할 수 있는 문법이다. async 함수 내에서 await 키워드를 사용하여 비동기 작업의 완료를 기다릴 수 있다. async 함수는 Promise를 반환하며, 비동기 작업이 완료되면 해당 Promise가 resolve되고, 실패하면 reject된다.

  4. AJAX(Asynchronous JavaScript ans XML): 비동기적으로 서버와 데이터를 교환하기 위한 기술이다.

  5. Fetch API: 웹 브라우저에서 제공하는 비동기 통신을 위한 API다.

모던 브라우저는 어떻게 비동기 로직을 처리하는가?

자바스크립트는 싱글스레드 언어이기 때문에 멀티스레딩을 지원하지 않는다. 하지만 자바스크립트 함수로 호출한 브라우저의 Web API는 서로 다른 스레드에서 동시에 실행된다. 물론 서버에 요청한 API 역시 서버에서 실행되므로 자바스크립트 스레드를 방해하지 않고 수행된다. 브라우저의 콜 스택에는 호출된 함수들이 스택 구조로 쌓이는데, 비동기 함수는 처리되는 동안 콜 스택에서 기다리는 것이 아니라 곧바로 사라진다.

콜 스택에 대한 자료: 자바스크립트 호출 스택(Call Stack) 이해하기

비동기 함수가 완료된 이후의 동작은 콜백 함수를 통해서 이루어진다.

  1. 비동기 함수를 호출할 때 인자로 콜백 함수를 넘겨준다.

  2. 콜백 함수가 별도의 메시지큐에 쌓여 다시 콜 스택에 쌓이기를 기다린다.

  3. 브라우저의 이벤트 루프는 주기적으로 콜 스택을 확인하고 콜 스택이 비면 메시지큐의 태스크를 콜 스택으로 이동시킨다.

이러한 원리로 콜 스택은 비동기 함수가 처리되는 동안 정체되지 않고 다음 태스크를 수행할 수 있다.

자바스크립트는 어떻게 비동기 로직을 지원해왔나?

전통적으로 비동기 처리는 콜백 함수를 통해 이루어졌다. 그러나 이 방식은 호출하는 비동기 함수의 깊이가 깊어질수록 에러 핸들링이 까다롭다.

콜백 함수를 중첩해서 호출하다 보면 소위 말하는 "콜백 지옥 현상"이 발생한다. 콜백 지옥이란 비동기 함수를 호출하는 과정에서 콜백 함수의 깊이가 감당하기 힘들 정도로 깊어지는 현상이다.

자바스크립트 ES6에서는 비동기 함수의 성공과 실패 여부를 thencatch라는 별도의 블록으로 구분해서 받을 수 있는 Promise 패턴을 지원한다. Promise 객체는 Promise 생성자 함수를 사용하여 만들며, 이 생성자 함수는 콜백 함수를 인자로 받는다.

이 함수는 resolve, reject라는 인자를 순서대로 받고, 각각의 함수를 통해 성공과 실패 케이스에 대해 처리할 수 있다.

  • resolve 시킨 결과는 호출자 입장에서 then블록으로 받을 수 있다.

  • reject 시킨 결과는 호출자 입장에서 catch블록으로 받을 수 있다.

만약 반드시 여러 개의 비동기 함수 호출이 모두 완료된 후 수행해야 할 태스크가 있다면, 이 부분은 동기적으로 수행되어야 하는 상황으로 볼 수 있다. 이런 상황을 위해 자바스크립트 ES8에서는 async/await 구문이 도입되었다. async 예약어를 붙여서 선언한 함수는 리턴 타입이 Promise객체이다. Promise객체의 최종 결괏값을 받기 위해서는 then-catch블록으로 받거나, async함수를 호출할 때 await예약어를 붙여서 호출하면 된다. await로 호출한 비동기 함수는 동기 함수처럼 동작하여, 해당 코드 라인이 완료되어 콜백 함수의 결괏값이 받아진 이후에 다음 코드 라인이 실행된다.

동기와 비동기

메인 함수가 큰 태스크를 처리하기 위해 작은 태스크를 담당하는 서브 함수를 호출하거나 외부 서비스 API를 호출하게 된다. 이 때 메인 함수를 호출자, 서브 함수나 API를 피호출자라고 부른다.

동기와 비동기는 호출자와 피호출자의 수행 시점과 관련이 있다. 만약 메인 함수가 첫 번째 태스크를 처리하기 위해 서브 함수를 호출하고, 서브 함수의 처리결과를 받아서 확인한 후에 두 번째 태스크를 수행한다면 이는 동기적인 로직(Sync)이다.

반면 메인 함수가 서브 함수를 호출만 할 뿐, 서브 함수의 처리 결과를 확인하지 않고 두 번째 태스크를 수행한다면 이는 비동기적인 로직(Async)이다.

참고
주니어 웹 개발자가 알아야 할 '비동기 통신'

profile
경험은 일어난 무엇이 아니라, 그 일어난 일로 무엇을 하느냐이다.

0개의 댓글