<Project 3 - Richmaker >
기간 : 3주
팀원 : 프론트 2명 (PM) / 백엔드 5명
필수 구현 사항 : 로그인, 회원가입, 테스트 코드, 메인페이지, 공동관리 페이지, 마이데이터(구현), 거래내역 리스트
const postTransactions = async (userID, data) => {
const CI = await getUserCI(userID);
await Promise.all(
data.map(async (obj) => {
let providerID = obj.providerID;
let financeNumber = obj.financeNumber;
let financeName = obj.financeName;
const userFinancesID = await providerDao.insertUserFinances(
userID,
providerID,
financeNumber,
financeName
);
const options = {
method: "POST",
uri: "http://10.58.52.75:3000/mydata",
body: {
CI: CI,
userFinancesId: userFinancesID,
providerID: providerID,
financeNumber: financeNumber,
},
json: true,
resolveWithFullResponse: false,
simple: false,
};
const responseFromAccountTransaction = await request(options);
if (responseFromAccountTransaction.message == "NO_RECORDS") {
const error = new Error("NO_RECORDS");
error.statusCode = 403;
throw error;
}
const res = decrypt(responseFromAccountTransaction.data);
const response = res[0];
response.map(async (obj) => {
let amount = obj.amount;
let transactionNote = obj.transactionNote;
let categoryID = obj.categoryID;
let isMonthly = obj.isMonthly;
let createdAT = obj.createdAT;
await providerDao.insertTransactions(
userFinancesID,
amount,
transactionNote,
categoryID,
isMonthly,
createdAT
);
});
})
);
};
저번 글에서 작성했던 API 중 4번째 API 를 작성하던 중 문제가 발생했다.
상황설명 : 고객이 선택한 계좌번호/ 카드번호를 백엔드 서버로 받아오면 선택한 금융의 각각의 고유번호(userFinanceId)를 구한 후 계좌/카드 마다 한번씩 거래내역을 마이데이터로 요청한 후 저장한다.
예를 들어 고객이 최종적으로 4개의 금융을 선택했다면 위의 작업을 4번 해야하는 상황이다.
상황 당시 나는 반복적으로 일을 처리해야겠다 생각했고 프론트에서는 데이터를
[ { }, { }, { },....... ] 이렇게 배열 안에 객체 형식으로 전달해준다고 했다. 그래서 map 을 활용해서 만들어야겠다 라고 생각했다.
그러나 여기서 문제가 발생하는데
map 을 사용해서 반복적인 작업을 처리하며 거기서 발생하는 에러를 controller 에서 error 를 캐치하여 errorstatus 로 사용하고 싶었으나 error 를 캐치 하지 못하는 상황이 생겼다.
외부 api 에서 “NO_RECORDS” 라고 메세지를 보내줄때
나는 if(response.message == “NO_RECORDS”) 일 경우
error 를 선언하여 “NO_RECORDS” message 를 전달하고 error status code 를 400 으로 지정하여 throw 를 하고 싶었다. 그러나 controller에서 error 를 전혀 잡지 못했다.
그래서 에러를 어느 부분에서 error를 캐치를 못하는 것인지 파악하기 위해 console.log() 를 찍어 추적하기 시작했고 error 메세지를 if() 문 안에서 받아내는 것까지는 가능했으나 controller 로 throw 를 하지 못하는 상황이였다.
결론은 promise.all() 로 map을 사용했던 부분을 모두 감쌌더니 해결이 되었다. 원인은 반복문의 동기 비동기에 대한 이해가 부족했다.
먼저 반복문마다의 특성을 처음 알았다. 결과값만 맞으면 된다고 생각했지만 각 반복문마다 결과를 만들어내기까지의 특성이 다르다.
나의 코드에 map 을 사용한 이유는 배열 안의 여러가지의 객체를 각각 사용해야하기 때문이였다. 그런데 map 의 특성상 동기 방식이기 때문에 던지지 못하는 것이였다. 그래서 그 전체를 promise.all 안에 넣어줌으로써 비동기적으로 흘러가게 해주며 하나라도 에러가 뜬다면 그 후에 작업은 진행하지 않게 해준다.
그래서 해결 전의 코드에 async 를 사용하더라도 작용하지 않고 흘러가던 것이였다.
따라서 각각의 반복문이 단순히 배열의 상황이냐 아니냐의 문제보다 더 심도 깊게 이해하여 비동기 동기적인처리부터 배열의 재구성이냐 단순히 배열의 인덱스를 수정하느냐 등등 각각의 기능과 역할을 제대로 파악하고 사용해야 하는 것이다.