헷갈리는 동기, 비동기 개념을 정리하는 포스팅 (1)
첫번째 포스팅에서는,
callback이 무엇인지,
어떻게 쓰이는지,
그리고 화살표 함수를 제대로 해석하는 방법까지 정리해보고자 한다.
참고한 영상 : https://youtu.be/s1vpVCrT8f4
callback이란?
1. 다른 함수(또는 코드)의 인자로서 활용되는 함수.
2. 어떤 이벤트에 의해 호출되는 함수.
쉽게 말하면, 함수의 인자처럼 전달되어서 쓰이는 함수를 의미한다.
const print = () => console.log('hi');
setTimeout(print, 2000)
print는 아무 인자도 전달받지 않고 'hi'를 출력하는 함수이다.
setTimeout은 함수 하나(print)와 숫자(ms)를 전달받아서,
숫자 만큼의 시간이 지난 후 함수(print)를 호출하는 함수이다.
여기서 이 print라는 함수가 callback이 된다.
setTimeout이라는 함수의 인자로 쓰여서, 2000ms가 지나는 이벤트 후에 호출되었기 때문이다.
이렇게 callback이라는 것은 (아주 비약하자면) 함수의 인자처럼 쓰이는 함수이다.
callback함수의 활용과 callback지옥 (화살표 함수에 대한 이해)
실행결과는 아래와 같다
실행 2초 후 위와 같은 문자열이 출력된다.
'woojin', 'hustle'이라는 id와 password 그리고
onSuccess(user를 넣으면 getRoles에 user를 전달해서 실행하는 함수)
onError(error를 넣으면 error를 출력하는 함수)
이렇게 4개의 인자를 loginUser에 전달해서 실행시킨다.
여기서 onSuccess, onError에서 정의한 함수가 callback이다.
onError는 loginUser에 전달되는데,
loginUser에서는 onError에 'not found'라는 문자열을 출력하는 new Error 객체를 전달하여 실행시키게 되어 있다.
관계가 복잡하지만,
화살표 함수의 용법과 콜백의 정의, 쓰임에 대해 정확하게 이해할 수 있는 코드이다.
하지만, 저렇게 해석하기 어려운 코드는 이해하기에도, 유지보수에도 불리하다.
위처럼 콜백이 콜백을 부르며 코드 왼쪽 공백의 깊이가 깊어지는 것을 콜백 지옥이라고 부른다.
다음 포스팅에서는, 콜백 지옥을 해결할 수 있는 방법인
Promise의 활용에 대해서 다뤄보겠다.
+) Javascript로 작성된 위 코드를 Typescript로 변환해보았다.
// Callback Hell example
interface success {
name: string;
role: string;
}
const obj: success = {
name: 'woojin',
role: 'admin',
}
class UserStorage {
loginUser(
id: string,
password: string,
onSuccess: (x: string) => void,
onError: (x: object) => void) {
setTimeout((): void => {
if (
(id === 'woojin' && password === 'hustle') ||
(id === 'money' && password === 'many')
) {
onSuccess(id);
} else {
onError(new Error('not found'));
}
}, 2000);
}
getRoles(user: string, onSuccess: (x: success) => void, onError: (x: object) => void) {
setTimeout(() => {
if (user === 'woojin') {
// onSuccess({ name: 'woojin', role: 'admin' });
onSuccess(obj);
} else {
onError(new Error('no access'));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id: string = 'woojin';
const password: string = 'hustle';
userStorage.loginUser(
id,
password,
(user: string) => {
userStorage.getRoles(
user,
(userWithRole: success) => {
console.log('hi')
console.log(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
},
error => {
console.log(error);
}
);
},
error => {
console.log(error);
}
);