💡 이번에 배운 내용
- Section3. 사용자 친화적이고 안전한 Web App을 만들 수 있다.
- Unit4. React 상태 관리: 프론트엔드 개발에서 React 상태 관리를 보다 더 효율적으로 할 수 있는 방법에 대해서 학습한다.
Redux를 공부하는 데 열심히 잘 따라왔지만, 바짝 집중하지 못하면 제대로 못할 수도 있겠다는 생각이 들었다.
그래서 실습도 잘 될 때까지 2번씩 하고 학습내용도 두세번씩 읽었다. 여기에 블로그까지 정리하니 어느 정도 이해는 된다.
react는 이렇게 할 때는 재밌도 있고 이해도 되고 실습도 잘 되었지만,
나중가서 처음부터 하려면 손이 막히는 경우가 많다. 코드가 안 나와!
그러므로 잘 아는 거라도 방심하지말고 복습해야 한다는 점을 여실히 느꼈다.
컴퓨터 언어가 자연어가 아닌 인공어지만, 그래도 언어라는 점을 들어 예전 언어학시간에 교수님이 해주신 말을 여기에 적용해 볼 수 있을 것 같다.
"어느 정도 문법을 배웠으면 자꾸 문법에 집착하지 말고, 잘 쓰는 문장을 자꾸 따라 읽고 외워!!"
Redux, state, Action 객체, Dispatch, Reducer, Store, useDispatch, useSelector
상태(state)는 UI, 프론트엔드 개발에서 "동적으로 표현되는 데이터"이다.
이 상태를 다룰 때에는 Side Effect(부수 효과. 함수의 입력 외에도 함수의 결과에 영향을 미치는 요인)을 잘 고려해야 한다. 대표적인 Side Effect로 네트워크 요청, API 호출 등이 있다.
React로 개발할 때 이런 부수 효과를 최대한 줄이고 컴포넌트 단위로 개발하는 것이 좋다.
하지만 어쩔 수 없이 사용해야 될 때가 있다.
이러한 점을 반영하여 상태의 위치를 잘 선택해야 한다.
상태의 위치에 대한 내용은 공식 문서의 다음 링크에서도 잘 소개하고 있으므로 사전에 읽어보면 좋다.
🔗 React - React로 사고하기
상태를 구분하는 데에 따로 법칙이 있는 것은 아니나 상태는 크게 전역, 로컬 상태로 나뉜다.
위 개념을 바탕으로 다음과 같은 원칙이 있다.
Props Drilling은 상위 컴포넌트의 state를 하위 컴포넌트에서 사용하기 위해 계속 props를 통해 전달하는 현상을 의미한다.
이 과정에서 하위 컴포넌트가 더 깊은 수준으로 들어갈수록, 중간에 이 상태를 사용하지 않지만 강제로 props 속성을 사용해 state를 전달해야하는 컴포넌트가 생기게 된다.
만약 이 전달 횟수가 많아진다면 다음과 같은 문제가 발생한다.
Props Drilling의 문제점을 해결하기 위해 상태 관리 라이브러리를 사용할 수 있다.
상태 관리 라이브러리로 전역으로 상태를 저장하고 사용할 수 있다.
물론 상태 관리 라이브러리가 반드시 필요한 것은 아니므로 때에 따라 적절히 사용하도록 한다.
대표적인 상태 관리 라이브러리 중 Redux가 있으며, 여기서는 Redux를 위주로 다룰 예정이다.
여러 컴포넌트가 존재하고 상,하위 컴포넌트 모두 같은 상태를 사용한다면
상태는 최상위 컴포넌트에 위치해야 한다.
그러나 만약 이 상태를 사용하는 컴포넌트가 많아질수록 다음과 같은 문제점이 생긴다.
그러나 위에서 언급한 상태 관리 라이브러리 중 Redux를 사용하면 이 상태를 보다 효과적으로 관리할 수 있다.
Redux는 다음과 같은 순서로 상태를 관리한다.
Redux를 사용하는 방법은 아래와 같다.
1) Store 생성 후 Reducer 함수 할당하기
2) Reducer함수 생성하기
3) Action 객체 작성 및 생성하기
4) Dispatch함수로 Action 객체 전달하기
5) Redux Hooks 사용하기
각 과정은 다음 항목에서 자세히 살펴볼 예정이다.
전역 상태 저장소를 만들기 위해 createStore 메서드를 불러와야 하며,
상태를 저장소에 저장해줄 reducer함수를 인자로 전달한다.
import { createStore } from 'redux';
//저장할 변수=createStore(임의의 reducer 함수명)
const store = createStore(myReducer);
Reducer함수는 인자가 두개로 첫번째 인자는 변경될 state, 두번째 인자는 action 객체이다.
Reducer는 Dispatch에서 전달받은 Action 객체를 확인하고,
그 값에 따라서 상태를 변경시킨다.
이 때, Reducer는 순수함수여야 하는데 이외의 방법으로 상태가 변경되서는 안되기 때문이다.
주로 아래의 action.type처럼 객체 안의 type값을 확인해 상태를 조정할 수 있다.
그리고 리턴한 상태는 Store에 저장된다.
const num = 0
// Reducer는 기존 상태를 받아 새로운 상태를 리턴하여 저장소에 저장한다.
// Reducer(state, action)
const counterReducer = (state = num, action) => {
// Action 객체의 type 속성값에 따라 분기
switch (action.type) {
case 'INCREASE':
return state + 1
case 'DECREASE':
return state - 1
// 해당 되는 경우가 없을 시 기존 상태를 그대로 리턴
default:
return state;
}
}
만약 여러 개의 Reducer를 사용하려면
아래와 같이 Redux의 combineReducers 메서드를 사용해서 하나의 Reducer로 통합한다.
import { combineReducers } from 'redux';
const rootReducer = combineReducers({
myReducer,
yourReducer,
...
});
Action객체의 형식은 아래와 같다.
//예시1)
{ type: 'INCREASE' }
//예시2)
{ type: 'SET_NUM', payload: 2 }
Action 객체를 작성할 때는 다음과 같은 몇가지 규칙이 있다.
이 Action은 보통 직접 작성하지 않고 아래처럼 생성함수를 만들어 사용하는 경우가 많다.
이를 액션(객체) 생성자(Action Creator)라고 한다.
//예시1)
const increase = () => {
return {
type: 'INCREASE'
}
}
//예시2)
const setNum = (n) => {
return {
type: 'SET_NUM',
payload: n
}
}
Dispatch는 Reducer로 Action을 전달해주는 함수이다.
Action 객체를 전달인자로 받으며 Reducer를 호출한다.
사용법은 아래와 같다.
// Action 객체 직접 작성
dispatch( { type: 'SET_NUM', payload: 2 } );
// 액션 생성자 사용
dispatch( setNum(2) );
컴포넌트와 redux의 state를 연결하기 위해 Redux Hooks를 사용한다.
Redux Hooks의 메서드는 React-Redux에서 제공하며 크게 두가지가 있다.
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch( increase() )
dispatch( setNum(2) )
import { useSelector } from 'react-redux'
const num = useSelector(state => state)
Redux의 원칙을 아래와 같이 정리했다.
Single source of truth
동일한 데이터는 항상 같은 곳에서 가지고 와야 한다.
즉, Redux의 데이터 저장소는 전역 상태 저장소인 Store만 있어야 한다.
State is read-only
상태는 읽기 전용이라는 의미다.
React에서 상태갱신함수로만 상태를 변경할 수 있었던 것처럼, Redux의 상태도 직접 변경할 수 없다.
Action 객체가 있어야만 상태를 변경할 수 있다.
Changes are made with pure functions
상태 변경은 순수함수로만 가능하다.
상태를 변경하여 store에 저장하는 Reducer함수는 상태가 엉뚱한 값으로 변경되는 일이 없도록 순수함수로 작성되어야한다.
1. Redux 공식 문서
https://redux.js.org/
2. React Redux 공식 문서
https://react-redux.js.org/
3. flux pattern
https://facebook.github.io/flux/docs/in-depth-overview/
Flux 패턴이란 데이터 흐름에 대한 애플리케이션 아키텍쳐 중 하나이다.
이 패턴은 기존 MVC모델에 기반한 양방향 데이터 흐름의 문제를 해결하기 위해 페이스북에서 고안했다.
Flux 패턴에서는
action -> dispatcher -> store -> view
이런 흐름으로 데이터가 단방향으로 흐르도록 한다.
이름도 그렇고 모양새도 Redux와 참으로 유사함을 알 수 있다.
기존 문서가 짧지도 않고 40분이 넘는 동영상에 영문이므로 쉽게 이해 수 있는 또다른 참고 문서들을 아래에 정리했다.