[JavaScript] 비동기 처리와 콜백 함수

Haeun Noh·2023년 7월 21일
2

JavaScript

목록 보기
1/3
post-thumbnail

0721


들어가며..

얼마전 멘토링 과제로 자바스크립트의 비동기 처리와 콜백 함수에 관해 공부해보라는 과제를 받게 되었습니다.

그리고 평소 js를 공부하고 있었는데 처음 들어보는 용어들이라 호기심이 생겨 이렇게 블로그에 기재를 해보게 되었습니다.

그럼 바로 동기와 비동기의 개념부터 차근히 시작해보자구요!



1. 동기 (Synchronous)

1.1. 동기란 무엇인가요?

자바스크립트는 한 번에 하나의 작업을 수행합니다.
마치 마트에서 장을 본 사람들이 한 사람씩 결제하는 것과 유사합니다.

이러한 동작은 단일 스레드(싱글 스레드), 즉 동기라고 부릅니다.

동기 : 한 작업이 실행되는 동안 다른 작업은 멈춘 상태를 유지하고 자신의 차례를 기다리는 것


1.2. 동기의 예제

동기를 코드로 이해해봅시다.

function first() {
  second();
  console.log("첫 번째");
}
function second() {
  third();
  console.log("두 번째");
}
function third() {
  console.log("세 번째");
}

first();
third();

위의 예제를 실행해보면

세 번째
두 번째
첫 번째
세 번째

가 출력이 될 겁니다.

이렇게 동기적으로 동작하는 코드는 작성된 순서에 따라 진행되므로 작업의 흐름을 파악하기가 쉽죠.


1.3. 동기적인 코드의 문제점

다만 한 가지 문제점이 있습니다.

동기적으로 동작하는 코드는 순서대로 작업이 진행되기 때문에 시간이 오래 걸리는 코드가 앞 쪽에 위치한다면 전체적인 코드의 진행이 느려진다는 단점이 있습니다.

console.log("시작");
// 느린 코드
// 빠른 코드

위의 코드를 보면 "시작"이 출력된 후 느린코드가 빠른 코드 앞에 위치해 빠른코드의 실행 시작 또한 늦추고 있는 것을 알 수 있습니다.

그래서 이러한 동기적인 코드의 문제점을 해결하기 위해 비동기라는 개념이 존재합니다.



2. 비동기 (Asynchoronous)

2.1. 비동기란 무엇인가요?

이전에 말했듯 자바스크립트는 단일 스레드, 동기식으로 동작합니다.

하지만 비동기는 어떠한 요청을 보내면 그 요청이 끝날 때까지 기다리는 것이 아니라, 응답에 관계없이 바로 다음 동작이 실행되는 방식을 말합니다.

비동기 : 어떠한 요청을 보내면 그 요청이 끝날 때까지 기다리는 것이 아니라, 응답에 관계없이 바로 다음 동작이 실행되는 방식


2.2. 비동기가 필요한 이유

그렇다면 비동기는 왜 필요할까요?
바로 앞에서 말했던 동기적인 코드의 문제점을 해결하기 위해 존재합니다.

웹페이지가 로딩되거나, 어떠한 동작 하나가 30초 이상이 걸린다고 상상해보죠.
그렇게 되면 웹페이지는 동작 하나가 끝날 때까지 화면에 나타나지 않거나 다음 동작을 하는 데 지장을 주게 되겠죠.
사용자들은 당연히 답답해하며 웹페이지를 꺼버릴 것입니다.

그렇기 때문에 자바스크립트가 웹사이트에서 동작할 때 비동기적으로 처리할 수 있어야 하는 것입니다.
웹사이트를 들어가는 데에 30초 이상이 걸리고 여는 것 외에는 아무 동작도 할 수 없다면 너무 답답하지 않겠나요?


2.3. JS에서 사용되는 비동기 처리

  • Ajax Web API 요청 : 서버 쪽에서 데이터를 받아와야 하는 작업을 할 때는 요청 후 응답까지의 시간이 걸리기 때문에 작업을 비동기적으로 처리합니다.
  • 파일 읽기 : 주로 서버쪽에서 파일을 읽어야 하는 상황에서 사용됩니다.
  • 암호화 / 복호화 : 시간이 어느정도 걸리는 작업이므로 비동기적으로 처리합니다.
  • 작업 예약 : setTimeout을 사용하여 비동기적으로 처리합니다.

2.4. 비동기 예제

그렇다면 비동기적인 코드는 어떨까요?

console.log("시작");

setTimeout(function () {
  console.log("중간");
}, 5000);

console.log("끝");

혹시 동기적으로 생각해서 아래와 같은 결과값을 기대하지는 않으셨나요?

시작 중간 끝

비동기적으로 처리하는 대표적인 함수 setTimeout은 브라우저 제공 API이므로 Web API로 들어간 뒤 console.log("끝");이 출력된 후 console.log("중간");이 출력되게 됩니다.

이 부분은 비동기 작동 원리를 알아야 하는 부분이니 나중에 따로 정리하여 포스팅하겠습니다.



3. 콜백 함수

3.1. 콜백 함수란 무엇인가요?

콜백 함수는 파라미터로 전달받은 함수를 의미합니다.

콜백 : 함수를 매개변수로서 다른 함수에 전달하고 감싼 함수의 내부에서 해당 함수를 호출합니다.


3.2. 콜백 함수의 예제

function callback() {
	console.log("콜백 함수군요!");
}
function print(callback) {
    callback();
}
print(callback);

print()함수의 매개변수로 객체인 함수를 넘겨주었더니 정상적으로 메시지가 출력되는 모습을 확인할 수 있습니다.


2. 두 수를 더하여 출력하는 콜백 함수

function print(result) {
    console.log(result);
}
function add(n1, n2, print) {
    print(n1+n2);
}
add(10,20, print);
  1. add함수가 호출됩니다.
  2. add함수에 파라미터로 전달된 print의 매개변수로 n1n2의 합을 전달합니다.
  3. print()함수가 호출됩니다.
  4. n1+n2의 값을 출력합니다.

3. 익명함수를 파라미터로 전달하기

function add(x, y, print) {
    print(x + y)
}

add(10, 20, (result) => {
    console.log(result)
})
  1. add()함수가 호출됩니다.
  2. 1020print가 전달됩니다.
    이 때, print는 아래의 내장 함수와 같습니다.
  3. 10+20의 결과를 콜백함수의 파라미터로 전달합니다.
  4. result의 값이 30을 받고 출력합니다.

3.3. 콜백 함수의 장단점

콜백 함수를 사용하면 다음과 같은 이점이 있습니다.

  • 함수를 인자로 받기 때문에 필요에 따라 함수의 정의를 달리해 전달할 수 있습니다.
  • 함수를 굳이 정의하지 않고 익명 함수로도 전달이 가능합니다.
  • 비동기 처리 방식의 문제점을 해결할 수 있습니다.

하지만 다음과 같은 단점 또한 존재합니다.

  • 콜백함수를 남용하면 코드의 가독성이 떨어집니다. (콜백 지옥)
  • 에러 처리가 어려워집니다.


4. 콜백 함수와 비동기처리 활용

4.1. 콜백 함수를 이용한 비동기 처리

		function print(callback) {
            setTimeout(callback, 1000);
            console.log("1초 기다려~");
        }
        print(() => {
            console.log("Hello");
        })
  1. print()함수가 호출됩니다.
  2. print()함수의 매개변수인 print에는 익명함수가 전달됩니다.
  3. setTimeout은 비동기적 함수이므로 Web API에 넘어가 "1초 기다려~"가 먼저 출력된 후 "Hello"가 출력됩니다.


4.2. 공부한 시간만큼 칭찬하기

		function study(time) {
            if ( time === 1) {
                setTimeout(() => {
                    console.log(time+"시간만큼 공부한거야?");
                }, 1000);
            } else if ( time === 3) {
                setTimeout(() => {
                    console.log(time+"시간만큼 공부한거야?");
                }, 3000);
            } else if ( time === 5) {
                setTimeout(() => {
                    console.log(time+"시간만큼 공부한거야?");
                }, 5000);
            } else if ( time === 10) {
                setTimeout(() => {
                    console.log(time+"시간만큼 공부한거야?\n");
                    console.log("대단하네~");
                }, 10000);
            }
        }
        study(10);
        study(5);
        study(3);
        study(1);

동기적으로 보면 10시간부터 1시간까지 내림차순으로 출력될 것 같지만 setTimeout은 비동기처리 함수이기 때문에 아래와 같은 출력 결과가 나옵니다.



profile
Tistory로 옮기게 되었습니다. @haeunnohh

0개의 댓글