[React] 리액트 데이터흐름의 중요성

2023. 10. 18. 17:29우당탕탕 에러기록

내가 마주한 문제는 진행중인 사이드 프로젝트의 캘린더를 체크박스로 묶어서 여러항목을 한번에 삭제하는 기능을 구현하다가 마주한 문제입니다.

기능구현에 앞서, 로직을 구성할 때 나의 머릿속에서 수도코드를 작성해봤다.

로직 수도코드

  1. 체크박스의 상태와 선택된 항목을 담을 상태를 만든다.
  2. 체크박스가 체크되면 체크박스핸들러라는 함수가 실행되고, 해당 함수에서는 체크박스의 상태를 true로 변경하고 선택된 항목을 배열 타입의 state에 추가한다.
  3. 조건문을 통해 체크박스가 비활성화된다면 배열에서 해당항목을 필터해서 삭제해준다.
  4. 삭제버튼을 누르면 해당 배열에 들어간 항목들을 순차적으로 순회하면서 DELETE요청을 서버로 요청한다.

위의 로직으로 구현을 했고, 체크박스를 클릭했을 때 내 예상과는 다른 결과가 나왔다.

내 예상으로는 [1756,1758,1760] 이렇게 세가지 캘린더ID가 배열에 추가가 되어야 했는데 체크박스를 클릭 할 때마다 값이 누적되지 않고 마지막 값만 들어오는것이다.

처음에는 함수안에서 문제를 열심히 찾았다.

리액트의 불변성을 어겨서 그런건가?

함수 내 조건문에 문제가 있는건가? 두시간가량 고민을 하고 삽질을 했다.

코드를 유심히 보던 중, 뭔가가 스쳐지나갔다.

위는 캘린더에 추가한 축제리스트를 보여주는 코드라인들이고, CalendarFestival 컴포넌트에 축제데이터를 넘겨줘서 맵으로 뿌려주는 식으로 구성되어있다.

그러니까, 저 빨간 박스 하나하나가 CalendarFestival 컴포넌트라고 볼 수 있다.

여기서 내가 한 큰 실수가 이전에는 단일 항목 삭제만 하다보니, CalendarFestival 컴포넌트 안에서 삭제 요청을 보내도 상관없었다.

각 CalendarFestival 컴포넌트마다 서로의 상태를 공유 할 일이 없기 때문이다.

하지만 여러항목을 삭제하기위해서는 체크한 항목들을 기억해둬야 했고, 그러기위해서는 상태로 관리해야만 했다.

단순하게 위의 수도코드처럼 작성하려고하니 CalendarFestival 컴포넌트안에서 상태를 관리하고 말았다.

당연히 하나하나의 컴포넌트마다 아무리 추가해봤자 서로는 관련이 없으니 배열에 곧죽어도 하나의 데이터만 담기는게 당연했다.

 

이제 알았으니 새로 수도코드 작성 해야겠지?

리뉴얼 로직 수도코드

  1. 부모 컴포넌트에 선택된 항목을 담을 상태와 삭제요청 함수를 만든다.
  2. CalendarFestival컴포넌트로 setState함수를 props로 내려준다 (depth가 깊지않아서 굳이 전역관리 필요성 못느낌.)
  3. CalendarFestival컴포넌트에는 체크박스관리 상태를 하나 만든다.
  4. 체크박스상태가 활성화되면, 체크박스 핸들러 함수가 실행되고 해당 함수에서는 체크박스상태를 현재상태의 반대로 만들고 선택한 항목을 내려받은 setState함수에 추가한다. 
  5. 삭제버튼을 누르면 해당 배열에 들어간 항목들을 순차적으로 순회하면서 부모컴포넌트에서 DELETE요청을 서버로 요청한다.

수정 후 결과

어떻게 보면 굉장히 기본적인거라고 생각하지만, 실제 개발을 하다보면 은근히 이런 사소한 실수가 많이 일어나는 것 같다.

그래도 이렇게 원하는 결과가 나오게되면 뿌듯하고 보람차다.

내가 머릿속으로 생각했던 로직이 내 예상대로 동작하는 걸 보는게 내가 프론트엔드 개발을 하는 큰 기쁨이자 이유같다.

깔끔하게 비워졌다!!!


오늘자 우당탕탕 요약

  1. 리액트의 데이터는 위에서 아래로 흐르게 하는게 가장 이상적이다.
  2. 같은 컴포넌트여도, 여러개가 쓰인다면 각자 컴포넌트끼리는 독립적임을 잊지말자.
  3. 내 의도대로 실행되지않으면 조건문부터 함수, 해당 컴포넌트, 부모 컴포넌트로 상향식으로 디버깅해보자.