[TIL] 동기, 비동기

이현동·2023년 1월 26일
0

TIL

목록 보기
15/59

동기와 비동기

동기란 데이터의 요청과 결과가 한 자리에서 동시에 일어나는 것을 말합니다. 요청을 하면 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 합니다.
비동기란 동시에 일어나지 않는다는 의미입니다. 요청한 결과가 동시에 일어나지 않을 것이라는 약속입니다.

ex) 브라우저를 실행시키는 시간이 약 10분이 소모된다고 가정했을 때, 브라우저가 실행되는10분이라는 시간 동안 사용자는 컴퓨터의 다른 프로그램들을동작시키지 못하며 브라우저가 켜지는 그 순간만을 계속 기다려야한다는 것입니다. 이 시간이 10분이든 100분이든 관계없이 한 개의 데이터 요청에 대한 서버의 응답이 이루어질 때까지 계속 대기해야만합니다. 하지만 비동기처리를 해주면 필요한 처리(예를 들어 UI)만 빠르게 실행시켜주고 시간이 걸리는 처리(예를 들어 서버와의 통신, 네트워크)들을 기다리지 않아도 됩니다.

싱글 스레드와 멀티 스레드

우선 스레드(thred)란 어떠한 프로그램 내에서, 특히 프로세스 내에서 실행되는 흐름의 단위를 말합니다. 일반적으로 한 프로그램은 하나의 스레드를 가지고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있습니다. 이러한 실행 방식을 멀티스레드(multithread)라고 한다.
결론부터 말하자면 자바스크립트는 싱글 스레드 입니다. 정확히 말해서 자바스크립트의 메인 스레드인 이벤트 루프(event loop)가 싱글 스레드이기 때문에 javascript를 싱글 스레드 언어라고 부릅니다. 하지만 이벤트 루프만 독립적으로 실행되는 것이 아니라 브라우저나 Node.js와 같은 멀티 스레드 환경에서 실행됩니다. 즉, 자바스크립트 자체는 싱글 스레드가 맞지만 javascript 런타임은 싱글 스레드가 아닙니다.

정확히 말하자면 자바스크립트 엔진은 싱글스레드로 동작하지만, 비동기 처리를 하기 위해 있는 별도의 스레드(Web API, Task Queye)가 존재 합니다.

비동기 처리 과정

자바스크립트가 비동기 코드들을 어떻게 처리하는지 알기 위해서는 자바스크립트 런타임 환경에 대해 알아야 합니다. 간단하게 필요한 요소들만 정리했습니다!

Call stack : 실행 컨텍스트
Web API : 웹 브라우저에서 제공하는 API, 비동기 작업을 실행
Task Queue : Callback Queue라고도 하며, Web API에서 넘겨 받은 Callback 함수 저장
Event Loop : Call Stack이 비어 있으면 Task Queue의 작업을 Call Stack 으로 옮김

그림과 함께 비동기 코드가 동작하는 과정을 알아보겠습니다.

setTimeout(() => console.log('hdlee0619'));
console.log('hello');

  1. setTime 함수가 실행되면서 Call Stack에 추가
  2. setTime 함수는 자바스크립트 엔진이 처리하지 않고 Web API가 처리
  3. API 요청 시간(설정한 시간)이 지나면 Task Queuefh Call back 함수 전달

2줄에 작성한 hello가 Call Stack추가 되고, hello가 출력

  1. 자바스크립트의 Event Loop가 Call Stack이 비어있는지 항상 확인하는데, 비어있고 Task Queue에 Call back 함수가 있으면 Call Stack으로 옮김

hdlee0619 출력

모든 작업이 끝나면 Call Stack과 Task Queue가 비워짐

비동기 처리 하는 방법

콜백 지옥

step1(function (value1) {
    step2(function (value2) {
        step3(function (value3) {
            step4(function (value4) {
                // Do something
            });
        });
    });
});

콜백 지옥은 JavaScript를 이용한 비동기 프로그래밍시 발생하는 문제로서, 함수의 매개 변수로 넘겨지는 콜백 함수가 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상을 말합니다. 주로 이벤트 처리나 서버 통신과 같은 비동기적인 작업을 수행하기 위해 이런 형태가 자주 등장하는데, 이와 같은 코드는 가독성이 떨어지고, 코드를 수정하기 어려워집니다.
따라서 Promise, async/await 등을 활용하여 편리하고 가독성이 좋도록 코드를 작성해야 합니다.

Promise, async/await 사용해보기

class UserStorage{
    loginUser(id, password){
        return new Promise((resolve, reject) => { // Promise를 사용해 비동기 처리, 새로운 Promise는 executor가 자동으로 바로 실행됨을 유의
            setTimeout(() => {
                if(
                    (id === 'hdlee0619' && password === '0619')
                 ) {
                    resolve(id); // id와 password 일치시 id를 리턴
                 } else{
                    reject(new Error('에러 발생')); // 불일치 시 에러
                 }
            }, 2000);
        })
    }
    getRoles(user){
        return new Promise((resolve, reject) => {
            setTimeout(()=> {
                if (user === 'hdlee0619') {
                    resolve({name: 'hdlee', role: 'admin'}); // user 일치하면 user의 roles을 리턴
                } else {
                    reject(new Error('에러 발생')); // 불일치 시 에러
                }
            }, 1000);
        })
    }
};

const userStorage = new UserStorage();
const id = prompt("아이디를 입력해 주세요.");
const password = prompt("비밀번호를 입력해 주세요.");

async function checkUser() {
  try {
    const userId = await userStorage.loginUser(id, password);
    const user = await userStorage.getRoles(userId);
    alert(`Hello ${user.name}, you have a ${user.role}`);
  } catch (error) {
    console.log(error); 
  }
}
checkUser(); // checkUser 실행

결론

동기와 비동기를 시작하기 전에는 동기와 비동기가 어떤 것인지, 왜 필요한 것인지 몰랐는데 어떤 것인지와 필요한 이유를 알 수 있었다. 서버와 통신하면서 딜레이가 있을텐데, 전부 동기적으로 처리를 하게 되었을 때는 서버의 요청이 완료 될 때 까지 딜레이가 생기면서 발생할 문제들에 대해서 생각해 볼 수 있었습니다. 예를 들어 바로 화면에 보여져야할 UI가 나오지 않는다던지, 바로 실행되어야할 코드들이 실행되지 않는다던지 등..
적절한 비동기적인 처리를 통해서 많은 정보가 있는 현대 웹사이트를 보다 유동적, 효율적으로 움직이게 하기 위해서는 비동기적 프로그래밍이 필요하다는 것을 알게 되었습니다.


참고자료

비동기처리의 시작 콜백 이해하기, 드림코딩
프로미스 개념부터 활용까지, 드림코딩
javascript async와 await, 드림코딩
동기와 비동기의 차이, slobber
스레드(컴퓨팅), 위키백과
자바스크립트는 왜 싱글 쓰레드일까?
Callback Hell, seul06

profile
https://hdlee.dev

0개의 댓글