\(@^0^@)/

Rtk-query로 FormData구현 본문

프로젝트&웨비나 회고/테오의 스프린트

Rtk-query로 FormData구현

minjuuu 2022. 12. 21. 11:59
728x90

리뷰 작성페이지를 구현하는 부분에서 기억에 남는 것들을 기록용으로 정리해보려 한다.


[ formData ]

서버에 추가할 데이터들을 formData에 추가하여, 전달해 주는 로직인데
사진 추가 기능이 있어서 formData를 사용하였음. (mvp는 일단 사진 1장만 추가하는 것으로 기획)

최근에 formData를 사용해 본 적이 없어서 간단한 건데도 생각보다 생각보다 헤맸던 것 같다.

첫 번째 로직을 작성하고 실행해 보니, 이렇게 error가 나더라. 코드를 이리저리 변경해 봐도 변함없이 error.
CORS 관련 error는 대부분 서버에서 조치를 취해야 한다고 들은 것 같아서 백엔드 개발자분께 여쭘..

(유튜브 "코딩 알려주는 누나"에서 백엔드 개발자에게 error 나는 부분에 대해 질문할 때,
네트워크 탭의 cURL을 첨부하면 훨씬 효율적이라는 영상을 보고, 복사하려 하는데 복사가 안되더라ㅠ
에러 나면 안 되고, 제대로 작동됐을 때만 복붙이 가능하던데ㅠ 이 부분에 대해서는 조금 더 알아봐야겠음)

결론은 Content-Type 문제와 내 잘못이었다고 한다..
(또한 CORS error가 떠도 내 잘못일 수도 있다는 것을 깨달았다고 한다... 송구합니다 백 님ㅠ)

Content-Type이 단순한 multipart/form-data가 아니라, 아래와 같이 뜨는 게 맞음!

구글링 해봤을 때, 대부분 headers안에 ContentType을 지정해 주었는데,
내 경우엔 Content-Type을 작성하지 않아도 알아서 api 요청하면 multipart로 잡히더라.

그래서 일단 ContentType 부분을 아예 빼버렸는데.. 무조건 넣어야 하는 건지, 아닌지 조금 더 알아봐야 할 것 같다.

간만의 formData 구현이라 이리저리 구글링 하여 코딩했는데, 
대부분의 개발자 블로그에서 일반 JSON 데이터를 formData 객체에 추가할 시 JSON으로 파싱을 해야 한다길래
나 또한 모든 데이터를 json형태로 파싱 해서 요청을 보냈는데, error 발생.

const formData = new FormData()
formData.append('user_id', JSON.stringify(userId))
formData.append('password', JSON.stringify(pwd))

 

네트워크 탭을 보니, 내가 일일이 파싱 하지 않아도 res에 json 형태로 들어가고 있었다. (어째서!?)


우여곡절 끝에 formData 구현 완료했지만, 내가 작성한 코드를 조금 더 간결하게 리팩토링 하고 싶다는 생각이 들었다.

아래와 같이 변수들을 삭제하고, 바로 append 하는 코드를 작성해 보았음.
코드길이는 확실히 줄었지만, 가독성이 많이 떨어지는 것 같고, 데이터를 수정할 때 불편함이 있어 보인다.
그렇다면 이번엔 append 부분을 간결하게 만들어보자.


일단  formData에 넣을 데이터들을 한 객체로 묶고 append 해주는 것이 제일 깔끔할 것 같다.
img는 json형식이 아니라서 객체 안에 넣지 않고, img가 없으면 append 하지 않는 방식으로 구현했음.

이렇게 구현하였더니 당연하겠지만 data 객체가 append 되어 submit 할 경우, error 발생함.
객체 안의 key, value를 formData에 하나씩 append 할 수 있는 방법이 무엇이 있을까?

Object.entries메서드를 이용하면 된다!
Object.entries메서드에 forEach메서드를 활용하면 객체의 key, value를 formData에 각각 append 할 수 있게 된다.
또한, 하나의 함수를 만들어서 formData를 append 하는 로직들을 모두 집어넣어서 submit handler와 기능을 분리하자.

이렇게, 내가 처음 생각했던 대로 훨씬 간결한 코드로 리팩토링 되어서 매우 만족스럽다.


[ Rtk-query ]

사용자가 리뷰를 작성을 완료했다면 작성페이지에서 머물러 있는 것이 아니라 리뷰 목록 페이지로 이동되어,
목록의 첫 번째 리뷰가 해당 사용자의 글이어야 하는 것이 맞다고 생각했다.

setReview(formData).then(navigate(`/tree/${tree_id}`, { replace: true }))

 

그래서, 작성을 완료하면 navigate를 통해 리뷰페이지로 이동시켰는데, 그렇게 될 경우에 리렌더링이 이루어지지 않음.
내가 핸들러에 작성해 둔 e.preventDefault()를 지워야 form 태그에서 submit 후 렌더링이 이루어지는데, 
그걸 지울 경우에 리뷰 목록 페이지로 이동되기 전에 리렌더링 돼버린다.

어떻게 하는 것이 좋을까 고민하며 요리조리 해봐도 잘 되지 않아서, 개발자 톡방에 질문을 올리기로 하였다.
나는 swr을 쓰지 않고, rtk-query로 구현하고 있지만 개발자 분으로부터 힌트를 얻어서 구글링을 시작했다.
(감사합니다! 만수무강하세요!)

https://stackoverflow.com/questions/72447522/how-to-automated-re-fetching-data-in-rtk-query

 

how to Automated Re-fetching data in RTK query

when i move next page or move to another page or update data ...data is not refetch ...when I reload the page then refetch data ...without reload how to refetch data using RTK query.. this is code ...

stackoverflow.com

 

refetchonmountorargchange라는 매개변수를 발견!
전체 리뷰를 불러오는 리뷰 목록 페이지 부분에 해당 변수를 true로 설정하였더니,
리뷰 작성 후 -> 리뷰 목록 페이지로 이동되고, 내가 쓴 리뷰도 렌더링 된 것을 볼 수 있다.

 

추가로 forcerefetch라는 매개변수도 알게 되었는데, 같은 페이지에서 re-fetch를 할 경우에 유용해 보인다.
공식 문서에는 무한 스크롤 같은 작업을 할 때 유용하다고 나와 있음.


[ 느낀 점 ]

Object.entries 메서드를 적용해 본 것은 이번이 처음이었다.
사실 formData에 데이터를 append 하는 로직을 리팩토링 하는 부분에서 해당 메서드가 있다는 것을 알지 못하고 계속 다른 방식들로 이리저리 구현해 보고, 그 로직들이 제대로 잘 되지 않아서 꽤나 많은 시간을 버렸다.

저런 메서드를 안다면 내가 생각했던 것들이 정말 단순하게 풀릴 때가 많다.
내가 아직 JS 개념들이 아직 정말 많이 부족하구나... 알고리즘 문제도 많이 풀어봐야겠다ㅠ 반성하자!

또한, 이번에 리팩토링의 중요성에 대해 다시 한번 짚고 넘어갈 수 있는 기회였다.
단순히 기능이 돌아간다고 다음 단계로 넘어갈 것이 아니라, 내가 작성한 코드들을 보면서 어떻게 해야 조금 더 간결하고 사용성이 (하나의 함수는 한 가지 역할만) 좋은 로직을 작성해야 할지 더 고민하고, 생각해야 진정한 개발자가 될 수 있는 것 같다.

또한 rtk-query도 이번에 처음 배우고 프로젝트에 적용해 보았는데,
공식문서를 간단하게만 읽고 바로 구현을 해서 그런지 생각보다 조금 막히는 부분들이 있었다.

조금 더 학습 후에 구현했어야 하나 하는 아쉬움이 남았지만,
그래도 이번 기능을 구현하면서 공식문서의 중요성을 다시 한번 깨달았다.
코딩하다가 막히는 것이 있다면 일단 공식문서에 검색하거나 빠르게 훑은 뒤, 그래도 없다면 구글링을 해보자.
현업에 있는 분들이 괜히 공식문서를 가까이하라는 것이 아니라는 것을 오늘 또 한 번 깊이 공감하고, 느낄 수 있었다.


 

728x90

'프로젝트&웨비나 회고 > 테오의 스프린트' 카테고리의 다른 글

Teo's Sprint DAY 7  (2) 2022.12.02
Teo's Sprint DAY 6  (0) 2022.11.29
Teo's Sprint DAY 4  (0) 2022.11.28
Teo's Sprint DAY 3  (0) 2022.11.26
Teo's Sprint DAY 2  (0) 2022.11.25