지난 2주 동안…
– 팀 프로젝트의 팀장이 되었습니다.
이에 대한 부담감과 고통이 컸다.
– JavaScript를 진지하게 배우기 시작했습니다.
현재 우리 팀은 API를 통해 사람들이 서로 소통할 수 있는 공간을 만들기 위해 노력하고 있습니다(Gathertown을 생각하면 편리합니다).
먼저 회원가입과 로그인 기능을 구현하기 위해 Node.js와 SQL을 배우기로 했다.
하지만 DB에서 조사하는 과정에서 “적절한 시점에 원하는 값이 계산되지 않았다”는 의견이 많았다.
강사님께 물어보니 “동기화와 비동기화의 개념”을 잘 이해하고 있어야 한다고 하셨어요.
또한 “콜백 함수”에 대해 살펴보라고 하셔서 이번 글에서는 동기, 비동기, 콜백 함수에 대해 작성하도록 하겠습니다.
동기 부여
동기식은 “위에서 아래로, 순서대로” 실행되는 것을 말합니다.
음악 대회를 예로 들어 봅시다.
여기에서 모든 것이 순서대로 이루어져야 하기 때문입니다.
음악 대회 참가자는 자신의 차례를 기다려야 합니다.
즉, 다른 모든 사람이 끝날 때까지 자신의 공연을 시작할 수 없습니다.
순리에 맡기다 “동기화 방식”프로그래밍에서 동일한 속성을 갖습니다.
console.log('이렇게')
console.log('위에서')
console.log('아래로')
console.log('실행됨')
함수나 메서드를 호출하면 함수나 메서드가 반환될 때까지 기다립니다.
또한 콘솔에서 위 명령어를 10번, 100번, 1000번 입력해도 결과는 같습니다.
‘모든 작업은 순차적으로 실행됩니다’ 당신은 그것을 볼 수 있습니다
비동기
비동기 란 무엇입니까? 이번에는 레스토랑을 예로 들어 내가 먹을 것을 주문했다고 가정해 봅시다.
주문이 주방으로 들어가는 순간부터 -> 셰프가 요리를 시작한 후 -> 음식이 준비되어 테이블에 놓일 때까지…
맛있는 음식을 먹으려면 일정 시간을 기다려야 하는데 일단 음식을 주문하면
음식이 나오기를 기다리는 동안 “나는 다른 일을 할 수 있다”비동기의 본질입니다.
프로그래밍에서 비동기를 처리하는 방법에는 여러 가지가 있습니다.
대표적인 예로 ‘콜백 함수‘있습니다.
const fs = require('fs');
fs.readFile('file.txt', 'utf8', function(err, data) {
if (err) throw err;
console.log(data);
});
위의 코드는 Node.js 환경에서 “비동기적으로” 파일을 읽습니다.
fs(파일 시스템)의 readfile 메소드를 사용하여 파일을 읽고 읽은 내용을 저장합니다.
‘콜백 함수로 전달’하다.
다음은 콜백 함수입니다.
기능(err, data)` 부분, 이 코드 파일을 읽는 과정이 완료되면 실행하다.
즉, 파일을 읽는 동안 다른 일을파일 읽기 프로세스가 완료되면 콜백 함수가 실행됩니다.
결과를 출력합니다.
위의 코드를 “동기적으로” 작성하고 실행하면 어떻게 될까요?
모든 절차가 순서대로 실행되기 때문에 파일을 읽는 동안 다른 작업을 수행할 수 없습니다.
이 상태에서는 다른 클라이언트에서 요청이 들어와도 파일을 읽는 작업이 우선권을 가지므로 요청을 처리할 수 없습니다.
동기 부여매우 쉽고 직관적으로 처리할 수 있으며,
결과가 나올 때까지 아무것도 할 수 없었기 때문에 효율적이지 않다는 것을 알았습니다.
비동기동기화보다 더 복잡한 코드가 필요하고 결과를 얻는 데 시간이 걸릴 수 있습니다.
그 시간 동안 다른 일을 할 수 있다는 것을 알았습니다.
그렇다면 비동기성에 대한 설명 ‘콜백 함수’ 그게 무슨 뜻이야? 인터넷을 검색해보니 이런 결과가 나왔다.
– 다른 함수의 인수로 사용되는 함수
– ‘이벤트’에 의해 호출되는 함수
“다른 함수”가 다른 함수의 인수로 전달된다고 합니까? 이것이 가능한가? 오류가 뜨지 않습니까?
함수, 조건문, 루프 등이 익숙하지 않은 순간 갑자기 떠오른 콜백 함수의 개념이 너무 난해하게 느껴졌다.
콜백 함수를 처음 보았을 때 처음부터 단계별로 어떻게 작동하는지 살펴보기로 했습니다.
function test () {
console.log ('난 원래 이렇게만 썼다')
} // 함수 선언
test() // 호출
위의 코드는 함수를 작성하는 가장 기본적인 방법 중 하나입니다.
함수 -> 함수 이름 -> 매개변수 쓰기 순으로 입력하여 함수를 선언할 수 있습니다.
함수 이름을 입력하면 해당 함수가 호출되고 “원래 그것만 썼어요”라는 메시지가 뜹니다.
function test1 (a, b) {
return a + b;
}
여기에 test1이라는 함수가 있습니다.
이 함수는 파라미터에 입력된 두 값을 더한 결과를 반환하는 함수가 있습니다.
합산할 수 있는 아주 아주 간단한 함수입니다.
그렇다면 이 기능의 단점은 무엇일까요?
기능만 ‘조용히’그걸로 만든
두 개의 값을 입력하면 값을 더해주는 역할을 합니다.
값을 할당하고 필요할 때마다 이 함수를 호출해야 하므로 반복적으로 해야 할 때 상당히 번거롭습니다.
그렇다면 이 함수의 알고리즘, 즉 실행 비행 중에 완료이것을 할 수 있는 방법이 있습니까?
function test2 (number, number2, callback) {
let a = number;
let b = number2;
return callback(a, b);
}
이 test2 함수를 확인해 봅시다.
test1 함수와 다른 점 다시 전화 세 번째 매개변수가 추가됨
숫자 매개변수의 값은 a라는 지역 변수에 할당됩니다.
매개변수 number2의 값은 b라는 로컬 변수에 기록됩니다.
갑자기 콜백의 매개변수 a 및 b보고!
도대체 어떻게 된 거죠?
test(10, 20, callback) {
let a = 10;
let b = 20;
return callback(a, b);
}
콜백 함수의 개념이 처음이라고 가정하고 매개변수에 값을 삽입해 보겠습니다.
1차 파라미터와 2차 파라미터에 각각 10, 20 값을 입력하면,
a = 10, b = 20
이때 세 번째 매개변수는 callback a 및 b “통과”.당신은 얻을 것이다.
그러면 인수로 전달된 매개변수는 어떻게 됩니까?
“매개변수 자리에 함수를 넣을 수도 있고 3번째 매개변수가 인수를 받는 함수가 된다”고 이해하기로 했다.
function test2 (number, number2, callback) {
let a = number;
let b = number2;
return callback(a, b);
}
console.log(test2(10, 20,function(a,b){
return a + b;
}))
// 예상 결과값 : 30
세 번째 매개변수가 함수로 변경되었기 때문에 test2 함수를 호출하는 방식도 다릅니다.
1. 함수 호출 시 숫자 입력
2. 입력된 숫자는 콜백 파라미터로 반환되어 함수로 변환됩니다.
3. 함수로 변경되었으므로 호출 시 함수를 호출하여 호출
함수를 호출하면 함수는 위의 과정을 거쳐 30이라는 값을 반환합니다.
function test1 (a, b) {
return a + b;
}
function test2 (number, number2, callback) {
let a = number;
let b = number2;
return callback(a, b);
}
test1 함수와 어떻게 다른가요? 결국 10과 20을 더한 결과를 반환하는 함수입니다.
언뜻 보면 test1 함수와 크게 다르지 않습니다.
좀 더 효율적으로 만들 수 있는 방법이 없을까요?
function add (first, second) {
return first + second;
}
console.log(test2(10, 20, add)); // 그리고 다음과 같이 실행하면...
새로 추가된 함수인 add는 두 개의 매개변수를 더한 값을 반환하는 함수입니다.
이 함수로 test2 함수를 호출할 때 두 개의 숫자를 입력하고 세 번째 매개변수로 add를 입력하면…
30의 값을 확인할 수 있습니다.
중요한 점은 함수가 호출되지 않고 함수의 “이름”만 얻어 계산이 수행되었다는 것입니다.
function add (a,b) {
return a + b;
}
console.log(add(10,20));
function subtract (a,b) {
return a - b;
}
console.log(subtract(20,30));
function multiply (a,b) {
return a * b;
}
console.log(multiply(40,50));
function divide (a,b) {
return a / b;
}
console.log(divide(60,70));
덧셈만 사용하고 다른 수학 함수도 추가해야 하는 경우에는 큰 문제가 되지 않습니다.
아마 위와 같은 방식으로 함수를 작성했을 것입니다.
특정 작업이 필요할 때마다 특정 함수를 호출하고 값을 할당해야 합니다.
단점은 코드가 길고 식별하기 어렵다는 것입니다.
하지만 콜백 함수로 코드를 작성한다면 어떨까요?
function test2 (number, number2, callback) {
let a = number;
let b = number2;
return callback(a, b);
}
function append (first, second) {
return first + second;
}
function subtract (first, second) {
return first - second;
}
function multiply (first, second) {
return first * second;
}
function divide (first, second) {
return first / second;
}
console.log(test2(10, 20, append));
console.log(test2(30, 40, subtract));
console.log(test2(50, 60, multiply));
console.log(test2(70, 80, divide));
1. test2에 입력된 두 개의 매개변수 값을 콜백에 인수로 전달
2. 콜백은 각 매개변수 값을 포함하는 “함수”로 변경됩니다.
3. 미리 계산하는 코드를 작성할 때
4. 함수를 따로 호출하지 않고 test2 함수를 호출하면 함수의 ‘이름’을 메모하여 계산을 계속할 수 있습니다.
setTimeout(function() {
console.log('5초가 지났습니다.
');
}, 5000);
콜백 함수를 사용하는 함수 중에는 setTimeout이 있습니다.
setTimeout 함수는 5초(5000) 후에 첫 번째 인수로 전달된 함수를 호출합니다.
이 함수가 실행되는 동안 다른 코드가 실행되고 전달된 함수는 5초 동안 실행되지 않습니다.
콜백 함수가 중요한 이유는 무엇입니까?
JavaScript는 비동기 프로그래밍을 위한 것입니다.
이벤트를 처리하도록 설계된 언어이 때문에
명령에 대한 응답을 기다리는 것보다 다음 명령을 실행하려면 콜백 함수를 사용하십시오.
기본적으로 JavaScript v8 엔진은 단일 스레드입니다.
여러 명령을 동시에 실행할 수 없습니다.
명령이 응답하는 데 시간이 오래 걸리면 매우 느려집니다.
즉, 콜백 함수를 비동기적으로 프로그래밍할 수 있다면,
JavaScript 엔진은 브라우저 또는 node.js에서 제공하는 웹 API에 작업을 맡깁니다.
다음 명령을 실행하여 속도 향상의 이점을 가져올 수 있기 때문에
JavaScript 및 node.js에서 콜백 함수를 잘 처리하는 것은 매우 중요합니다.
내 눈으로 보이지 않는 영역에서 콜백 기능이 작동하는 방식
사실 이 글을 쓸 당시에는 콜백 함수의 개념을 잘 이해하지 못했습니다.
나는 강사에게 이 고민을 털어놓았고 그는 원시 값과 참조 값을 공부하면 이해가 더 잘 될 것이라고 말했다.
코드를 수십 번 읽고, 쓰고, 사용하면 못 할 일이 없다고 생각합니다.