▶ function.js 파일
export function getEmployees(callback) {
console.log('Sending request...');
const response = `[{ "id": 1, "name": "Jason", "email": "jason@codeitmall.kr", "department": "engineering" }, { "id": 2, "name": "Alice", "email": "alice@codeitmall.kr", "department": "engineering" }, { "id": 3, "name": "Brian", "email": "brian@codeitmall.kr", "department": "marketing" }, { "id": 4, "name": "Erica", "email": "erica@codeitmall.kr", "department": "marketing" }, { "id": 5, "name": "Wilson", "email": "wilson@codeitmall.kr", "department": "sales" }]`;
setTimeout(() => callback(response), 1000);
}
export function json(string, callback) {
console.log('Parsing string...');
const json = JSON.parse(string);
setTimeout(() => callback(json), 1000);
}
export function groupEmployees(employees, callback) {
console.log('Grouping employees...');
const res = {};
employees.forEach((employee) => {
const { name, department } = employee;
if (!(department in res)) {
res[department] = [];
}
res[department].push(name);
});
setTimeout(() => callback(res), 1000);
}
콜백을 이용해서 비동기 처리하는 방식은
여러 비동기 작업을 연속적을 처리하는데 취약하다.
다음과 같이 function.js 파일에서 세 개의 임의적으로 정한 비동기 함수를 main 파일에서 import 하고 있다.
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
각 비동기 함수에 대해 자세히 알아보자.
getEmployees 함수
getEmployees 함수는 웹 리퀘스트를 보내는 함수이다.
정확히는 웹 리퀘스트를 보내는 것을 흉내 내는 함수인데
실제로는 리퀘스트를 보내지는 않고
그냥 정해진 데이터를 response로 돌려주며 다음과 같이 사용한다.
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
getEmployees((response)=> console.log(response));
콜백으로, response로 무엇을 하고 싶은지 알려 주면 되는데
일단 예시로 console.log로 response를 출력하였다.
실행해보면 function.js의 response가 잘 출력되는 것을 확인할 수 있다.
지금 이 response는 배열이 아니라 문자열인데
받은 데이터를 자바스크립트에서 편하게 사용하려면 배열로 바꿔줘야한다.
그 작업을 하는 함수가 json 함수이다.
json 함수
실제 response는 위 출력 된 것들 보다 훨씬 복잡하며
response를 받으면 우리가 원하는 데이터 부분을 추출해서
자바스크립트에서 사용하기 편한 형태로 바꿔 주는 작업을 파싱(parsing)이라고 한다.
즉 json 함수는 response를 파싱해주는 것이다.
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
// getEmployees((response)=> console.log(response));
json('[{ "id": 1, "name": "Jason", "email": "jason@codeitmall.kr", "department": "engineering" }, { "id": 2, "name": "Alice", "email": "alice@codeitmall.kr", "department": "engineering" }, { "id": 3, "name": "Brian", "email": "brian@codeitmall.kr", "department": "marketing" }, { "id": 4, "name": "Erica", "email": "erica@codeitmall.kr", "department": "marketing" }, { "id": 5, "name": "Wilson", "email": "wilson@codeitmall.kr", "department": "sales" }]',
(data) => console.log(data));
출력된 response를 복사해서 문자열로 만들어주고 콜백을 전달해준다
코드를 해석하면..
첫 번째 아규먼트는 파싱할 문자열이고
두 번째 아규먼트는 파싱 작업이 완료되고 나서 실행할 콜백인데
파싱된 결과를 파라미터로 받는다.
즉 파싱된 결과를 출력하라는 뜻으로 볼 수 있다.
이번에는 결과가 배열이기 때문에 전 보다 다르게 출력된다.
groupEmployees 함수
마지막으로 groupEmployees 함수는 직원 데이터를 프로세싱하는 함수이다.
직원들을 세일즈나 마케팅 같은 부서별로 모아주며
이 작업도 오래걸리는 작업이라고 가정하고 비동기 함수로 만들었다.
첫 번째 아규먼트는 프로세스할 직원 데이터이다.
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
// getEmployees((response)=> console.log(response));
// json('[{ "id": 1, "name": "Jason", "email": "jason@codeitmall.kr", "department": "engineering" }, { "id": 2, "name": "Alice", "email": "alice@codeitmall.kr", "department": "engineering" }, { "id": 3, "name": "Brian", "email": "brian@codeitmall.kr", "department": "marketing" }, { "id": 4, "name": "Erica", "email": "erica@codeitmall.kr", "department": "marketing" }, { "id": 5, "name": "Wilson", "email": "wilson@codeitmall.kr", "department": "sales" }]',
// (data) => console.log(data));
groupEmployees([
{
id: 1,
name: 'Jason',
email: 'jason@codeitmall.kr',
department: 'engineering'
},
{
id: 2,
name: 'Alice',
email: 'alice@codeitmall.kr',
department: 'engineering'
},
{
id: 3,
name: 'Brian',
email: 'brian@codeitmall.kr',
department: 'marketing'
},
{
id: 4,
name: 'Erica',
email: 'erica@codeitmall.kr',
department: 'marketing'
},
{
id: 5,
name: 'Wilson',
email: 'wilson@codeitmall.kr',
department: 'sales'
}
])
이번에도 결과를 복사해서 아규먼트 자리에 붙여 넣어주고
두 번째 아규먼트는 콜백을 전달한다.
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
// getEmployees((response)=> console.log(response));
// json('[{ "id": 1, "name": "Jason", "email": "jason@codeitmall.kr", "department": "engineering" }, { "id": 2, "name": "Alice", "email": "alice@codeitmall.kr", "department": "engineering" }, { "id": 3, "name": "Brian", "email": "brian@codeitmall.kr", "department": "marketing" }, { "id": 4, "name": "Erica", "email": "erica@codeitmall.kr", "department": "marketing" }, { "id": 5, "name": "Wilson", "email": "wilson@codeitmall.kr", "department": "sales" }]',
// (data) => console.log(data));
groupEmployees([
{
id: 1,
name: 'Jason',
email: 'jason@codeitmall.kr',
department: 'engineering'
},
{
id: 2,
name: 'Alice',
email: 'alice@codeitmall.kr',
department: 'engineering'
},
{
id: 3,
name: 'Brian',
email: 'brian@codeitmall.kr',
department: 'marketing'
},
{
id: 4,
name: 'Erica',
email: 'erica@codeitmall.kr',
department: 'marketing'
},
{
id: 5,
name: 'Wilson',
email: 'wilson@codeitmall.kr',
department: 'sales'
}
], (results) => console.log(results));
즉 프로세스된 데이터가 콜백의 파라미터로 전달되는 것이다.
실행해보면 각 부서별로 잘 출력 되는 것을 확인할 수 있다.
지금까지 사용해 왔던 세 개의 함수 모두 비동기 함수이기 때문에
만약 다른 코드를 추가하면 긴 작업을 처리하는 동안 먼저 실행해 줄 것이다.
여기까지 잘 진행되었다면 다행인데
문제는 지금까지 본 작업들을 이어서 하려고 할 때 발생한다.
getEmployees((response)=> {
json(response, (data) => {
console.log(data);
})
});
콜백 안에 콜백이 들어가 있어서 뭔가 복잡해 보이는 코드이다.
코드를 해석해보자면
response가 오면 그 response를 json 함수에 넘기고
json 함수에서 response를 배열로 다 바꾸면
그 결과를 출력하는 코드이다.
그 다음으로 groupEmployees 함수까지 이어서 실행해보자
// main.js
import {getEmployees, json, groupEmployees} from './function.js'
getEmployees((response)=> {
json(response, (data) => {
groupEmployees(data,(result) => {
console.log(result);
});
})
});
json 안에 들어가는 콜백에서 groupEmployees를 호출하고
또 그 안에서 실행할 콜백을 전달하였다.
코드가 더 읽기 힘들고 복잡해 졌는데
실행해보면 한번에 프로세싱까지 잘 되서 결과가 출력된다.
이렇게 콜백 안에 콜백이 여러번 중첩되는 것을
콜백 헬(callback hell) 우리 말로 콜백 지옥이라고 부르며
이런 코드는 이해하기도 힘들고 디버깅하게되면 떄려치고 싶을 정도이다.
하지만 콜백을 이용해서 비동기 프로그램을 구현하다 보면
어쩔 수 없이 발생하는 문제이며
이 문제를 해결하려면 Promise 문법(Link)을 사용해야한다.
'JS' 카테고리의 다른 글
(5) Asynchronous JavaScript - Promies (0) | 2025.01.01 |
---|---|
(1) ~ (4) Callback 정리 (0) | 2025.01.01 |
(3) Asynchronous JavaScript - 비동기 함수들의 예시 (0) | 2024.12.31 |
(2) Asynchronous JavaScript - 콜백(callback)과 비동기 함수(async function) (0) | 2024.12.30 |
(1) Asynchronous JavaScript - 비동기 자바스크립트의 콜백(callback) (0) | 2024.12.27 |