발단
const axios = require('axios');
const jwt = require('jsonwebtoken');
// 비밀키를 비동기적으로 얻기 위한 함수 (외부 API 호출)
function getSecretKey(callback) {
axios.get('<https://example.com/getSecretKey>')
.then(response => {
const secretKey = response.data.secretKey;
callback(null, secretKey); // 에러는 null, 비밀키는 응답 데이터에서 가져온 값
})
.catch(error => {
callback(error, null); // 에러 발생 시 에러 객체를 전달
});
}
// JWT 생성을 위한 콜백 함수
function generateJwt(payload) {
return function (err, secret) {
if (err) {
console.error('Failed to get secret key:', err);
return;
}
jwt.sign(payload, secret, (err, token) => {
if (err) {
console.error('JWT signing error:', err);
return;
}
console.log('Generated JWT:', token);
});
};
}
// 비밀키를 얻고 JWT 생성
const payload = { user_id: 123456 };
const jwtCallback = generateJwt(payload); // 클로저를 활용하여 콜백 함수 생성
getSecretKey(jwtCallback);
위의 코드를 이해하기가 힘들었다.
return function은 말 그대로 함수를 다시 반환하는 것일텐데.. 뭔가 어떻게 함수를 반환한다는 것인지 이해가 안 갔다.
문제
먼저, 이 코드를 이해하려면 일급 객체와 해당 문서 안에 설명되어 있는 고차함수, 콜백 정도는 제대로 알고 있어야한다고 생각한다.
자바스크립트의 1급 객체의 특성을 이용해서, 함수를 리턴하는 예시를 보여보자면 이런게 있겠다.
function add(num1) {
return function (num2) {
return num1 + num2;
};
}
add(1)(2) // = 3
인자 num1을 그대로 저장해서 리턴된 함수에서 써먹을 수 있는 모습을 볼 수 있다.
극단적으로 이런 것도 당연히 가능하다. (다른 파일이라는 가정 하에)
function add(num1) {
return function (num2) {
return function (num3) {
return function (num4) {
return num1 + num2 + num3 + num4;
};
};
};
}
add(1)(2)(3)(4); // = 10
결론
내가 읽지 못하던 코드는 막 어려운 내용이 아니었다.
내가 return function을 잘 이해하지 못해서 생긴 문제였다. 자바스크립트에 대한 이해도가 낮았다.
이해가 가는 입장에서 데이터의 흐름을 번호로 달아서 설명을 해보자면,
const axios = require('axios');
const jwt = require('jsonwebtoken');
function getSecretKey(callback) {
axios.get('<https://example.com/getSecretKey>')
.then(response => {
const secretKey = response.data.secretKey;
callback(null, secretKey);
})
.catch(error => {
callback(error, null);
});
}
function generateJwt(payload) {
return function (err, secret) {
if (err) {
console.error('Failed to get secret key:', err);
return;
}
jwt.sign(payload, secret, (err, token) => {
if (err) {
console.error('JWT signing error:', err);
return;
}
console.log('Generated JWT:', token);
});
};
}
const payload = { user_id: 123456 };
const jwtCallback = generateJwt(payload); // 1. generateJwt에 의해 함수가 생성된다. 이 함수는 jwtCallback에 대입된다.
getSecretKey(jwtCallback); // 2. getSecretKey에 jwtCallback에 대입된 함수가 인자가 들어간다.
// 3. getSecretKey가 작동하면서 'example.com/getSecretKey' 에서 정보를 받아온다.
// 4-1. 정보를 받아오는데에 성공했다면, .then 으로 넘어가서 jwtCallback에 대입되었던 함수로 넘어간다. 첫번째 매개변수인 err이 null 값으로, 토큰 값을 출력한다.
// 4-2. 정보를 받아오는데에 실패했다면, .catch 로 넘어가서 jwtCallback에 대입되었던 함수로 넘어간다. 첫번째 매개변수인 err에 값이 있다. 따라서 에러를 출력하고 리턴된다.
이 정도로 설명할 수 있겠다.
코드가 이해가지 않을 땐 나눠서 이해해보려고 하면 금방 이해가 가는듯 하다.
잘못된 부분이 있다면 댓글 부탁드립니다!!
'백엔드' 카테고리의 다른 글
무한 대댓글 실제로 구현해보기 O(N^2) (0) | 2023.08.06 |
---|---|
Redis O(N) 문제와 대응: SCAN 명령어로 효율적으로 데이터 조회하기 (0) | 2023.07.27 |
백엔드에서의 무한 대댓글 구현 (0) | 2023.07.26 |
jsonwebtoken의 jwt.sign(), jwt.vertify()에서 콜백 사용이 필요할까? (0) | 2023.07.23 |
JWT에서 Bearer는 무엇을 의미할까? (0) | 2023.07.20 |