상태관리를 찾아서

11t518s·2022년 9월 7일
2
post-thumbnail

FE개발을 하면 상태관리를 빼놓을 수 없습니다.

혹시 여러분들이 상태관리를 하는 목적은 어떤것인가요?

기존에 저희 서비스는 전역에 ContextApi를 하나만 두고 나머지는 스크린 내부에서 호출하고 관리했습니다.

처음에는 이러한 것을 긍정적으로 생각했습니다.
최근 React-Query, Swr이 원하는 것처럼 "서버 데이터를 굳이 상태로 관리할 필요가 있을까?" 라는 부분에서 의문을 갖고 입사했기 때문에 회사의 방식에 동의를 했었습니다.

그러다가 코드를 더 많이 만들고 리팩토링을 하고, 디버깅을 하고, 제 코드를 다른 개발자님들이 봐주시면서 상태관리가 필요한 이유를 알게 됐습니다.

그러면 제가 상태관리를 도입하려고 한 큰 이유는 다음과 같습니다.


1. Props drilling을 하기 싫다.

말 그대로 Props drilling이 싫었습니다.
여기서 보다 명확히 표현하면 Props로 인자를 넘겨주는 코드들이 싫었습니다.
컴포넌트마다

type Props = {
  exampleState: any;
  setExampleState: Dispatch<SetStateAction<any>>;
}

const ExampleComponent: React.FC<Props> = ({exampleState, setExampleState}) => {
	return (
    	...
    )
}

상태를 이런식으로 단순한 상태의 타입을 지정하고 넘겨주는 일이 많아질 수록 추상적인 재사용 가능한 컴포넌트를 만들기 보단 종속적인 컴포넌트를 만들 수 밖에 없었습니다.

다시 말하면 단순히 코드가 길기 때문에 컴포넌트를 나누게 됐습니다.
(물론 종속된 상태 별로 나누거나, 혹은 관심사 별로 나누긴 했지만 저러한 이유 때문이기 보단 코드가 길어져서 나눈 듯 합니다.)

그래서 Props는
1. 명확히 종속적인 컴포넌트
2. 뷰와 비즈니스로직을 나누는 등 특별한 목적에 의해서 만들어진 추상적 컴포넌트

위 두 상황에만 넘겨주고 싶었고 그러기 위해서 상태를 스크린에 종속시키지 않고 싶었습니다.


2. 관심사 분리

기존까지는 ContextApi에 최소한의 데이터가 있고, 나머지 필요한 데이터들은 스크린에 모여있었습니다.

이렇게 되면 그 스크린이 어떻게 동작하는지 이해하기는 좋았습니다.
맨 처음 회사에 와서 수정 할 스크린이 생겼을 때 그 스크린에서 모든 동작이 이뤄졌기 때문에 그 스크린만 이해하면 됐기 때문에 좋았던 것도 있었습니다.

그런데 하나 이상의 스크린에서 필요한 수정사항을 다룰 때 간단한 하나의 변경사항에도 수 많은 파일들을 수정해줘야 했습니다.
( 최근 유저를 즐겨찾기하고 닉네임을 넣어주는 로직을 진행했는데 걸리는 스크린이 많아서 변경 파일만 70개 가까이 됐던 것으로 기억합니다. )

물론 많은 파일을 변경할 수는 있다고 생각합니다!
그러나 리팩토링이나 디버깅을 할 때 해당 요소를 찾아서 바꿔주는 그 과정이 조금 험난했습니다.

뷰를 수정해주고 싶어도 스크린에 들어가서 비즈니스 로직들을 지나 return 문 아래에 있는 뷰의 영역에 도착해야 했고,
비즈니스 로직을 수정하고 싶어도 스크린에 종속된 수 많은 function들 중 내가 원하는 것을 찾아서 수정해줘야 했고,
다음 스크린 그리고 또 다음 스크린에서 동일하게 진행해줘야 했습니다.

그럼 이제 질문을 할 수 있는게

Q. 상태관리가 문제가 아니라 컴포넌트를 잘 못나눈 것이 아니냐?

A.
컴포넌트를 잘못 나눈 문제가 맞지만 그건 궁극적인 문제라고 생각했습니다.
근본적인 원인은 상태와 로직이 너무 스크린에 종속적이었기 때문에 종속적인 컴포넌트를 많이 만들었던 것이 문제였다고 생각합니다.
1. 그래서 상태를 스크린 밖으로 내보내고,
2. 자연스럽게 상태를 관리하기 위한 비즈니스 로직들도 스크린 밖으로 내보내고,
3. 재사용 할 수 있고 추상적인 컴포넌트를 만들기 시작할 수 있다고 생각했습니다.


Recoil

그래서 선택한 상태관리는 Recoil이었습니다!

전에 React-Native 버전업 고생기에서도 잠깐 언급했는데 Recoil을 선택했습니다.

선택한 가장 큰 이유는 다음과 같습니다

  1. 빠르게 익히고 빠르게 적용할 수 있는 것 (Redux... bye..)
  2. 꾸준한 업데이트를 지원받을 수 있을 것
  3. 우리가 사용하고 있는 큰 틀에서의 흐름과 달라지지 않을 것

ContextApi를 떠나기로 한 이유

사실 랜더링 최적화는 큰 문제가 되지 않았습니다.

랜더링 최적화를 하고 싶다면 차라리 React.memo(물론 이렇게 쓰지 말라고 했지만,,,)를 더 잘 해줘도 되고, 다들 디바이스에 컴퓨팅 파워가 충분히 좋아서 state만 잘 관리해주면 큰 문제는 되지 않을 거라 생각했습니다.

그렇지만 보다 명확하게 Screen에 있는 상태와 비즈니스 로직을 외부로 내보내려면 여러개의 Context를 만들어주는 것이 좋았고, 그럴거면 필요없는 리랜더링도 없고 코드도 더 간결한 상태관리 라이브러리들을 사용하는게 좋다고 생각했습니다.

가장 크게 고민한 것은 Redux를 사용할까 Recoil을 사용할까 였습니다.

Redux를 선택하지 않은 이유

먼저 1번의 경우 다들 공감하겠지만 Redux는 하나의 상태에도 굉장히 많은 코드가 들어옵니다. Redux-toolkit을 사용해도 redux-saga 를 함께 사용해주면 그래도 많은 코드들이 생기게 됩니다.

제가 처음에 입사할 때 상태관리에 거부감이 있었던 이유도 Redux를 사용하면서 정말 단순한 post api하나 역시 reducer를 만들고 방대해지는 코드를 보면서 아... 이러면.. 안되겠구나,,, 하는 생각을 했습니다.

이런저런 이유로 저희는 스타트업.
생존해야했고, 이 것들을 바르게 이해하고 적용시키기보단 빠르게 하고 싶었습니다.

Recoil을 선택한 이유

그러고 남은 선택지에서 Recoil을 선택했습니다! 일단 React를 위한 라이브러리이자 Meta에서 공식 지원하는 라이브러리이기도 하고, 아직 공식버전이 나오진 않았지만 React-Native도 사용하고있는 마당에 굳이 거부할 이유가 없었습니다.

그리고 FE개발자가 모두가 고민하는 에러핸들링과 비동기 처리 관련해서 Suspense와 ErrorBoundary를 사용하고 싶은 마음이 컸던 터라 Suspense를 사용할 수 있는(loadable은 눈감자) Recoil에 마음이 많이 갔습니다.

무엇보다 굉장히 간편하게 사용할 수 있다는 점에서 매력을 느꼈고, 우리는 최소한의 데이터만 전역상태로 관리하기 때문에 이러한 점도 비슷하게 가져갈 수 있다고 생각했습니다.


이제 다음에는 Recoil을 사용하면서 느낀 후회와 고민을 공유하는 시간을 갖으려 합니다!

혹시 이 글을 읽으신 분들은 어떤 고민을 하면서 상태관리를 결정하고 사용하고 계신가요?

profile
사람들에게 행복을 주는 서비스를 만들고 싶은 개발자입니다!

0개의 댓글