[JavaScript] 동기(Synchronous)와 비동기(Asynchronous), 콜백 함수

J·2023년 6월 17일
1

JavaScript

목록 보기
10/11

동기 synchronous

console.log(1);
console.log(2);
console.log(3);

// 차례 대로
// 1
// 2
// 3
  • 자바스크립트는 싱글 스레드 기반의 언어로, 하나의 작업을 한 번에 처리함.
  • 이는 하나의 작업이 완료되어야 다음 작업이 시작됨을 말함. 한 번에 하나 씩 순차적으로 실행.
  • 코드의 실행 순서와 결과가 명확하지만, 긴 실행 시간을 가진 작업이 있을 경우엔? 그 작업으로 인해 다음 작업이 멈춰있음.
  • 이를 해결하기 위해 Event Loop 라는 메커니즘을 활용하여 비동기 처리를 수행.

Single-Threaded?

  • 한 번에 오직 하나의 작업만 처리할 수 있는 시스템 구조. 동기적 특성을 가짐.

Event Loop?

  • 자바스크립트의 비동기 처리를 가능하게 하는 핵심 구조.
  • 콜 스택, 콜백 큐 등을 이용해 동시성 관리.
    1. Call Stack : 현재 실행중인 작업과 실행될 함수들이 쌓이는 곳. LIFO(Last In First Out) 순서대로 함수 실행 및 제거.
    2. Callback Que : 비동기 작업이 완료되면 콜백 함수가 콜백 큐에 쌓임. FIFO(First In First Out) 순서대로 함수 실행.
    3. 그 외 setTimeOut 등의 메서드를 통해 비동기 처리 지원할 수 있음.

비동기 asynchronous

console.log(1);
setTimeout(() => console.log(2), 1000);
console.log(3);

// 1
// 3
// 2 -> setTimeout 메서드 사용으로 1000ms 뒤 실행.
  • 비동기 방식은 작업이 독립적으로 실행됨. 각자 시간표에 따라서 실행!
  • 작업이 시작된 후에도 다른 작업을 동시에 실행시킬 수 있으므로 동기 방식에서의 사용성을 개선할 수 있음.
  • 오래 걸리는 작업을 실행하는 동안 다른 작업을 실행함으로써 성능 향상과 사용자 경험 개선 등을 위해 사용.

비동기 처리 방식의 문제

// jQuery 를 사용해 ajax 요청하는 예제 코드.
// jQuery 에서 제공하는 $.get() 메서드는 비동기적으로 동작하는 것이 기본 설정임.

function getData() {
	var tableData;
	$.get('https://domain.com/products/1', function(response) {
		tableData = response;
	});
	return tableData;
}

console.log(getData()); // Output: undefined
  • getData() 를 찍어보면 undefined 출력 됨. 이유는?
  • $.get() 로 데이터를 요청하고 받아올 때까지 가디리지 않고 다음 코드인 return tableData 를 실행했기 때문. 따라서 getData() 는 초기 값을 설정하지 않은 tableData의 값 undefined.
  • 비동기 처리 방식의 문제를 해결하기 위한 방식으로 콜백 함수가 있음

콜백 함수?

function sayHello(callback) {
  console.log('안녕하세요!');
  callback(); // 콜백 함수 호출
}

function sayName() {
  console.log('제 이름은 Kim입니다.');
}

sayHello(sayName);
// Output: 안녕하세요! 제 이름은 Kim입니다.
  • 다른 함수에 인자로 전달되어 특정 시점에 호출되도록 되어 있는 함수. 함수 안에서 호출되는 함수!
  • 위 코드
    1. sayHello 함수는 콜백 함수를 매개변수로 받음.
    2. sayHello 함수 안에서 "안녕하세요!"를 출력한 후, 콜백 함수인 sayName를 호출하여 "제 이름은 Kim입니다." 출력
    3. 여기서 sayName 함수가 콜백 함수.
  • 콜백 함수를 사용하면 코드의 재사용성이 높아지고 유연한 동작을 구현할 수 있음. 이러한 방식으로 특정 함수에 동작을 전달하여 필요할 때 해당 동작을 실행할 수 있음.

콜백 함수로 비동기 처리 방식의 문제점 해결하기

// ajax 통신 코드 콜백 함수로 개선해보기.

function getData(callbackFunc) {
	$.get('https://domain.com/products/1', function(response) {
		callbackFunc(response); // 서버에서 받은 데이터 response를 callbackFunc() 함수에 넘겨줌.
	});
}

getData(function(tableData) {
	console.log(tableData); // $.get()의 response 값이 tableData에 전달됨.
});
  • 이렇게 콜백 함수를 사용해 특정 로직이 끝났을 때 원하는 동작 실행.

콜백 지옥

task1(function () {
  task2(function () {
    task3(function () {
      setTimeout(function () {
        console.log('마지막 작업 시작');
        setTimeout(function () {
          console.log('마지막 작업 완료');
        }, 1000);
      }, 1000);
    });
  });
});
  • 그러나 비동기 작업으로 처리해야 하는 일이 많아질수록 예시 코드처럼 중첩 깊이가 더 깊어지면서 코드가 복잡해짐.
  • 코딩 패턴으로 이러한 콜백 지옥을 분리할 수 있지만 Promise 나 async/await를 사용하면 더 편하게 해결할 수 있음.
  • 다음 시간엔 스택과 큐, 프로미스, 어싱크/어웨잇을 더 알아봐야겠다.

reference

profile
벨로그로 이사 중

0개의 댓글