Web: React Flux 패턴

Heechan
HcleeDev
Published in
7 min readSep 24, 2021
Photo by Leonardo Zorzi on Unsplash

React 공부를 좀 하다보니, 뭔가 상태 관리나 관련 메서드들을 한번에 모아둔다는 느낌이 들었다. 지금까지 모바일 개발을 할 때는 딱히 만나본 적 없는 방법 같은데, 특이한 것 같아 찾아보니 웹 개발, React에서 자주 쓰이는 Flux 패턴임을 알 수 있었다.

이번주는 간단하게 Flux 패턴에 대해 알아보도록 하자. 추석 연휴라 글 쓸 시간이 좀 줄어들어서…

왜 Flux가 등장했는가

모바일 애플리케이션도 그렇고, 웹 애플리케이션도 그렇고, 기존에는 MVC 패턴을 많이 사용했나보다. MVC 패턴에 대해서는 iOS 개발 관점에서 이전에 쓴 글이 있으니, 이에 대한 자세한 내용은 그쪽을 참고하면 된다.

iOS의 MVC는 ViewController를 중심으로 한 디자인 패턴이었고, ViewController 하나가 화면 하나를 끌고 가고 있었다고 볼 수 있었다. 웹앱에서의 MVC는 Controller가 하는 역할이 그보다도 조금 컸던 것 같다. Single Page App의 경우에는 화면 하나를 계속 끌고 가는 상태이다 보니, 아래 그림처럼 되버렸을 것이다.

실제로 컨트롤러가 모델도 관리하고, 뷰도 관리해야 하는 상황에선 위처럼 구조가 굉장히 복잡해질 수 있다. 특히 React는 Single Page App, 하나의 페이지로 앱을 다루는 경우가 많은데, 단 하나의 Controller로 여러가지 View와 Model을 관리하면 깔끔해지긴 어렵다.

그리고 한 View에서 일어난 상호작용 때문에 여러 Model이 변경되거나, 그 반대의 일도 벌어지기 때문에 정말 잘 짜지 않는 이상 코드를 이해하기도 굉장히 어려울 것이다.

따라서 페이스북은 이렇게 데이터가 중구난방으로 전달되는 상황을 줄이고 보다 깔끔하게 만들고 싶어, Flux 패턴을 만들어낸다.

Flux 패턴이란

어디서 어느 방향으로 데이터가 전달될지 알지 못할 정도로 혼란한 MVC 패턴의 복잡성을 해소하기 위해, Flux 패턴에서는 데이터가 한 방향으로만 흐르도록 했다.

이게 기본적인 Flux의 형태로, 조금 뒤에서 더 자세히 설명하겠지만 어떤 Action이 발생하면, Dispatcher에서 이를 받아와 해석한 후 Store에서 저장된 정보에 변경을 가하고, 그 결과가 View로 다시 전달되도록 한다.

그런데 모바일에서 터치를 하는 것처럼, 웹에서도 사용자가 View를 통해서 클릭 같은 액션을 발생시킬 수 있다. 그런 경우도 고려하면 아래와 같은 흐름이 만들어진다.

이러면 뭐가 단방향이냐… 라고 볼 수도 있겠지만, 전달된 데이터가 View에서 다시 돌아오는 것은 아니니 단방향이 깨진다고 볼 이유는 없는 것 같다.

어디에서든 Action이 발생하면, Dispatcher를 통해 단방향으로 흘러간다고 보면 될 것 같다.

그러면 각 단계에 대해서 좀 더 자세히 알아보자.

Action

여기서 액션은 특별한 계층이라고 하기는 어려워보인다. 이 구조에서 이 Action은 정확히 Action Creator라고 생각하면 된다. 위에서 말한 것 같으면 클릭 같은 이벤트가 발생했을 때 그 이벤트가 발생했음을 Action 정보를 담고 있는 객체를 만들어내 Dispatcher에 전달하는 역할을 한다.

Dispatcher

Dispatcher는 들어오는 Action 객체 정보를 받아 실제로 어떤 행동을 할지 결정하는 곳이다.

주로 switch 문으로 들어오는 Action 객체를 나누어 처리한다. 미리 정해둔 Action 객체의 type 을 구분해 미리 작성해둔 명령들을 수행한다.

흔히 쓰이는 표현으로 Dispatcher는 중앙 허브 역할을 하고 있다고 한다. Dispatcher에서는 주로 Store에 있는 정보에 접근해 수정하는 명령이 많다. 이때 상태 관리와 관련한 문제가 있을 수 있다. Store에 있는 상태 사이의 의존성이 있을 경우 이를 관리하는 것도 Dispatcher가 하는 일이다.

Store

데이터, 상태를 담고 있다. React에서 우리는 이 Store를 Dispatcher와 연결해 Store에 접근할 수 있도록 callback 명령을 제공할 수 있다.

또한 여기서 가지고 있는 상태에 View가 접근하고, 상태가 변경되면 View에서도 이를 반영한다.

View

View는 우리가 알고 있는 그 View의 역할을 일단 하고 있다. Store에서 어떤 이벤트(변경 등)가 발생하면 View는 변경된 점을 가져오고, 이를 바탕으로 화면을 다시 랜더링한다. 언젠간 다룰 날이 오겠지만 이 랜더링을 어떻게 처리하느냐가 성능에 큰 영향을 끼친다.

React에서 View는 특이하게도 언제나 보여주는 역할만을 하는 것은 아니다. Controller-View라는 존재가 있을 수 있는데, 이는 상위에서 하위 View들에게 어떤 상태나, Dispatcher 등을 제공하기 위해서 하위 View를 감싸는 형태로 존재한다. 그런 방식으로 감싸면 굳이 하위 View로 계속 넘겨주는 불편함을 겪을 필요가 없어져서 적절히 활용하면 도움이 된다.

Flux 패턴 예시

정말 간단하고 단순한 카운터 예시를 하나 만들어보자. 단순하게 버튼을 누르면 숫자가 1씩 올라가는 카운터라고 생각해보자.

일단 Store에 해당하는 부분을 간단하게 만들어보았다. 원래 상태에 들어있는 정보는 달랑 number 보다 많은 경우가 많겠지만, 일단 여기선 number 만 넣었다.

그 밑에 reducer 함수는 React의 useReducer 에 넣어서 Dispatcher에 제공해줄 메서드이다. 이 함수는 상태와, Dispatcher가 받은 Action에 따라 어떤 명령을 수행할지 그 내용을 Callback으로 제공한다고 볼 수 있다.

여기서는 ADD 라는 타입의 Action 객체를 받으면, 현재 number 에서 1을 추가해 새로운 객체를 상태로 넘겨준다. 다른 타입의 객체라면, 그냥 현재 상태를 그대로 돌려준다.

React에서 제공하는 useReducer 를 이용해, 위에서 만들었던 reducerinitialStatestate , dispatch 를 얻는다. 여기서 state 는 View가 상태에 접근할 수 있도록 하고, dispatch 는 Dispatcher의 역할을 한다.

여기서 Action Creator는 View에 들어있는데, <button onClick={onAdd}> 를 보면 버튼에 클릭이라는 이벤트가 생겼을 때, onAdd 가 실행된다.

onAdd는 Action 객체를 만드는 역할을 하고 있다. onAdd 에서는 Action 객체, { type: 'ADD' } 를 만들어서 dispatch , Dispatcher에게 넘긴다. Dispatcher는 이 Action 객체를 reducer 메서드에 맞춰 해석해 Store를 업데이트한다.

Store가 업데이트되면 이 View의 <h1>{state.number}</h1> 에서도 변경을 감지하고 화면을 다시 랜더링할 것이다.

사실 이정도는 React에서 제공하는 useState 로 간단하게 하면 되긴 하는데… useReducer 를 사용하는 편이 Flux 패턴이 더 잘보이는 것 같아 살짝 쓸데없이 복잡하게 만들었다.

실제로 구동해봐도 잘 올라가는 모습이다.

결론

Flux 패턴도 꽤 깔끔해보이긴 하지만, 아직 내가 MVVM에 익숙해서 그런가, MVVM이 좀 더 좋은 것 같다. Flux의 문제는, reducer 가 상당히 비대해질 수 있다는 것이 아닐까 싶다.

상태 관리 라이브러리에는 Redux라는 것도 있는데, 이 Redux가 Flux 패턴을 따르고 있다. 꽤 호평을 받고 많이 사용되는 라이브러리니 관련 공부를 해보는 것도 괜찮을 것 같다.

참고한 것

Flux | 사용자 인터페이스를 만들기 위한 어플리케이션 아키텍쳐 (haruair.github.io)

--

--

Heechan
HcleeDev

Junior iOS Developer / Front Web Developer, major in Computer Science