최근 프론트엔드를 Angular로 전면 교체하면서 상태 관리 코드에 관한 고민이 많은 차에 많은 영감을 주는 좋은 글을 발견하여 (처음으로, 제대로) Mark Johnson님의 허락을 얻어 모자란 실력이나마 번역을 해봤습니다.
이에 관한 제 생각과 경험이 더 있는데 그 글은 따로 포스트를 작성하도록 하겠습니다ㅋ

How GraphQL Replaces Redux

Mark Johnson @wmdmark (March 6th 2018)

원문: https://hackernoon.com/how-graphql-replaces-redux-3fff8289221d

"뭐라고요?, GraphQL 은 서버의 쿼리 언어, Redux 는 클라이언트의 상태 관리 라이브러리잖아요. 어떻게 대체가 되죠?"

-라고 말하고 싶으신가요? 좋은 질문입니다.

비웃음은 잠시 넣어두세요. 제가 그걸 설명드리려 합니다.

⚛️ React로의 전환

먼저, 간단히 뒷이야기를 할게요. 2016년, 우리 PathWright 프론트엔드 팀은 클라이언트 코드 베이스를 Backbone & Marionette 스택에서 React 스택으로 스위칭하기 시작했어요. 선언적인 UI 모델은 우리가 다루고 있던 MVC 패턴보다 훨씬 더 진보한거라고 생각했거든요.

그건 정말 신선한 바람이었고, 여전히 그렇게 생각해요.

모든게 아름다웠어요, 상태 관리 측면을 제외하고는. 우리는 재빠르게 Flux 아키텍쳐 도입을 결정했고, 처음엔 그게 굉장한 진보로 느껴졌어요. 순환 데이터 플로우(Circular Data Flow), 단일 소스(Single Source of Truth) 컨셉은 정말 괜찮아 보였어요. 최소한 모델 중심적인 뷰 바인딩을 지향하는 다른 MVC 라이브러리들보다는.

그런데 상태 관리의 복잡도가 증가하면서, 점점 더 덜 직관적인 레이어가 늘어나는 느낌이 들기 시작했어요. 상태 트리 안에 유용한 스토어 혹은 브랜치를 두면, 결과적으로 서버사이드의 비즈니스 데이터와 모델간의 관계가 클라이언트에 중복 구현되었죠.

우리는 정말 아름답고 선언적인 React 컴포넌트들을 갖게 되었지만 한편 액션, 리듀서, 비동기 미들웨어 그리고 정규화되지 않은 비즈니스 데이터/로직으로 가득찬 쥐소굴 (rats nest) 같은 데이터 레이어 역시 갖게 되었어요.

이건, 모두, 잘못되었다고 느꼈죠.

↪️ GraphQL로의 전환

그때 때마침 GraphQL을 시도하고 있었어요. 우리는 여러 개의 서로 다른 데이터소스를 결합해야하는 새 대시보드부터 적용해보기 시작했고, (이걸 REST API 로 구현한다면, 그건 정말 끔찍했겠죠) 곧 완전 빠져버렸어요. 그건 마치 React 를 처음 알았을 때 받았던 느낌 같았어요. 그때 우리의 열정은 정말 대단해서, 프로덕션에 적용할 새 GraphQL 서버를 단 2주만에 개발해냈죠!

바로 이어서, 우리는 수많은 REST API들을 GraphQL 기반으로 전환하기 시작했고, 그건 계속 놀라웠어요.

여기서 파생된 부수적 효과는(sagas? <역주: '부수적 효과'를 side effect로 쓰면서 redux-saga를 떠올린듯>), 새 GraphQL 엔드포인트를 사용하는 우리 UI 가 더이상 스토어가 필요 없어졌다는 거에요. 전혀요. 우리도 처음엔 새 스토어, 액션 등등을 만들며 시작했지만 결국은 그 모두를 다 지워버렸어요. 왜냐하면 그 코드들이 실질적으로 하는 일이 없었거든요.

🤯 세가지 놀라운 깨달음

이로써 세가지의 놀라운 깨달음을 얻었습니다. 분명한 가늠자는 아니지만, 적어도 우리에게는요.

  1. 우리의 상태 관리 코드는 대부분 분산된 REST 리소스들을 받아와 우리 UI 모양에 맞게 데이터를 결합하고(merging) 변조하는(mutating)데 필요했다는 것. (reducers, selectors, actions 등)
  2. 아주 많은 대부분의 복잡한 상태 관리는, 순서에 맞춰 특정 경로에서 데이터를 비동기로 가져와 관리하는 코드들이라는 것. (sagas, middleware, thunks 등)
  3. 실질적으로 이 모든 것들을 제외하고 남는건 UI의 상태, 이건 순수하게 React 의 상태 관리 방식을 사용해도 충분히 깔끔히 동작한다는 것.

“Damn”, we said, “damn,” while plunking coins into the swear jar.

<역주: 이 부분은 번역이 애매한 부분이라 원문을 싣습니다. Swear Jar 는 욕하면 동전을 넣는 저금통이라 두번 Damn! 하면서 동전 넣었다는 뜻이에요. "젠장" 이라고 번역하기엔 좋은 뜻도 섞여있어서ㅋ>

그리고 우리는 그 많은 코드를 지워버렸어요. 기분이 좋았죠.

그래서, GraphQL과 Redux는...

이 글의 제목은 약간 오해의 소지가 있었어요. (그래서 클릭하셨나요?) 우리가 정말로 교체한 것은 REST API였고, 그 결과로 거의 모든 상태 관리를 위한 코드가 더 이상 불필요 하게된 것이죠.

클라이언트가 서버에서 받아오는 데이터를 정확히 원하는 모양으로 컨트롤 할 수 있다면, 또 이걸 단 하나의 요청으로 그럴 수 있다면, 상태 관리를 위한 라이브러리가 필요없다는 뜻이죠.

이걸 잘 설명드리기 위해, 우리의 UI가 상태 관리 라이브러리를 통해 백엔드 서비스와 '대화'하는걸 상상해볼게요.

그건 아마 이런 모습이겠죠:

img

왼쪽: Redux + REST --- 오른쪽: Apollo + GraphQL

Redux와 사이드 이펙트 관리 라이브러리가 해주는 아주 많은 작업들을 간단히 표현하면 위의 그림 중 왼쪽의 대화내용과 같아요.

저는 이 글에서 거의 모든 클라이언트 앱에서 GraphQL이 Redux의 필요를 완전히 대체할 수 있다고 주장하고 싶었어요.

Redux가 아무 쓸데없다는걸 말하려는건 아니에요. Redux는 아주 훌륭한 라이브러리이고 Redux가 소개한 상태 관리 패턴은 꽤 오랜 시간 사용될 거에요.

혹시 이 글을 읽는 여러분들 중 누군가는, 백엔드 스택을 컨트롤 할 권한이 없어서 클라이언트 UI를 구성하는데 반드시 REST를 사용해야 할 수 있어요. 짜증나는 일이지만 그런 환경이라면 Redux는 정말 큰 도움을 주겠지요.

혹시 당신이 '추적 가능'하고 일관성 있는 로우레벨 컨트롤, 예를 들면 클라이언트 캐시나 오프라인 동기화 같은 것들을 포함하는 복잡한 상태 관리가 필요한 경우라면? Redux는 이런 케이스에 최고지요. 사실 인기있는 GraphQL 라이브러리들(e.g Apollo)은 내부에 캐시로써 Redux를 사용할 수 있어요.

하지만...

REST를 대신해서 GraphQL을 사용할 수 있는 경우, 꼭 쓰세요. 이 전환은 당신의 클라이언트 코드에서 엄청난 양의 복잡성을 제거하고, 클라이언트 코드가 담당해야 할 부담을 줄여주어 오직 어떻게 데이터가 UI를 그리는지에만 집중하게 할거에요. (이건 계속 함께 있어야 했죠)

오, 그래도 여전히 GraphQL과 Redux를 함께 쓸 수 있어요, 그게 그렇게 많이 필요하진 않겠지만요. 아마 반 정도 되는 코드는 지워도 상관 없을걸요. 그건 정말 기분 좋은 일일거에요.

🤔 Major League Soccer가 비슷한 경험을 했네요. 이를 적은 훌륭한 포스트가 있으니 한번 읽어보세요: https://dev-blog.apollodata.com/reducing-our-redux-code-with-react-apollo-5091b9de9c2a

👉한번 GraphQL을 시도해보고 싶으셨나요? 여기가 시작하기에 딱 좋은 곳입니다: https://www.howtographql.com/

🤨의견? 질문? 무례한 댓글? 제 트위터를 두드려주세요: https://twitter.com/wmdmark