![[블로깅] Redux&FLUX패턴](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbUPpT%2FbtsbTuDAkka%2F96WmbJSMgutfHOGSx8ktok%2Fimg.png)
FLUX 패턴?
FLUX패턴은 단방향 데이터 흐름을 통해 예측가능하게 상태를 관리할 수 있게 해주는 클라이언트 사이드 웹 애플리케이션 아키텍처입니다.
기능에 따라 코드를 구성하여 각 구성요소가 독립적으로 작동하는 것을 목표로 하는 MVC패턴과 달리 FLUX패턴은 엄격한 단방향 데이터 흐름을 통해 데이터 흐름을 예측 가능하도록 하는 것이 목표입니다.
FLUX패턴의 흐름
FLUX패턴은 ACTION, DISPATCHER, STORE, VIEW로 구성됩니다.
이때 흐름은 다음 그림과 같습니다.
- ACTION : Ajax나 View에서 발생한 상태 변경 요청
액션 생성자는 타입(type)과 페이로드(payload)를 포함한 액션을 생성합니다.
액션 생성자가 액션 메시지를 생성한 뒤에는 디스패쳐(dispatcher)로 전달합니다. - DISPATCHER : Action을 모든 스토어에게 전달하는 전달자 역할
여러 스토어에 액션을 보냅니다.(동기적)
스토어가 자신이 액션을 처리할 실행 순서를 Dispatcher에게 알려줄 수 있기 때문에 Dispatcher에서 Store 간 의존성을 관리할 수 있습니다.
만약 스토어 사이에 의존성이 있어서 하나를 다른 것보다 먼저 업데이트해야한다면 waitFor()을 사용해서 디스패쳐가 적절히 처리하도록 할 수도 있습니다. - STORE : 어플리케이션 상태가 저장되어 있는 전역 저장소
Dispatcher에서 전달된 Action을 통해서만 상태를 변경합니다.(외부에서 직접 수정 X, 액션을 받아 스토어의 상태 변경)
상태 변경 로직을 가져 전달된 Action에 따라 상태 변경 결정 가능 보통 switch statement를 사용해서 처리할 액션과 무시할 액션을 결정하게 됩니다.
상태가 변경되면 변경 이벤트(change event)를 내보냅니다. 이 이벤트는 컨트롤러 뷰(the controller view)에 상태가 변경했다는 것을 알려줍니다. - 컨트롤러 뷰와 뷰
관심있는 애플리케이션 상태가 변경될 때마다 다시 그려주는 컴포넌트 뷰는 최신 상태를 반영한 화면을 렌더링 하는 역할을 맡습니다.
컨트롤러 뷰는 스토어와 뷰 사이의 중간관리자같은 역할을 합니다.
상태가 변경되었을 때 스토어가 그 사실을 컨트롤러 뷰에게 알려주면, 컨트롤러 뷰는 자신의 아래에 있는 모든 뷰에게 새로운 상태를 넘겨줍니다.
Dispatcher에게 Action을 요청할 수 있습니다.- Controller-View(React) → Store의 상태 변경 수신+받은 상태에 따라 View 새로 렌더링
- Controller-View(React) → Store의 상태 변경 수신+받은 상태에 따라 View 새로 렌더링
장점과 단점
데이터 흐름을 구조화할 수 있습니다. 전체 흐름을 파악할 필요 없이 액션을 따라가면서 어떠한 변경이 가해지는지 쉽게 알 수 있습니다. 따라서 코드 유지 보수가 쉬우며 새로운 기능을 확장할 때 편리합니다.
그러나 초기 작은 기능을 정리하기에 상대적으로 많은 코드를 필요로하며 문법이 장황하다는 단점이 있습니다.
우리는 Redux라는 상태 관리 라이브러리를 통해 쉽게 flux패턴을 구현할 수 있습니다.
Redux
리덕스는 상태를 하나의 store에 저장하는 단일 스토어 아키텍처입니다. 불변 객체로 상태 변경 사항을 관리하기 때문에, 상태 관리에 대한 예측 가능성과 디버깅 용이성을 제공합니다. 다양한 미들웨어를 지원하여 비동기 작업 처리와 같은 고급 기능도 쉽게 구현할 수 있습니다.
Redux 역시 Action -> Dispatch ->Reducer -> Store 순서로 데이터가 단방향으로 흐릅니다.
- 액션은 어떤 액션을 취할 것인지 정의해 놓은 객체입니다.
- Counter의 경우 다음과 같은 액션이 있을 수 있겠습니다.
//1씩 증가하는 카운터 payload가 필요없음
{ type: 'INCREMENT' }
//1씩 감소하는 카운터 payload가 필요없음
{ type: 'DECREMENT' }
//원하는 값만큼 증가하는 카운터 payload가 필요함
{type: 'INCREASE', payload: Number(원하는 값)}
보통 액션 생성자 함수를 통해 사용하는 경우가 많습니다.
const increase = () => {
return {
type: 'INCREMENT'
}
}
- Reducer는 Dispatch에게 전달받은 Action 객체의 type에 따라 상태를 변경시키는 함수입니다.
const counterReducer = (state = 0 , action) => {
switch(action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
case 'INCREASE' : return state + action.payload;
default: return state;
}
}
- Dispatch는 Reducer로 Action을 전달하는 함수입니다. 전달인자로 Action 객체가 전달됩니다.
//직접 action 객체를 작성하는 경우
dispatch( { type: 'INCREMENT' } );
dispatch( { type: 'INCRESE', payload: 10 } );
//액션 생성자를 사용하는 경우
dispatch(increase());
- Store는 상태가 관리되는 오직 하나뿐인 전역 저장소입니다. createStore메서드로 Reducer를 연결하여 Store를 생성할 수 있습니다.
import { legacy_createStore as createStore } from 'redux';
const store = createStore(rootReducer);
Redux Hooks
useDispatch() 메서드는 Dispatch함수를 반환하는 메서드입니다.
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch(increase())
useSelector()를 사용하여 state에 접근할 수 있습니다.
import { useSelector } from 'react-redux'
const counter = useSelector(state => state)
그래도 복잡해보인다고요? redux-toolkit을 사용하면 더 간결하고 편리하게 코드를 작성할 수 있습니다. 이 부분은 시간이 나면 따로 다뤄보겠습니다.
https://redux-toolkit.js.org/
'BootCamp' 카테고리의 다른 글
[블로깅] Cookie, Session, Token, OAuth2.0 (0) | 2023.05.04 |
---|---|
[블로깅]웹 표준과 웹 접근성 (0) | 2023.04.27 |
[블로깅]UI/UX (0) | 2023.04.13 |
[블로깅]REST-API (4) | 2023.03.29 |
[React-twittler] 자식 컴포넌트에서 부모 컴포넌트로 데이터 보내기 (0) | 2023.03.24 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!