반응형
250x250
Notice
Recent Posts
Recent Comments
Link
관리 메뉴

짧은코딩

Redux를 사용하는 이유 및 기본 본문

인프런, 유데미/Redux

Redux를 사용하는 이유 및 기본

5_hyun 2022. 9. 6. 22:20

Redux

서버에서 데이터 수정을 하면 프론트에서 값이 바뀌고, 프론트에서 데이터 수정을 하면 서버에서 값이 바뀌는 양방향 코딩을 하게되면 문제가 발생할 수 있다. 코드가 좀 복잡해지면 값이 이상하게 꼬일 수 있다. 따라서 Redux를 활용해서 데이터 관리를 쉽게 해줄 수 있다. Redux는 꼭 리액트에서만 사용하는 것은 아니다. 그치만 리액트에서 Redux를 많이 사용한다.

 

-예시

리액트에서 A, B, C 컴포넌트가 있고 A가 제일 위 부모 태그, C가 제일 아래 자식 태그라 하면 state값을 다 따로 관리 해주게된다. 이 state를 다 같이 관리하기 위해서 Redux에 state를 저장하고 쉽게 관리 할 수 있다. 즉 컴포넌트 간의 state를 관리 할 때 사용하면 된다. 만약 컴포넌트 B에서만 사용하는 state는 굳이 리덕스로 관리 할 필요가 없다.

=> 서로 간에 관계가 생기면 Redux를 사용하면 된다.

Redux의 원리

리덕스는 단방향이다.

 

원리

1. store에 data가 객체 형식으로 저장되어있다.

2. action에 store의 data를 어떻게 변화 시킬건지 만들어 놓는다.

3. dispatch가 action을 실행하면 store의 data가 바뀐다.

4. dispatch와 Reducer 사이에 middleware가 있다.

5. 3번을 하면 Reducer에서 불변성을 지키기 위해 새로운 객체를 만들어내고 store의 data를 갈아끼워준다.

store -> action -> dispatch -> store... 이런식으로 진행되어서 단방향이다.

 

-장점

1.  dispatch도 함수인데 dispath(action) 이런식으로 바꾸는 거라서 기록이 다 남는다. 누가 뭐를 바꿨는지 기록에 다 남기 때문에 에러 찾기가 편하다.

2. 기록이 있기 때문에 타임머신 처럼 그 시점으로 돌아갈 수 있다.

3. 에러가 딱 보이고 결국 개발자 잘못인 것을 알 수 있다.

 

-단점

1. action을 미리 만들어 놔야 한다.

2. 타임머신 기능을 쓰려면 불변성을 지켜야해서 객체를 항상 만들어 줘야 한다.

예시 코드

-store 만들기

const { createStore } = require("redux");

const reducer = () => {};
const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

이렇게 store에 state를 저장할 수 있다. initialState로 해서 좀 더 보기 쉽게 만들어줬다.

 

-직관적인 코드(안좋음)

const { createStore } = require("redux");

const reducer = () => {};
const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

//action
const changeCompA = {
  //  type이 action의 이름
  type: "CHANGE_COMP_A",
  data: "b",
};

const changeCompB = {
  //  type이 action의 이름
  type: "CHANGE_COMP_B",
  data: "c",
};

action을 이렇게 만들 수 있는데 compA를 b로도 만들고 싶고 c로도 만들고 싶으면 이렇게 2개를 만들어야 한다. 이런것을 직관적인 코드라 한다. 하지만 이렇게 이름을 자주 지어야하는 상황이 오는 코드는 좋지 않은 코드이다.

 

-추상적인 코드(좋음)

const { createStore } = require("redux");

const reducer = () => {};
const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

const changeCompA = (data) => {
  // action
  return {
    type: "CHANGE_COMP_A",
    data,
  };
};

이런식으로 추상적으로 해야하며 return해주는 객체가 action이다.

 

-불변성

state가 어떻게 바꼈는지 알기 위해서는 새로운 객체를 계속 찍어내면서 비교해줘야한다. 이런 역할을 reducer에서 해준다.

const { createStore } = require("redux");

const reducer = (prevState, action) => {
  switch (action.type) {
    case "CHANGE_COMP_A":
      return {
        compA: action.data,
        compB: 12,
        compC: null,
      };
  }
};

const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

//action
const changeCompA = (data) => {
  // action
  return {
    type: "CHANGE_COMP_A",
    data,
  };
};

store.dispatch(changeCompA("b"));

console.log(store.getState());

결국 Reducer는 새로운 state를 만들어 준다.

 

-중복을 제거하면서 바꾸고 싶은거 바꾸기

const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const nextState = {
  ...initialState,
  compA: action.data,
};

이렇게 얕은 복사를 이용해서 바꾸면 된다.

 

const { createStore } = require("redux");

const reducer = (prevState, action) => {
  switch (action.type) {
    case "CHANGE_COMP_A":
      return {
        ...prevState,
        compA: action.data,
      };
  }
};

const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const nextState = {
  ...initialState,
  compA: action.data,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

const changeCompA = (data) => {
  // action
  return {
    type: "CHANGE_COMP_A",
    data,
  };
};

store.dispatch(changeCompA("b"));

console.log(store.getState());

따라서 reducer에서 첫번째 인자를 활용해 얕은 복사를 해준다.

 

-코드에 오타 난 경우

const { createStore } = require("redux");

const reducer = (prevState, action) => {
  switch (action.type) {
    case "CHANGE_COMP_A":
      return {
        ...prevState,
        compA: action.data,
      };
    default:
      return prevState;
  }
};

const initialState = {
  compA: "a",
  compB: 12,
  compC: null,
};

const store = createStore(reducer, initialState);

console.log(store.getState());

const changeCompA = (data) => {
  // action
  return {
    type: "CHANGE_COMP_A",
    data,
  };
};

store.dispatch(changeCompA("b"));

console.log(store.getState());

만약 action 이름을 잘못 쓴 경우 reducer의 switch 문에 default를 달아서 해결하면 된다.

하지만 이렇게 하면 단점은 action이 너무 길어진다는 점이 있다.

실질적 예시

const { createStore } = require("redux");

const reducer = (prevState, action) => {
  switch (action.type) {
    case "LOG_IN":
      return {
        ...prevState,
        user: action.data,
      };
    case "LOG_OUT":
      return {
        ...prevState,
        user: null,
      };
    case "ADD_POST":
      return {
        ...prevState,
        posts: [...prevState.posts, action.data],
      };
    default:
      return prevState;
  }
};

const initialState = {
  user: null,
  posts: [],
};

const store = createStore(reducer, initialState);

console.log(store.getState());

const logIn = (data) => {
  // action
  return {
    type: "LOG_IN",
    data,
  };
};

const logOut = () => {
  return {
    type: "LOG_OUT",
  };
};

const addPost = (data) => {
  return {
    type: "ADD_POST",
    data,
  };
};

// 위 부분까지는 미리 만들어 놔야하는 코드
//___________________________________
// 아래 코드는 리액트에서 실행하는 코드, 즉 dispatch 부분은 리액트에서

store.dispatch(
  logIn({
    id: 1,
    name: "zerocho",
    admin: true,
  })
);

store.dispatch(
  addPost({
    userId: 1,
    id: 1,
    content: "안녕하세요, 리덕스",
  })
);

store.dispatch(
  addPost({
    userId: 2,
    id: 2,
    content: "안녕하세요, 리덕스2",
  })
);

console.log(store.getState());

aciton과 reducer는 미리 만들어 놔야한다. 그리고 dispatch 부분은 리액트에서 사용하면 된다.

728x90
반응형

'인프런, 유데미 > Redux' 카테고리의 다른 글

immer(코드를 줄일 수 있음)  (0) 2022.11.18
리액트와 리덕스 연결하기, redux devtools  (0) 2022.11.18
redux-thunk  (0) 2022.11.18
리덕스 미들웨어  (0) 2022.09.13
리덕스 내부 구조 잡기  (0) 2022.09.10
Comments