상태🧐
상태(state)란 UI에 동적으로 표현될 데이터를 의미한다. 즉, 보여지는 화면에서 변화될 수 있는 데이터를 의미하는데 이 때 state는 props를 통해 전달되지 않으며 시간이 지나 변화될 수 있고 컴포넌트 안에 있는 다른 state나 props를 통해 계산이 가능하지 않아야 한다는 조건을 가진다. 이를 통해 컴포넌트 안에는 최소한의 상태를 만들게 된다.
Side effect😎
Side effect란 함수(컴포넌트)의 입력 외에도 함수의 결과(출력)에 영향을 미치는 요인으로 side effect의 대표적인 예시로 네트워크 요청(API 호출)이 있다. 함수를 정의할 때 side effect는 최대한 배제할 수 있도록 작성해야 하지만 네트워크 요청과 같이 불가피하게 side effect에 의존하는 경우도 있는데 이 경우 상태를 잘 고려하여 만들어야 한다.
Props Drilling❓
Props Drilling이란 상위 컴포넌트의 state를 특정 하위 컴포넌트로 전달하기 위해 그 사이에 위치한 컴포넌트들은 props를 전달하는 용도로만 쓰이게 되는 현상을 말한다.
Props Drilling의 문제점
Props Drilling 이슈 해결 방법
Redux는 왜 필요할까❓
깊이 3단계 트리 구조의 컴포넌트들로 구성된 애플리케이션의 경우 각기 다른 부모를 가진 가장 하위의 2개의 컴포넌트들만 하나의 상태를 공유한다고 가정해보자. 이 때 2개의 컴포넌트가 상태를 공유하기 위해 공통으로 공유할 수 있는 최상위 컴포넌트에 하나의 상태를 위치시킨다. 이 경우에는 비교적 단순해 보일 수 있지만 이보다 훨씬 더 높은 단계의 트리 구조를 가진 애플리케이션의 경우라면 어떠한 일이 발생할까?
- 사이에 있는 컴포넌트는 불필요한 상태 데이터를 가지게 됨
- 상태를 끌어올리고 props를 내려주는 과정의 반복을 거쳐야 함
- 컴포넌트의 구조가 바뀔 경우 데이터 흐름 자체가 바뀔 수 있음
❗️Redux는 하나의 저장소인 Store에서 전역 상태를 관리하여 문제를 해결❗️
Redux가 상태를 관리하는 순서
- 상태가 변경되어야 하는 이벤트 발생 시, 변경될 상태 정보가 담긴 Action 객체 생성
- Aciton 객체가 Dispatch 함수 인자로 전달
- Dispatch 함수는 Action 객체를 Reducer 함수로 전달
- Reducer 함수는 Action 객체의 값을 확인 후, 값에 따라 전역 상태 저장소인 Store의 상태를 변경
- 상태가 변경 시, React는 화면 리렌더링
Store🗄
- 상태가 관리되는 유일한 저장소의 역할로 redux 앱의 state가 저장되어 있는 공간
import { createStore } from 'redux';
const store = createStore(Reducer함수);
Reducer🗂
- Dispatch에게서 전달받은 Action 객체의
type
에 따라 상태를 변경시키는 함수
❗️주의❗️
Reducer는 입력에 따라 출력이 이루어지는 순수함수여야 함
state
, 두 번째 인자에는 action
객체를 전달combineReducer
를 사용해 하나의 Reducer로 병합 가능combineReducer
를 통해 하나로 병합하는 과정은 여러 컴포넌트가 하나의 큰 컴포넌트의 구성요소과 되는 과정과 비슷함 const Reducer함수 = (state = 초기상태, action) => {
// Action 객체의 type 값에 따라 분기하는 switch 조건문
switch (action.type) {
case 경우1:
return 경우1일 때, 변화하는 상태
case 경우2:
return 경우2일 때, 변화하는 상태
// 해당 되는 경우가 없는 case에는 기존 상태를 그대로 리턴
default:
return state;
}
}
Action🤸🏻
- 경우에 따라 수행할 각각의 액션을 정해놓은 객체
// payload가 필요 없는 경우
{ type: 'CASE_NO_PAYLOAD' }
// payload가 필요한 경우
{ type: 'CASE', payload: 5 }
type
은 Action 객체가 수행할 동작을 명시하기 때문에 필수로 지정해줄 것
type
작성 시, 대문자와 snake case(공백을 밑줄로 대체하는 규칙)로 작성payload
는 필요에 따라 작성
보통 Action을 직접 작성하기보다 Action 객체를 생성하는 함수를 만들어서 사용하는 데 이러한 함수를 액션 생성자(Action Creator)라고 함
// payload가 필요 없는 경우
const caseNoPayload = () => {
return {
type: 'CASE_NO_PAYLOAD'
}
}
// payload가 필요한 경우
const case = (인자) => {
return {
type: 'CASE',
payload: 인자
}
}
Dispatch📤
- Reducer로 Action을 전달해주는 함수
// Action 객체를 직접 작성하는 경우
dispatch( { type: 'CASE_NO_PAYLOAD' } );
dispatch( { type: 'CASE', payload: 5 } );
// 액션 생성자(Action Creator)를 사용하는 경우
dispatch( caseNoPayload() );
dispatch( case(5) )
Action, Dispatch, Reducer, Store의 개념을 연결시키기 위해 이용하는 함수
useDispatch()
- Dispatch 함수를 반환하는 메서드
- Dispatch 함수는 Action 객체를 Reducer로 전달해주는 역할을 수행
import { useDispatch } from 'react-redux'
const dispatch = useDispatch()
dispatch( caseNoPayload() )
dispatch( case(5) )
컴포넌트와 state를 연결하여 Redux의 state에 접근할 있게 해주는 메서드
형식
// Redux Hooks 메서드는 'redux'가 아니라 'react-redux'에서 불러옴
import { useSelector } from 'react-redux'
const state = useSelector(state => state)
1. Single source of truth🗄
2. State is read-only🤸🏻
3. Changes are made with pure functions🗂
참고
Redux
<오늘의 일기>
이번 유닛은 상태 관리를 복습해보고 상태 관리를 도와주는 라이브러리인 Redux에 대해 공부했다. 처음 Redux를 접했을 때 사실 상태라는 개념 자체도 어려웠었는데 Redux를 봤을 때 '이걸 도대체 어떻게 적용하지?' 라는 걱정에 사로잡혔었다. 지금도 역시 Redux를 자유자재로 사용할 수 있는 수준은 아니지만 그래도 실습이나 과제를 통해 Redux의 필요성이나 데이터 흐름에 대해서는 확실하게 알게 되었다.
이번 페어분은 페어와 소통을 원활하게 하기 위해 노력하시는 분 같았다. 사실 페어 활동할 때 나에게는 그런 부분들이 가장 어렵게 느껴졌는데 이번 페어 활동을 하면서 앞으로는 페어 활동을 할 때 너무 기다리는 것보다 다가가기 위해 노력해봐야겠다는 생각이 많이 들었다.
이번 유닛은 특히 부트캠프에 들어오면 다짐한 목표 중에 하나가 협업 능력을 키우는 것이었던 만큼 부트캠프의 남은 기간 동안은 지금의 나보다는 조금 더 적극적인 자세를 가져야겠다고 다짐하게 된 유닛이었다.