프로그래밍/React

Redux 강의 정리

matte 2021. 8. 9. 11:03

Redux 1

- React 에서 component communication 을 배웠음. 데이터를 변경시키려면 props 를 전달, 전달하는 구조

- 문제점이 중간에 있는 component 들은 전달만 하는 component 로 사용된다는 것 

이런 문제의 해결을 위해 Context API 를 사용할 수 있음

 

Context 를 사용할 경우, Context 가 가진 전역 data 를 잘 활용하는 게 중요함. Context 에 주어지는 전역 data 를 어떻게 효과적으로 관리할 것인지에 대한 라이브러리 = Redux

 

Redux 가 사용하는 방식은? 파란공 자리에 STORE

- STORE 안에 있는 상태를 보라색 공이 변경할 수 있고, STORE 의 상태를 가진 component 들이 STORE 의 상태가 변경되면 자동으로 다시 render 됨

- 보라색 공이 STORE 안의 상태를 변경하고, STORE 안의 상태를 받아서 표현하는 애들이 있는 것

 

어떻게 STORE 의 상태를 변경하고, 어떻게 STORE 의 상태를 받아서 render 하는 것인가? action, Reducers 부분에서 설명할 것임

 

*중요한 건 단일 스토어. 스토어는 1개 뿐임

- 단일 STORE 를 만드는 법, 그리고 파란선과 보라색 공이 어떻게 연결되는지가 중요하겠죠

- connect 라는 HOC 함수를 통해 컴포넌트에 연결하거나, Hook 들을 이용해 connect 역할을 대체할 수도 있음

 

Action 

Action 은 그냥 객체. 그냥 일반 Object. 2개 형태의 Action 이 있음.

① type 이라는 property 만 가진 Action, ② type 이 있고, 그 외에 payload, 즉 다른 여러 property 가 있는 Action

type 만 필수 property 이고, type 은 보통 문자열임

 

이렇게 만들어진 Action 이 Store 에 전달되면 Store 에 있는 상태를 변경하는 용도로 사용됨

Store 의 상태를 변경할 때, 특별한 인자값이 없는 경우 type 만 있는 Action 이 전달되고,

Action 을 전달하면서 값을 이용해서 상태를 변경해야 한다면, type 을 제외하고 다른 parameter 도 들어가게 됨

 

Action 객체를 만들 때는 Literal 로 사용하는 게 아니라, Action 을 생성하는 함수를 만들어서 사용하게 됨

이런 함수를 Action 생성자라고 하고, return 은 Action 임

return 은 앞에서 배운 Action 의 형태를 띄고 있어야 하고, Action 종류별로 같은 갯수의 Action 생성함수가 만들어짐

 

Redux 에서 Action 은 어떤 일을 하나?

만들어낸 Action 객체를 Redux Store 에 보냄. 보내는 것은 Action, 도착지는 Store. Redux Store 는 Action 객체를 받으면, 원래 가지고 있던 상태값이 변경됨. 이에 따라 상태를 이용하고 있는 component 가 변경됨. Component 와 Redux store 는 연결되어 있으니까, Action 이 component 를 변경하는 요인이 됨

 

Action 준비? 2단계

- Action type 을 정의하고, 상수로 빼둔다. type 이 문자열이니까 실수 방지를 위해

- Action 생성함수를 만든다. Action type 은 위에서 정의한 type 상수로 부터 가져와서 사용한다

 

Reducer

Action 을 주면 그 Action 이 적용돼서 달라진/안 달라진 결과를 만들어주는 "함수"

함수인데, PURE Function. 항상 같은 input 을 받아서 같은 output 을 내는 함수. Reducer 안에 시간에 따라 다른 결과를 낸다든지 하는 형태의 코드가 들어가면 안됨

 

Immutable 해야 함. Original State 와 New State 가 별도의 객체로 만들어져야 한다, 서로 다른 참조를 가져야 한다 (Redux 가 state 의 변경을 인지하는 방식)

 

Reducer 란 이름이고, 1번째 인자는 previousState (현재 State), 2번째 인자는 Action 객체

previousState, Action 객체를 이용해서 새로운 State 객체를 만들어 냄. Action 을 받아서 State 를 리턴하는 구조

 

Reducer 를 작성할 때는 State 의 모습에 대해 구상해 봐야 함

최초에 Reducer 가 어디서 실행됐을 때는, 현재 previousState 가 뭔지 설정해줘야 함. 아무것도 지정이 안 돼 있다면, 가장 최초의 상태일 것임. 그래서 초기값을 지정해줄 수 있음

 

아무 대응도 하지 않는 경우, 똑같은 State 를 리턴하면, Immutable 하지 않음. previousState.push(); 같은 메소드는 객체는 변경하지만, 객체의 참조는 변경하지 않으므로 사용하면 안됨

const initialState = 초기값 상태를 먼저 정의해주고, 미리 지정해주면, 가능

 

Reducer 를 Pure 하게 만들고, Immutable 하게 처리되게 만들 작성이 끝남 

 

Reducers in Redux

Redux 라이브러리를 이용해 createStore 함수를 활용하자. Redux 에서 가져와서 사용하고, Store 를 만드는 함수

 

Store 를 만들면, Store 안에 있는 상태와, 상태를 변경하는 Action 을 보내서, 각종 State 관리를 할 수 있음

createStore 함수의 인자는 3개

① Reducer 함수, ② preloadedState (initialState 를 넣거나 Reducer 에서 처리), ③ enhancer

 

reducer 만 넣어서 createStore 하고, Store 에 어떤 게 들어있나 console 에 찍어보면

dispatch, getState, replaceReducer, subscribe 4개 정도의 함수가 들어있음

 

store.getState 하면 현재의 상태가 출력됨. 최초에 [] 나오는 것은 preloadedState 를 설정하지 않았지만, Reducer 에서 initialState 를 지정했으므로 그게 출력되는 것

 

Store 의 상태를 이제 변화시킬 건데, Action 을 인자로 가지는 함수가 Dispatch. React hook 에서 useReducer Hook 을 사용할 때도 사용한 함수, dispatch 를 사용해서 action 을 던지면 state 가 변경되었음

 

store.dispatch 하고 Action 객체를 넣으면 되는데, Literal 로 작성({ type: xx }) 이 아니라, Action 생성함수를 이용함

넘기는 인자를 "todo" 로 보내면, Action 이 생성돼서, Dispatch 가 날아가고, Store 에 도착하고, State 를 변경함

다음 줄에서 store.getState() 하면 결과가 바뀌어 있음

 

이 코드를 Store 의 Subscribe 함수를 활용하겠음 (= 구독하다)

Store 에 변경사항이 생기는 것을 구독하는 것. 함수를 넣으면, Store 의 상태가 변경될 때마다 구독한 함수가 호출됨

getState 출력을 넣으면, 구독 시작했으니까 dispatch 하면 subscribe 이 실행되면서 결과가 나옴

 

구독해 놓으면 dispatch 가 일어날 때마다 subscribe 내부에 인자로 넣어준 함수가 계속 호출됨

subscribe 의 리턴함수는 unsubscribe 함수임. 어떤 시점 후에 unsubscribe 를 호출하면 그 후에는 똑같이 dispatch 해도 구독함수 호출이 안됨. 실제 Store 에는 변경이 진행돼 있음

 

getState : 현재 Store 의 state 를 가져오는 함수

dispatch : Action 을 인자로 넣어서 Store 상태를 변경시키는 함수

subscribe : Store 에 변경이 생겼을 때 특정 함수를 실행하도록 하는 함수, 결과물이 unsubscribe 역할을 하는 함수. unsubscribe 호출하면 구독함수가 제거됨

 

replaceRudcer : 원래 가지고 있던 Reducer 를 다른 Reducer 로 바꾸는 것인데, 실무에서는 잘 안쓰임

 

combineReducers

Store 가 커질 때, Store 안에 있는 State 가 복잡해질 때 어떻게 처리하는 지를 배워보겠음

기존 Reducers 에 initialState 를 ["코딩", "점심 먹기"] 에서 [{ text: '코딩', done: false}, { text: '점심 먹기', done: false}] 로 바꾸면서 done: false -> true 로 complete 처리해주는 Action 을 추가함

추가로 Store 안의 상태 중에 현재 View 에서 어떤 걸 보여줄지를 필터링하는 property 를 하나 더 추가하면 initialState 가 객체가 됨 {todos: [{ text: '코딩', done: false}, { text: '점심 먹기', done: false}], filter: 'ALL'}

 

Reducers 안에 있는 로직이 App state 가 커질수록 복잡해짐

Redux 는 단일 Store 임. Reducer 안에 있는 내용을 쪼개는 능력이 필요함

Action 종류에 따라, ① Todo 에만 영향 O Filter 에는 영향 X ② Todo 에는 영향 X Filter 에만 영향 O

이렇게 별개의 Reducer 로 작성해서 하나로 합치는 식으로 로직/파일을 쪼개는데, 이를 combineReducer 로 구현가능

 

*패스트 캠퍼스 프론트엔드 강의를 듣고 정리함