오티스의개발일기

[REACT NATIVE] REDUX 적용하기 + 폴더 구조 -git첨부- 본문

개발/react-native

[REACT NATIVE] REDUX 적용하기 + 폴더 구조 -git첨부-

안되면 될때까지.. 2022. 12. 19. 15:40
728x90


다음글 >

2022.12.20 - [개발/react-native] - [REACT NATIVE] REDUX 미들웨어 그리고 클라이언트단부터의 로직의 흐름

 

[REACT NATIVE] REDUX 미들웨어 그리고 클라이언트단부터의 로직의 흐름

저번글에서 react native에서 redux를 추가하는방법을 배워보았다. redux-saga를 공부를 하고있는데 아무리봐도 도저히 이해가 안가는부분이 있었다. 일단은 미들웨어에서 어떻게 처리하는지도 모르겠

otis.tistory.com



< 이전글

2022.12.18 - [개발/react-native] - [REDUX] 에대해서

 

[REDUX] 에대해서

다음글 > 2022.12.19 - [개발/react-native] - [REACT NATIVE] REDUX 적용하기 + 폴더 구조 + 깃허브 참조 < 이전글 2022.12.18 - [개발/react-native] - [REACT NATIVE] 프로젝트 시작하기 글을 시작하기에 앞서 본인은 vue.js

otis.tistory.com


오늘은 리엑트 네이티브에 리덕스를 적용시켜보겠다.

 

리덕스에 대해 공부하면서

리덕스 툴킷(redux toolkit) 과 사가(redux saga)

라는것을 알게되었고

 

그것들이 편하다는걸 알고있었지만

일단은 기초적인것 부터해봐야 추후에 툴킷과 사가를 더욱 쉽게 이해할수있을거같아

 

오늘은 기본적인것만 해보려고한다.

 

 

이블로그를 시작하는 이유중한개는 새로운 언어를 시작부터 제대로 배워보기 위해 시작하였다.

또한 프로잭트를 제작하는것을 목표로하고 스택 하나하나 빌드업시키려고 계획중에있다.

 

그렇기에 나에게는 폴더 구조나 데이터의 흐름이 중요하고 그것들부터 찾는것부터 시작하였다

 

하지만 생각처럼 검색하는 정보마다 각기다르기에 어느 하나를 고를수가 없었다.

그래서 필요한 몇가지로 갖춰봤다.

 

1. UI

2. axios 

3. 상태관리

 

이 3가지에대해 공부하다보면 어느정도 폴더구조라든지 아키텍처를 볼수있을것이라 기대하며

공부를 하며 이글을 쓰고있는것이다.

 

나처럼 비전공에 독학하려는사람들 모두 화이팅이며 

내글이 조금이라도 도움이되었으면 한다.

 

 

 

 

1. 폴더 구조

 

 

src안에 

-action

-reducer

-stores

를 넣어놨다.

 

기본적인 기능과 역할은

src

-action [api 혹은 데이터를 다루는 장소라 보면된다 axios 같은것들]

-reducer [데이터를 실질적으로 읽거나 변경하는 곳이다.]

-stores [redux를 사용하기위한 설정파일 그리고 생성자정도로 생각하면되겠다.]

 

 

 

1. [ store.js ] 스토어

//src/stores/store.js

import { createStore, applyMiddleware } from "redux";
import {composeWithDevTools} from 'redux-devtools-extension'
import thunk from 'redux-thunk'
import rootReducer from "../reducer/rootReducer"; // 리듀서 모음집이라 생각하면된다 
                                                 // 리듀서를 하나하나 만들어서 이곳에 생성해도 되지만 가독성을 위해 하나의 리듀서안에 여러가지를 넣고 사용한다.

// 위에서 만든 reducer를 스토어 만들때 넣어줍니다
let store = createStore(
    rootReducer,
    composeWithDevTools(applyMiddleware(thunk)) // 미들웨어 
);

export default store;

 

스토어를 만들었고 이제 rootReduer를 만들어주겠다.

위 주석에있는 리듀서 모음집을 만드는것이다.

 

2. [ rootReducer.js ] root 리듀서  [모음집]

 

// src/reducer/rootReducer.js

// 여러 reducer를 사용하는 경우 reducer를 하나로 묶어주는 메소드
// store에 저장되는 리듀서는 오직 1개이지만 그 1개에 여러개의 리듀서가 들어갈수있음

import { combineReducers } from "redux";
import reducer from "./reducer"; // 만든 리듀서
//import 또다른 리듀서 from '경로'
//import 또다른 리듀서 from '경로'
//import 또다른 리듀서 from '경로'

const rootReducer = combineReducers({
  reducer : reducer,
  //또다른 리듀서 : 또다른 리듀서,
  //또다른 리듀서 : 또다른 리듀서,
  //또다른 리듀서 : 또다른 리듀서,
});

export default rootReducer;

 

기본적인 설명은 주석에 다 있다.

 

보이는것처럼 이제 저곳에 화면마다 혹은 어떤 비지스마다 필요한 리듀서(reducer) 를생성하고 

루트 리듀서에 등록을 시켜 사용하게될것이다.

 

이것은 단순 가독성을 위한 구조이니 참고바란다.

 

이제 실질적으로 사용한 reducer를 만들러 가보자

 

 

 

3. [ reducer.js ] 리듀서 

 

// src/reducer/reducer.js

import {INCRESECOUNT, DECRESECOUNT, SET_COUNT} from '../action/countAction' // 엑션 타입 선언

let initialState = {
  count: 0,
}

const reducer = (state = initialState, action) => {
  let  {type, payload} = action
  switch (type) {
    case INCRESECOUNT: // 1씩 증가
      return {
        ...state,
        count: state.count + 1,
      };

    case DECRESECOUNT: // 1씩 감소
      return {
        ...state,
        count: state.count - 1
      };
      
      case SET_COUNT: // 100 증가
        return {
          ...state,
          count: payload //payload 에 100이 들어가있음 payload = action.payload
        };

    default:
      return state;
  }
};

export default reducer;

 

상단에 보면 

import {INCRESECOUNT, DECRESECOUNT, SET_COUNT} from '../action/countAction' // 엑션 타입 선언

이것들은 타입일 미리 선언해놓는것이라 보면된다.

이것또한 일일이 손으로 적어서 보낼수있지만 

가독성과 안정성을 위해 사용하는듯하다.

 

 

조금있다 countAction.js  파일을 보면 좀더 이해가 편할것이다.

 

 

이제 action파일을 작성해보자

 

3. [ countAction.js ] 액션

//src/actions/countAction.js

export const INCRESECOUNT = 'increseCount'; // 엑션 타입 선언 자바로 따지면 컨트롤러 매핑한다고 생각하면 쉽다.
export const DECRESECOUNT = 'decreseCount';
export const SET_COUNT = 'setCount';

export const setCount = (count) => dispatch => {
    console.log(count); // 받은 매게 변수   결과 = 101 // 매게변수가 들어오는지 확인하기위해 100이 아닌 101을 넣었음
    dispatch({
        type: SET_COUNT,
        payload: 100 // 실질적으로 여기에 count가 들어가는게 맞음
    });
}


export const increseCount = (count) => dispatch => {
    console.log(count);
    dispatch({
        type: INCRESECOUNT,
    });
}

export const decreseCount = (count) => dispatch => {
    console.log(count);
    dispatch({
        type: DECRESECOUNT,
    });
}

 

 

export const INCRESECOUNT = 'increseCount'; // 엑션 타입 선언 자바로 따지면 컨트롤러 매핑한다고 생각하면 쉽다.

export const DECRESECOUNT = 'decreseCount';
export const SET_COUNT = 'setCount';
 
상단에 이것들을 아까 reducer.js에서 사용했던것이다.
 
서로 통일하게 한가지의 타입을 공유하여 실수가 일어나지않도록 하는것같다.
 
그리고 밑에있는 함수들은 view단에서 쓰일 예정이다.
 

이제 screen을 만들어보자.

 
 
 
 

3. [ CountScreen.js ]  스크린 (뷰단)

 

//src/screens/CountScreen.js

import { useDispatch, useSelector } from 'react-redux'; // userDispatch = 데이터 변경시 사용 // useSelector = 데이터 가져올때 사용
import {setCount, increseCount, decreseCount} from '../action/countAction' // axios 나 어떤 비지니스 로직을 처리할때 사용
const Counter = () => {
  const dispatch = useDispatch(); // dispatch를 편하게 변수에 담아 사용한다.
  const count = useSelector(state => state.reducer.count); // 데이터 가져오기
  const handleIncrement = () => {  
    dispatch(increseCount()); // dispatch안에 action에서 만든 함수 넣고 실행   
                              // 이렇게 함수를 넣고 실행하면 
                              //action (변경할 데이터)-> dispatch(변경) -> getState(변경된 데이터 실행) -> 상단에있는 useSeletor 실행이되어 변경된 값이 보인다.
  }

  const handleDecrement = () => {  
    dispatch(decreseCount());
  }

  const updateCount = () => { 
    dispatch(setCount(101));
  }

  return (
    <div>
      <center>
        <h1>Redux</h1>
        <h1>{count}</h1>
        <button className="btn btn-primary" onClick={handleIncrement}>Increment</button>
        <button className="btn btn-warning" onClick={handleDecrement}>decrement</button>
        <button className="btn btn-warning" onClick={updateCount}>100증가</button>
      </center>
    </div>
  );
}

export default Counter;

그전에 actions에서 만든 함수를 여기에 등록후 사용한것이다.

 

 

기본적인 흐름은 이렇다

 

1.사용자가 버튼을 클릭한다  [CountScreen]

 <button className="btn btn-warning" onClick={updateCount}>100증가</button>
const updateCount = () => {
    dispatch(setCount(101));
  }
 
 
 

2. countAction.js 안에있는 함수가 실행된다.

export const SET_COUNT = 'setCount';
 
 
 
 

3. 함수가 실행되면서 dispatch가 동작한다.

export const setCount = (count) => dispatch => {
    console.log(count); // 받은 매게 변수   결과 = 101 // 매게변수가 들어오는지 확인하기위해 100이 아닌 101을 넣었음
    dispatch({
        type: SET_COUNT,
        payload: 100 // 실질적으로 여기에 count가 들어가는게 맞음
    });
}
 
 
 
 

4. reducer.js 안에 에 있는 reducer가 실행된다.

import {INCRESECOUNT, DECRESECOUNT, SET_COUNT  <<<} from '../action/countAction' // 엑션 타입 선언

let initialState = {
  count: 0,
}
const reducer = (state = initialState, action) => {
  let  {type, payload} = action
  switch (type) {
    case INCRESECOUNT: // 1씩 증가
      return {
        ...state,
        count: state.count + 1,
      };

    case DECRESECOUNT: // 1씩 감소
      return {
        ...state,
        count: state.count - 1
      };
     
      case SET_COUNT: // 100 증가 <<<<
        return {
          ...state,
          count: payload //payload 에 100이 들어가있음 payload = action.payload
        };

    default:
      return state;
  }
};
 
 
 
 

5. reducer.js 안에 reducer함수의 switch 문이 실행되면서 맞는것들을 실행시킨다.

const reducer = (state = initialState, action) => {
  let  {type, payload} = action
  switch <<< (type) {
    case INCRESECOUNT: // 1씩 증가
      return {
        ...state,
        count: state.count + 1,
      };

 

    case DECRESECOUNT: // 1씩 감소
      return {
        ...state,
        count: state.count - 1
      };
     
      case SET_COUNT: // 100 증가 <<<<
        return {
          ...state,
          count: payload //payload 에 100이 들어가있음 payload = action.payload
        };

 

    default:
      return state;
  }
};

 

 

6.아마 이때 미들웨어내부에있는 함수가 실행되면서 값이 변경된걸인지하는걸로 알고있다.

그러면서 getState를 발동하여 CountScreen에서 사용한 useSeletor가 실행되면서 변경된 값은 다시 Get 해 와

새로운 데이터를 화면에 뿌려주는것이다.

 

const count = useSelector(state => state.reducer.count); // 데이터 가져오기

(6번에대한 잘못된 정보가있으면 알려주시기 바랍니다. 감사합니다.)

 

 

 

 

 

 

 

 

 

 

 

 

이렇게 react-native에서 redux를 사용해보는 시간을 가졌다.

다음번에는 redux-saga 와 redux toolkit에 대한 포스팅을 해보겠다.

 

 

 

관련 코드는 깃허브에 올려놨습니다.

https://github.com/1domybest/react-native-redux-.git

728x90
Comments