현재 보여지는 레시피에서 재료를 한줄 한줄 추가 하거나 이미 등록 되어 있는 레시피의 세부사항을 추가, 삭제할 것이다.
우선 등록을 해보자.
클라이언트쪽 부분이다.
ingredientList를 변할 수 있는 state 값으로 설정을 하고 input 태그에서는 onChange 이벤트를 통해 현재 입력하고 있는 값을 각각의 name, ea, unit에 넣어줬다.
한번에 하나의 값만 넣는게 아닌 여러개의 값들을 넣을 수 있기 때문에 입렵 값 부분을 map 함수로 감싸게 되었고 매개변수로 index 값을 넣어 늘어나는 index 값만큼 리스트의[index]에 값을 넣어주었다.
백엔드 부분이다.
아무 입력도 하지 않았을 때에는 등록을 할 필요가 없으니 입력된 리스트가 있을 경우에만 재료를 추가해주기로 했다.
마찬가지로 하나의 배열값만 받아오는것이 아니기 때문에 map 함수로 묶고 그 값들을 bulkCreate를 해주었다.
bulkCreate 는 seaquelize 에서 여러 인스턴스를 일괄 생성하고 삽입한다고 정의하고있다.
우선 전체적인 로직은 이러하다.
현재 등록 되어있는 재료리스트의 개수가 입력받는 재료리스트의 개수가 같을 경우에는 그 값만 수정(update)해준다.
현재 등록 되어있는 재료리스트의 개수가 입력받는 재료리스트의 개수보다 작을 경우( = 클라이언트 부분에서 재료리스트를 더 추가한 경우가 되겠다.)
현재 등록 되어있는 재료리스트의 개수가 입력받는 재료리스트의 개수보다 클 경우( = 클라이언트 부분에서 재료리스트를 삭제한 경우가 되겠다.)
총 3가지 경우를 생각해서 만들게 되었다.
생각보다 어려운 부분은 현재 db와 들어오는 값들의 비교부분이었다.
const currentIngredientList = await Ingredient.findAll({
where: {
recipeId: recipeId
}
})
const newAddArray = newIngredientList.filter((received) => {
return !currentIngredientList.some((current) => {
return received.id === current.id
})
})
const newMinusArray = currentIngredientList.filter((current) => {
return !newIngredientList.some((received) => {
return received.id === current.id
})
})
결국 받아오는 배열에서 현재있는 배열에는 없는 요소들만 필터링하여 새로운 배열을 만들게 된다.
이 값은 새롭게 추가되는 배열이 되는 것이다.
이 배열을 가지고 map 함수로 묶어 spread연산자에 recipe 아이디를 추가해주어 create해주게 된다.
위의 두번째 코드와 주객만 바뀌게 되었다.
말 그대로 입력받은 값은 삭제된 배열을 제외하니 현재 db에는 그 배열의 아이디값이 존재하지 않게 되고 현재재료배열에서의 id값과 받아오는재료배열에서의 id값이 같지 않은 배열을 나열하는 것이니 현재배열에서의 id값이 일치하지 않는 잉여의 배열만 존재하게 되고 그 배열을 삭제하게 된다.
마지막으로 일괄처리를 위해 삭제될 배열들을 Promise.all 함수를 사용하여 배열의 각 요소에 대해 비동기적으로 destroy함수를 호출하고 모든 작업이 완료될때까지 기다리게 했다.