상태 관리 라이브러리의 발전
TIL 23. 11. 13
오늘 한 일
- 상태 관리 라이브러리의 발전 알아보기
상태 관리
하나의 페이지에서 실시간으로 데이터를 주고 받는 방식의 SPA 구조로 웹 애플리케이션을 개발하게 되면서 많은 상태를 관리할 필요가 생겼다.
상태란 쉽게 말해 화면에 보이는 모든 것들이다. 화면에서 실시간으로 변화하는 데이터와 서버와 주고받는 데이터와 UI 상태 등을 포함한다.
문제는 상태는 실시간, 비동기로 계속해서 변경된다. 이로 인해 상태가 언제, 어떻게, 왜 변화했는지 알 수 없게 된다.
이러한 상태를 관리하기 위해 jQuery 시절부터 오늘까지 다양한 접근법이 제시되었다. 상태 관리 라이브러리의 발전을 살펴보며 상태 관리가 필요한 이유와 어떻게 발전했는지 살펴보고자 한다.
아래 내용은 TECH CONCERT: FRONT END 2019 - 데이터 상태 관리. 그것을 알려주마 영상을 참고해 정리
jQuery 상태 관리
jQuery는 주로 DOM 조작을 위한 라이브러리로, DOM에 jQuery로 동작을 입히는 방식으로 개발한다. 즉, DOM을 토대로 자바스크립트 작업을 한다.
그래서 DOM의 각 Element에 상태를 저장해서 상태를 관리해왔다. 동작을 위한 상태를 가지고 있고 각 상태에 접근해서 처리한 후 Element에 동작을 입힌다.
이러한 jQuery 상태 관리의 문제점은 서로 다른 Element의 상태변화 추적이 어렵다는 것이다. 예를 들어 살펴보자.
Element A와 Element B의 상태를 바탕으로 Element C에 새로운 동작을 추가하려 한다. 순서는 다음과 같다.
- Element A와 Element B를 선택해서 데이터를 가져온다
- 가져온 데이터를 조합한다
- API 호출해 응답 받은 값을 처리한다
- Element C를 선택해 상태를 업데이트한다
이때, 위의 Element C의 상태를 업데이트하기 전에 Element A의 상태가 변경이 되었다고 하자. Element C에는 변경된 Element A의 상태가 반영되지 않은 UI가 사용자에게 보여지게 된다. 상태를 업데이트했으나 엉뚱한 값이 나타나는 이유다.
이는 DOM이 변경되는 시점을 알 수 없어서 발생하는 문제이다. 각 동작에서는 Element 상태가 변경되는 것을 실시간으로 알 수 없다.
복잡한 애플리케이션에서 jQuery를 사용하지 않는 이유이기도 하다.
AngularJS 상태 관리
AngularJS의 상태 관리 방식은 출력할 데이터에 초점을 맞추어 작업이 수행되며, 데이터의 값이 변경되면 출력도 자동적으로 수행되도록 처리된다.
이는 상태 관리의 패러다임을 바꾸는 혁신적인 방법이었다. 기존 jQuery는 데이터가 변경되면 수동으로 데이터를 읽어와 DOM을 업데이트해야 했다. AngularJS는 변수를 변경했을 뿐인데 DOM이 변경이 된다.
- View: 레이아웃과 화면을 처리
- Controller: View에서 사용자 입력을 받아 로직을 통해 state를 변경. 변경된 state를 기반으로 View를 업데이트
- Service: 공통으로 사용되는 logic과 state
- Service에서 데이터를 가져온다
- 가져온 데이터를 조합한다
- API 호출해 응답 받은 값을 처리한다
- Module C를 선택해 상태를 업데이트한다
그런데 마찬가지로 Module C가 업데이트 되기 전에 Module A가 변경되었다면? 역시 C에는 변경된 데이터가 반영되지 않은 UI가 보여진다. 여전히 상태가 변경되는 것을 실시간으로 알 수 없다.
문제점은 여전하다. 그러나 jQuery의 상태 관리 방법과 다른 점은 Service에서 데이터를 가지고 온다는 것이다. 공통된 데이터는 Service에 있으므로 state를 변경하는 logic은 보통 Service 내에 구현한다.
필요한 상태를 가져와서 각각의 동작 구현 코드를 찾아서 console.log
를 찍어 순서를 확인했어야 하는 jQuery. 반면에 AngularJS는 확인해야할 부분이 Service로 한정된다.
(+) MVC 구조
사용자의 입력 혹은 이벤트가 발생(Action)해 데이터 변경이 필요해지면 Controller를 통해 Model에 해당 데이터를 반영한다. Model에서 특정 데이터가 변경되면 View에 반영해 사용자가 변경된 화면을 보게 된다. 이러한 구조를 MVC 구조라고 한다.
- Model: 데이터와 비즈니스 로직을 관리
- View: 레이아웃과 화면을 처리
- Controller: 모델과 뷰로 명령을 전달
MVC 구조에서는 View에서도 데이터가 발생할 수 있다(e.g. 사용자 입력). View에서 Model로 데이터를 반영할 수도 있는 양방향 데이터 흐름이 발생한다. MVC 구조의 문제점은 여기서 드러나는데 애플리케이션의 규모가 커질수록 데이터 흐름이 복잡해진다는 점이다.
AngularJS는 방식은 다르지만 MVC 구조에 기반한다. 이런 양방향 데이터 이동이 가능한 구조는 컴포넌트가 복잡해질수록 상태를 부모 컴포넌트까지 끌어올리고(lifting state up), 해당 상태가 필요하지 않은 중간 컴포넌트들에게도 prop으로 전달하는 prop drilling 문제를 야기한다.
Redux 상태 관리
AngularJS의 등장에도 상태(데이터)를 언제, 왜, 어떻게 변화했는지 알기가 어려웠다. Redux는 이러한 문제를 해결하기 위해 ‘Flux, CQRS, Event Sourcing’ 세 가지 개념을 조합해 만들어졌다.
FLUX
React 라이브러리는 단방향의 데이터 흐름을 갖도록 설계되었다. View의 역할만을 하는 React는 데이터를 전달받아 어떻게 보여질 지를 고민한 라이브러리이다. React 공식 홈페이지에서도 React를 다음과 같이 소개하고 있다.
사용자 인터페이스를 만들기 위한 JavaScript 라이브러리
Flux는 Facebook에서 단방향 데이터 흐름을 보완하기 위해 개발된 아키텍처이다.
- View: 레이아웃과 화면을 처리
- Store: 모든 상태와 그와 관련된 로직을 관리
- Dispatcher: 모든 데이터의 흐름을 관리(Action과 Store 매핑 포함)
- Action: Store의 상태를 변경하는 방법
데이터 흐름(the data flow)
- Action creator - 애플리케이션의 상태를 변경하거나 뷰를 업데이트하기 위해 액션을 생성한다. 액션을 생성한 뒤에는 Dispatcher로 넘겨준다.
- Dispatcher - 들어온 액션의 순서에 따라 Store에 액션을 전송한다. 액션 타입과는 관계없이 등록된 모든 Store로 보내진다.
- Store - 필요한 액션만을 골라서 상태를 필요에 맞게 변경. 상태 변경이 완료되면 새로운 상태를 Controller View에 넘겨준다.
- View - 새로운 상태에 맞게 렌더링
간단히 요약하면 View에서 사용자가 상호작용을 일으키면 중앙의 Dispatcher를 통해 Action을 전파한다. 상태와 로직을 가지고 있는 Store는 Action이 전파되면 해당 Action에 연관된 모든 View를 갱신한다.
댓글남기기