Redux 난 정말 처음인걸..

남예지·2023년 8월 30일
0

Redux

목록 보기
1/5
post-thumbnail

개발자는 새로운걸 잘 받아들일 줄 알아야 한다지...난 정말 그런거 못해..
그래도 성장하려면 이런 머리 깨지는 것도 해야지!(머리아팡...)
리덕스 뽀개자!


#리덕스란?
크로스 컴포넌트 또는 앱 와이드 상태를 위한 상태 관리 시스템
데이터를 관리하도록 도와준다.
// 로컬 상태 아닌 상태에서 데이터 관리를 도와준다는 말.

상태는 3가지로 구분할 수 있다.
1. Local State 로컬 상태
: 데이터가 변경되어서 하나의 컴포넌트에 속하는 UI에 영향을 미치는 상태
: 토글 버튼 등 useState()/useReducer()
2. Cross-Component State 크로스 컴포넌트 상태
: 다수의 컴포넌트에 영향을 미치는 상태
: 모달 컴포넌트가 다수의 컴포넌트에 영향을 미치거나 하는 등 그럴때는 prop chains/ prop drilling을 사용
3. App-Wide State 앱 와이드 상태
: 애플리케이션의 모든 컴포넌트에 영향을 미치는 상태
: 사용자 인증 등 prop chains/ prop drilling.

왜 리덕스가 필요할까

  • 리액트 컨텍스트의 대안
    구축 상황에 따라 리액트 컨텍스트 사용이 단점이 아닐 수 있고, 이때는 굳이 리덕스를 사용하지 않아도 된다.
    리액트 컨텍스트의 단점은
  1. 설정이 복잡해질 수 있다
    : 소형과 중형 프로젝트에서는 문제가 되지 않지만 대형 프로젝트를 구현한다면 수많은 상태를 관리하기 위해 심하게 중첩된 JSX 코드가 나올 수 있다.
  2. 성능이 문제가 될 수 있다.
    : 고빈도 변경에는 적합하지 않다. 또한 유동적인 상태 확산을 대체할 수 없다. 그에 반해 리덕스는 유동적인 상태 관리 라이브러리이다.

리덕스의 작동방식

리덕스는 애플리케이션에 있는 하나의 중앙 데이터 저장소이다.
여기서 데이터는 상태를 가리킨다.
우리는 저장소를 딱 한개만 가지고 전체 애플리케이션에 모든 상태를 다 저장한다.
이러면 복잡할 것 같지만 그렇지 않다.
우리는 이 중앙 데이터 저장소에 데이터를 저장하고 컴포넌트 안에서 사용할 수 있다.
state가 변경되면 리덕스가 알아채고 업데이트하길 기대한다.

간단한 리덕스 동작 흐름
중앙 데이터 저장소는 컴포넌트에 Subscription(구독)을 설정한다. -> 데이터가 변경될 때마다 저장소가 컴포넌트에 알려준다. -> 컴포넌트는 필요한 데이터(인증, 인가, 등)를 받게 된다. -> 그 데이터를 사용한다.

아래 더 자세히 알아보자.

시작하기

  • npm init -y : 기본 질문에 모두 yes라고 대답한다.
  • npm install redux
  • import redux = require('redux')

리덕스의 중심 개념은 저장소이다.

저장소 만들기

  • redux.createStore()를 호출한다.
    리덕스 라이브러리에서 온 이 메소드는 저장소를 생성한다.
    저장소의 역할은 데이터를 관리하는 것이다.

리듀서 함수 만들기

  • const counterReducer = (state, action) => {return {} }
    - 리듀서 함수는 항상 2개의 입력(파라미터)를 받는다.
    - 항상 새로운 상태 객체를 리턴해야만 한다.
    - 리듀서 함수에 의해 데이터가 결정된다.
    - 리듀서 함수는 순수한 함수로 같은 값을 넣으면 어떠한 부수적인 효과 없이 동일한 리턴을 주어야 한다.
    - 리듀서 함수는 액션이 도착할 때마다 새로운 상태 스냅샷을 뱉어내야 한다.

    여기서 스냅샷이 뭘까 ?
    마치 사진 찍듯이 특정 시점에 스토리지의 파일 시스템을 포착해 보관하는 기술을 말한다.
    리듀서 함수에서는 액션이 도착하면 해당하는 리턴값을 뱉는다.

기본적인 카운터 리듀서 함수는 아래와 같다.

const redux = require("redux")

const counterReducer = (state, action) => {
	return {
    	counter: state.counter + 1 // 1을 더한 새로운 객체를 리턴한다.
    }
}

const store = redux.createStore(counterReducer); // 저장소를 변경하는 리듀서 함수를 넣어준다.  

이제 이 저장소를 구독할 함수와 발송할 액션도 필요하다.

구독부터 함수를 만들자. 파라미터를 받지 않지만 저장소에 getState() 메서드를 호출할 수 있고, 이는 createStore()에서 사용할 수 있다.
getState()는 업데이트 된 후 최신 상태 스냅샷을 제공한다.
구독함수는 상태가 변경될 때마다 트리거 된다.

이를 실행할 메서드도 필요하다. 이때는 store에 subscribe 메서드를 호출한다.

const counterSubscriber = () => {   // 구독함수 만들고 아래 최신상태 스냅샷을 제공하는 getState() 를 넣고 콘솔로 출력한다. 
	const latestState = store.getState();
    console.log(latestState);
}

store.subscribe(counterSubscriber); // 구독함수를 실행한다. 

리덕스는 데이터와 저장소가 변경될 때마다 이를 실행하게 된다.
즉 리덕스가 실행시켜 줄테니 우리는 함수를 호출하지 말고 그냥 넣어주자.


아무튼 액션을 넣지 않고 이대로 실행을(터미널에 node 파일이름) 한 번 해보면 state가 없어서 오류가 난다.
state에는 초기값이 없어 설정해주어야 한다.

const counterReducer = (state = {counter: 0}, action) => { // state에 초기값 넣어주기

이렇게 하면 실행되지만, 액션이 없어 출력값이 없다.

이제 액션을 만들고 디스패치 해보자.
저장소에 액션을 발송하는 dispatch()메서드를 호출하면 된다.

store.dispatch({ type : "increment" })

그러면 이제 따로 콘솔을 쓰지 않고도 counterSubscriber 구독 함수 안에 있는 콘솔이 실행되어 {counter: 2}을 출력한다.(아까 액션 만들기 전에 한 번 실행되어 +1인 상태로 한 번 더 불러왔기 때문에 2 이다.)

여기까지가 리덕스의 핵심적인 작동 방식이다.

정리하자면.
1. redux.createStore()로 저장소를 만들고 리듀서 함수를 만든다음 연결한다.
2. 구독 함수도 만들어서 getState() 해준다.
3. 액션 dispatch() 해준다.


현재는 액션이 아무런 효과가 없는데 이 부분을 더 자세히 알아보자.

액션은 리듀서 함수 안에서 다른 동작을 위해 사용한다.
예시로 만약 액션 type이 'increment'라면 현재 상태에 1을 더한 값을 리턴하고, 아니라면 전에 상태를 리턴한다.

const counterReducer = (state, action) => {
  if(action.type === 'increment'){ // 만약 이 액션이 디스패치 되었다면 리턴값을 출력해줘.
      return {
          counter: state.counter + 1
      }
  }
  return state; // 아니라면 초기 스테이트를 출력해줘
}

액션을 추가해보자.

store.dispatch({ type : "decrement" })

그리고 리듀서 함수에도 적절한 식을 넣으면 된다.

const counterReducer = (state, action) => {
  if(action.type === 'increment'){
      return {
          counter: state.counter + 1
      }
  }
  
  if(action.type === "decrement"){
  	return {
    	counter: state.counter - 1
    }
  }
  return state;
}

이렇게 하고 실행시키면 counterSubscriber 구독 함수에 있는 콘솔로 { counter: 1 }{ counter: 0 } 이 나온다.

dispatch 된 순서대로 나온 것이다.

여기까지는 바닐라 js 에서 사용한 리덕스 사용법이었다. 리액트에서는 사용법이 좀 다른가보다. 다음 글에서 알아보자.

profile
총총

0개의 댓글