redux-saga
는 redux 미들웨어로, 매우 강력한 사이드 이펙트 처리를 가능하게 만드는 라이브러리다.
최근 회사 코드베이스에서 이 의존성을 제거하고자 하여 그 의사결정의 근거들을 남긴다.
이 글은 읽는 사람이
redux-saga
와redux-toolkit
을 이용한 프론트엔드 개발 경험이 있다고 가정한다.
1. 러닝커브의 관점
Generator는 saga 이외의 사용처를 찾아보기 힘들다. 대부분의 입문자는 saga를 배우려면 먼저 generator부터 공부해야 한다.
또한 saga가 제시하는 멘탈 모델에 익숙해져야 한다. 공식 문서에 따르면,
The mental model is that a saga is like a separate thread in your application that's solely responsible for side effects.
사가의 멘탈 모델은 어플리케이션에서 사이드 이펙트를 책임지는 별도의 스레드와 같다. 일반적인 React 개발 경험과는 상당히 이질적이어서 익숙해지는데 시간이 필요하다.
2. 코드 변경으로 인한 사이드 이펙트 통제의 관점
사가는 generator function
과 (이하 saga function
) 이들을 트리거 시키는 action의 watcher
가 함께 쓰이는 것이 일반적인 패턴이다.
이러한 패턴으로 인해 saga function
을 실행하는데는 크게 세 가지의 방법이 있다.
call
fork
put
/dispatch
이 세 방식은 플로우 컨트롤에 있어 다른 특징을 가지므로, 어떤 구현을 원하느냐에 따라 적절히 선택해야 한다.
문제는 특정 saga function
의 body를 변경하려면, 해당 saga function
이 세 가지 중 어떤 방식으로 호출되고 있느냐를 살펴봐야 한다는 점이다. 즉 호출부를 면밀히 살펴봐야 선언부를 고치기 위한 확신을 얻을 수 있었다.
이는 결국 코드를 적극적으로 변경하기 힘들게 만든다. 코드의 변경으로 인한 사이드 이펙트 통제가 어렵다고도 표현할 수 있다.
3. 재사용의 어려움 관점
saga function
을 재사용하기 위해서는 로직을 추출하고 그 로직에 대한 플로우 컨트롤이 필요하다. 여기서 플로우 컨트롤에는 자연스럽게 그 로직에 대한 호출이 포함된다.
예를 들어 saga function
내에서 다른 saga function
을 호출한다면 2에서 언급했던 세 가지 방식 중 하나로 호출하게 된다. 즉 재사용을 하기 위해서 2에서 말한대로 적극적으로 변경하기 어려운 코드를 작성하게 되는 것이다.
또한 saga를 새로 만드려면 slice에 이를 위한 action들을 추가로 선언해주어야 한다. 이는 어느정도는 필연적으로 어려운 것으로 보았다. 왜냐하면 slice는 기본적으로 데이터를 담기 위한 단위이다. 여기에 로직의 재사용을 위한 saga를 위한 action을 담는다는 것은 본질적인 불일치가 존재한다.
결국 해당 saga의 action들을 넣을 적절한 slice가 없는 상황이 종종 발생한다. 이런 상황 때문에 우리는 종종 어쩔 수 없이 saga의 action만을 담고있는 slice를 만들곤 했다.
4. redux store가 비대해지는 문제
saga는 redux store를 비대하게 만든다. 여기서 비대하게 만든다는 표현의 정확한 뜻은, 본래 필요한 정도보다 비대해 진다는 뜻이다.
saga는 비동기 로직을 처리한 뒤 redux store에 담기 위한 의존성이다. 즉, store에 담기는 해당 데이터 외의 추가적으로 redux store를 비대하게 만드는 것은 saga가 해결하는 문제와는 관련 없는 불필요한 오버헤드라고 생각했다.
redux store가 비대해지면 전반적인 코드베이스 파악이 힘들어지고, 번들도 불필요하게 커진다.
또한 우리 코드는 side effect 의 제어를 제외한 부분까지도 saga로 구현된 부분이 다수 존재했다. 예를 들면 팝업을 열거나 닫는 로직조차 saga로 작성되어 있다. 어떻게 보면 비즈니스 로직까지 saga라는 레이어에 포함시킨 것이다. 그 결과 saga에서 select 혹은 put하기 위해 redux에 있을 필요 없는 상태 조차 redux에 넣고 있었다. 이는 또 한 번 store를 비대하게 만들었다.
5. Typescript 타이핑의 관점
saga는 Typescript native로 작성된 라이브러리가 아니다. 타이핑을 개선하기 위한 커뮤니티 라이브러리 (i.e. typed-redux-saga
) 들이 있지만 이것도 그리 만족스러운 타입스크립트 코딩 경험을 주진 못했다.
다만 개인적으로 DX는 결국 비즈니스를 지탱하기 위한 최 소 생산성을 담보하기 위한 선만 지켜도 된다고 생각하고, typed-redux-saga
를 이용한 개발 경험이 아슬아슬하지만 그 선 이상은 지켜준다고 생각하기에 언급만 하고 넘어가겠다.
위와 같은 이유들로 saga를 떠나 다른 server state 관리 라이브러리로 마이그레이션하는 것으로 결정했다. 그리고 우리의 다음 스텝은 rtk-query
로 결정했다. 관련되어 어떤 어려움이 있었고, 좋았던 점은 무엇이 있는지 등 관련된 이야기는 다음 글에서 다뤄 봐야겠다.
지금까지 우리의 웹 개발 스택을 잘 지탱해준 saga에게 감사를 표하며...