/TIL

what i learn today

Primary LanguageJava

TIL - What i Learn Today๐Ÿ“–

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ณต๋ถ€ํ•œ ๊ฒƒ ์ •๋ฆฌ์šฉ๋„

index

start Date : 2021/11/11

redux-action

  • redux-action์€ ์•ก์…˜์ƒ์„ฑ ํ•จ์ˆ˜์™€ ๋ฆฌ๋“€์„œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  • createAction, handleAction, combineAction ์ด ์žˆ๋‹ค.(createAction๊ณผ handleAction ์„ ์ฃผ๋กœ ์ด์šฉํ•˜๋Š”๊ฑฐ ๊ฐ™๋‹ค.)

1. createAction

* ์•ก์…˜ ์ƒ์„ฑ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ•จ์ˆ˜ ์ด๋‹ค.
* ์ง์ ‘ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Œ
* ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ ๋ฐ›์€ ๊ฐ’์„ ์•ก์…˜์˜ payload ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค.
// ๊ธฐ์กด
export const increment = (index) => ({
  type: "INCREMENT",
  index,
});
//===========================================
// createAction๋ฅผ ์‚ฌ์šฉ
export const increment = createAction("INCREMENT");

//์ด๋ ‡๊ฒŒ createAction๋กœ ์ƒ์„ฑ ํ›„ increment(ํŒŒ๋ผ๋ฏธํ„ฐ) ๋ฅผ ๋„ฃ์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
increment(1);

createAction์œผ๋กœ ์ƒ์„ฑํ•œ increment๋ฅผ ํ˜ธ์ถœ ํ•˜๊ฒŒ ๋˜๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ์•ก์…˜์ด ๋งŒ๋“ค์–ด์ง„๋‹ค.

{
    type: 'INCREMENT',
    payload: 1
}

2. handleAction

* ๋ฆฌ๋“€์„œ ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค.
* ๋ฆฌ๋“€์„œ๋ฅผ ๊ฐ„๋‹จํ•˜๊ณ  ๊ฐ€๋…์„ฑ์žˆ๊ฒŒ ์ž‘์„ฑ ํ•  ์ˆ˜ ์žˆ๋‹ค.
* ์ฒซ๋ฒˆ์งธ ์ธ์ž๋Š” ์•ก์…˜์„ ์‹คํ–‰ํ•  ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด, ๋‘๋ฒˆ์งธ ์ธ์ž๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค.

๊ธฐ์กด ํ˜•์‹

const reducer = (state = initState, action) => {
  switch (action.type) {
    case "INCREMENT":
      return {
        ...state,
        number: state.number + 1,
      };
    case "DECREMENT":
      return {
        ...state,
        number: state.number - 1,
      };
    default:
      return state;
  }
};

creahandleAction์„ ์‚ฌ์šฉ

const reducer = handleActions(
  {
    INCREMENT: (state, action) => ({
      counter: state.counter + action.payload,
    }),

    DECREMENT: (state, action) => ({
      counter: state.counter - action.payload,
    }),
  },
  { counter: 0 }
);

๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ


immer

  • React์—์„œ state์˜ ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

    ๋ณ€ํ•˜์ง€ ์•Š๋Š” ์„ฑ์งˆ์„ ๋ถˆ๋ณ€์„ฑ์ด๋ผ๊ณ  ํ•œ๋‹ค.
    React์—์„œ๋Š” State๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๋ณ€ํ™”์‹œํ‚ค๋ฉด ์•ˆ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๋Š”๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.

React์˜ State

  • ๋ฐ์ดํ„ฐ์˜ ๊ด€๋ฆฌ์†Œ๋ผ๊ณ  ๋ณด๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.
  • State์˜ ์–•์€๋น„๊ต๋ฅผ ํ†ตํ•ด์„œ ์ƒˆ๋กœ์šด ๊ฐ’์ธ์ง€ ํŒ๋‹จํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์ƒˆ๋กœ์šด ๊ฐ’์ผ ๊ฒฝ์šฐ ๋ฆฌ๋ Œ๋”๋ง
  • state๋ฅผ ๋ณ€ํ™”์‹œํ‚ค๊ณ  DOM์„ ๋‹ค์‹œ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ƒˆ๋กœ์šด ๊ฐ์ฒด or ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด ์ƒˆ๋กœ์šด ์ฐธ์กฐ๊ฐ’์ด ์ƒ์„ฑ๋˜์–ด์•ผ ํ•œ๋‹ค.
//์ด๋ ‡๊ฒŒ ์ง์ ‘์ ์œผ๋กœ ์ˆ˜์ •ํ•˜๋ฉด ๋ฆฌ๋ Œ๋”๋ง ๋˜์ง€ ์•Š๋Š”๋‹ค.
state.push("value"); //์ƒˆ๋กœ์šด ์ฐธ์กฐ๊ฐ’์ด ์•„๋‹˜

//state ๋ณ€ํ™”ํ•˜๋Š” ๊ฒฝ์šฐ
//Class component ์ผ๊ฒฝ์šฐ
setState((prevState) => {
  return newState;
});
//ํ˜น์€
setState(newState);

//functional component ์ผ ๊ฒฝ์šฐ
const [value, setValue] = useState(์ดˆ๊ธฐ๊ฐ’);
setValue(newState);

immer๋ฅผ ์‚ฌ์šฉ

// state : ๋ฐ”๊พธ๊ณ ์‹ถ์€ ๊ฐ์ฒด or ๋ฐฐ์—ด
// draft : ์–ด๋–ค์‹์œผ๋กœ ๋ณ€๊ฒฝํ• ์ง€์— ๋Œ€ํ•œ ํ•จ์ˆ˜
const nextState = produce(state, (draft) => {
  draft.value = value;
});

์ด๋Ÿฐ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋˜๋ฉด ์–•์€๋ณต์‚ฌ๋ฅผ ํ†ตํ•ด์„œ ๋ฆฌ๋ Œ๋”๋ง์ด ๋œ๋‹ค.

redux์—์„œ immer ์‚ฌ์šฉ

  • ์ฃผ๋กœ ๋ฆฌ๋“€์„œ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.
//๊ธฐ์กด ๋ฆฌ๋“€์„œ ์ƒ์„ฑํ• ๋•Œ
const reducer = (state = initState, action) => {
  switch (action.type) {
    case "INCREMENT":
      return {
        ...state,
        number: state.number + 1,
      };
    case "DECREMENT":
      return {
        ...state,
        number: state.number - 1,
      };
    default:
      return state;
  }
};
// immer๋ฅผ ์ ์šฉํ•œ ๋ฆฌ๋“€์„œ
const reducer = (state = initState, action) => {
  switch (action.type) {
    case "INCREMENT":
      return produce(state, (draft) => {
        draft.number + 1;
      });
    case "DECREMENT":
      return produce(state, (draft) => {
        draft.number - 1;
      });
    default:
      return state;
  }
};

์Šคํ”„๋ ˆ๋“œ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค.

useState ํ•จ์ˆ˜ํ˜• ์—…๋ฐ์ดํŠธ์— ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ

const [value, setValue] = useState({
  number: 1,
  done: false,
});

//๊ธฐ์กด
const onClick = useCallback(() => {
  setValue((value) => ({
    ...value,
    done: !value.done,
  }));
}, []);

//์ ์šฉํ•œ๊ฒƒ
const onClick = useCallback(() => {
  setValue(
    produce((draft) => {
      draft.done = !draft.done;
    })
  );
}, []);

์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ ์ƒํƒœ๊ฐ’์„ ์ƒ๋žตํ•˜๊ณ  ๋‘๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ ์—…๋ฐ์ดํŠธ ํ•จ์ˆ˜๋งŒ ๋„ฃ์–ด์ฃผ๋ฉด ์—…๋ฐ์ดํŠธ๋ฅผ ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋œ๋‹ค.

๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ


redux-middleware

  • ์ฃผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌ ํ•  ๋•Œ ์‚ฌ์šฉ
  • action์„ dispatch ํ–ˆ์„ ๋•Œ reducer๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „์— ์ถ”๊ฐ€ ์ž‘์—…์„ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  • redux-thunk์™€ redux-saga ๋‘๊ฐ€์ง€๊ฐ€ ๊ฐ€์žฅ ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ ์šฉ ํ•  ๋•Œ๋Š” applyMiddleware(๋ฏธ๋“ค์›จ์–ด) ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    (logger๋ฅผ ์‚ฌ์šฉ ํ•  ๋•Œ๋Š” ๋งจ๋’ค์— logger๋ฅผ ์ ์šฉ์‹œ์ผœ์•ผํ•จ example : applayMiddleware(thunk,logger) )
  • ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋ฆฌ๋•์Šค์˜ ํ๋ฆ„ : ์•ก์…˜ -> ๋ฏธ๋“ค์›จ์–ด -> ๋ฆฌ๋“€์„œ -> ์Šคํ† ์–ด

๊ฐ€๋Šฅํ•œ ์ถ”๊ฐ€ ์ž‘์—…

  • ์•ก์…˜์ด ๋ฌด์‹œ๋˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ์•ก์…˜์„ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ ์„œ๋ฒ„์— ๋กœ๊น… ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜ ๋์„ ๋•Œ ์ˆ˜์ •ํ•ด์„œ ๋ฆฌ๋“€์„œ์— ์ „๋‹ฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŠน์ • ์•ก์…˜์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‹ค๋ฅธ ์•ก์…˜์ด ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŠน์ •์•ก์…˜์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ๋•์Šค ๋ฏธ๋“ค์›จ์–ด์˜ ํ…œํ”Œ๋ฆฟ

const middleware = store => next => action =>{
    //์ˆ˜ํ–‰ํ•  ์ž‘์—…
}
// ์œ„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ’€์–ด์„œ ์“ด๊ฒƒ
function middleware(store){
    return function(next){
        return function(action){
            ์ˆ˜ํ–‰ํ•  ์ž‘์—…
        }
    }
}
  • store๋Š” ๋ฆฌ๋•์Šค ์Šคํ† ์–ด ์ธ์Šคํ„ด์Šค( dispatch, getState, subscribe ๋‚ด์žฅํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•จ)์ด๋‹ค.
  • action์€ ํ˜„์žฌ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ์•ก์…˜ ๊ฐ์ฒด
  • next๋Š” ์•ก์…˜์„ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด์— ์ „๋‹ฌํ•˜๋Š” ํ•จ์ˆ˜ next(action) ๊ฐ™์€ ์‹์œผ๋กœ ์‚ฌ์šฉ
    (next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์•ก์…˜์ด ๋ฌด์‹œ์ฒ˜๋ฆฌ๋˜์–ด ๋ฆฌ๋“€์„œ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ)

redux-thunk

  • ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌ ํ•  ๋•Œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด
  • ์•ก์…˜ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜๋ฅผ ๋””์ŠคํŒจ์น˜ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜๋ฅผ ๋””์ŠคํŒจ์น˜ ํ•  ๋•Œ๋Š” dispatch์™€ getState๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์™€์•ผ ํ•œ๋‹ค.
    (getState๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ๋ฐ›์•„์˜ค์ง€ ์•Š์•„๋„ ๋ฌด๊ด€ํ•จ)

Thunk ์˜ˆ์ œ

export const increase = () => (dispatch, getState) => {
  setTimeOut(() => dispatch(increase()), 1000); //1์ดˆ ๋”œ๋ ˆ์ดํ›„ dispatch์‹œํ‚ด
};

// getState๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์„œ ๋„ฃ์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์Œ
export const increase = () => (dispatch) => {
  setTimeOut(() => dispatch(increase()), 1000);
};

// Async/await๋„ ์ ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค
export const callApi = () => async (dispatch) => {
  try {
    const data = await API.getData();
    dispatch({ type: GET_DATA_SUCCESS, data });
  } catch (e) {
    dispatch({ type: GET_DATA_ERROR, error: e });
  }
};

redux-saga

  • ์•ก์…˜์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋‹ค ํŠน์ • ์•ก์…˜์ด ๋ฐœ์ƒํ•˜๋ฉด ํŠน์ • ์ž‘์—…์„ ํ•˜๋Š” ๋ฐฉ์‹(ํŠน์ •์•ก์…˜ : ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰, ๋‹ค๋ฅธ์•ก์…˜ ๋””์ŠคํŒจ์น˜, ํ˜„์žฌ ์ƒํƒœ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ)
  • Generator ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•  ๋•Œ ๊ธฐ์กด ์š”์ฒญ์„ ์ทจ์†Œ ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŠน์ • ์•ก์…˜์ด ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋‹ค๋ฅธ ์•ก์…˜์ด ๋””์ŠคํŒจ์น˜๋˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜, js์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์›น์†Œ์ผ“ ์‚ฌ์šฉ ์‹œ Channel์ด๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ํšจ์œจ์ ์œผ๋กœ ์ฝ”๋“œ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ
  • API ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์„ ๋•Œ ์žฌ์š”์ฒญํ•˜๋Š” ์ž‘์—… ๊ฐ€๋Šฅ

Generator๋ฌธ๋ฒ•

  • ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑ ํ•  ๋•Œ ํ•จ์ˆ˜๋ฅผ ํŠน์ • ๊ตฌ๊ฐ„์— ๋ฉˆ์ถ”๊ฑฐ๋‚˜ ๋˜๋Œ์•„๊ฐ€๊ฒŒ ํ•  ์ˆ˜ ์ž‡๋‹ค.
  • function * ์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค
  • yield ๋ผ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์ผ์‹œ์ ์œผ๋กœ ์ •์ง€๋˜๊ณ  ๋ฉ”์„œ๋“œ.next() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๋‹ค์‹œ ์‹œ์ž‘ ๋  ์ˆ˜ ์žˆ๋‹ค.
function* generatorFunction() {
  console.log("1");
  yield 1;
  console.log("2");
  yield 2;
  console.log("3");
  yield 3;
  return 4;
}

const generator = generatorFunction();

//next๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋˜๋ฉด yield ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์ฝ”๋“œ์˜ ์ง„ํ–‰์„ ๋ฉˆ์ถ˜๋‹ค.
generator.next(); // value : 1, done : false
generator.next(); // value : 2, done : false
generator.next(); // value : 3, done : false
//yield๊ฐ€ ๋๋‚˜๊ณ  return์ด ๋˜๋ฉด done ๊ฐ’์ด true๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.
generator.next(); // value : 4, done : true

function* generatorFunction2() {
  let a = yield;
  let b = yield;
  yield a + b;
}

const generator2 = generatorFunction2();

//nextํ˜ธ์ถœ์‹œ ์ธ์ž๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ๋„ ์ด์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
generator2.next(1); // value : undefined, done : false
generator2.next(2); // value : undefined, done : false
generator2.next(); // value : 3, done : true

saga์˜ ์ฃผ์š”ํ•จ์ˆ˜

  • delay(ms) => ์„ค์ •๋œ ์‹œ๊ฐ„ ์ดํ›„์— resolveํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค
  • put({type,payload}) => ํŠน์ • ์•ก์…˜์„ dispatch ํ•˜๋„๋ก ํ•œ๋‹ค
  • takeEvery(type, function) => ๋“ค์–ด์˜ค๋Š” ๋ชจ๋“  ์•ก์…˜์— ๋Œ€ํ•ด ํŠน์ • ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค.
  • takeLatest(type,function) => ๊ธฐ์กด ์ง„ํ–‰ ์ค‘์ด๋˜ ์ž‘์—…์„ ์ทจ์†Œํ•˜๊ณ  ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ์ž‘์—…๋งŒ ์ˆ˜ํ–‰
  • call(function,parameter) => ํŠน์ • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฌผ์ด ๋ฐ˜ํ™˜ ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
  • all([ ]) => ์ œ๋„ค๋ ˆ์ดํ„ฐ ํ•จ์ˆ˜๋ฅผ ๋ฐฐ์—ด๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋ณ‘ํ–‰์ ์œผ๋กœ ๋™์‹œ์— ์ˆ˜ํ–‰ Promise.all๊ณผ ๋น„์Šทํ•จ

redux-saga ์ ์šฉํ•ด๋ณด๊ธฐ

/* saga ๋ฉ”์„œ๋“œ ๊ตฌํ˜„ */
const GET_DATA = "GET_DATA";

function* getDataSaga() {
  try {
    const count = yield call(DataAPI.getData);
    //์„ฑ๊ณต์‹œ
    yield put({
      type: GET_DATA_SUCCESS,
      payload: data,
    });
  } catch (e) {
    //์‹คํŒจ์‹œ
    yield put({
      type: GET_DATA_ERROR,
      error: true,
      payload: e,
    });
  }
}

export function* dataSaga() {
  yield takeEvery(GET_DATA, getDataSaga);
}

/* ๋ฃจํŠธ ๋ฉ”์†Œ๋“œ index */
//๋ฏธ๋“ค์›จ์–ด์— ์ ์šฉํ•  rootSaga ๋งŒ๋“ค๊ธฐ
const rootReducer = combineReducers(๋ฆฌ๋“€์„œ๋“ค);
export function* rootSage() {
  //์œ„์—์„œ ๋งŒ๋“  dataSaga๋ฅผ ๋„ฃ์–ด์คŒ
  yield all([dataSaga()]); //all์€ ๋ฐฐ์—ด ์•ˆ์˜ ์—ฌ๋Ÿฌ ์‚ฌ๊ฐ€๋ฅผ ๋™์‹œ์— ์‹คํ–‰์‹œ์ผœ ์ค€๋‹ค.
}

/* ์Šคํ† ์–ด */
//๋ฏธ๋“ค์›จ์–ด์— ์ ์šฉ
const sagaMiddleware = createSagaMiddleware(); // ์‚ฌ๊ฐ€ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋งŒ๋“ฌ

const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));

//์Šคํ† ์–ด ์ƒ์„ฑ ํ›„ ์‹คํ–‰ ์‹œ์ผœ์ค˜์•ผํ•จ
sagaMiddleware.run(rootSaga);

๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ


๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ ํ™˜๊ฒฝ์„ค์ •

npm

  • node.js์˜ ์˜์กด์„ฑ๊ณผ ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €
  • npm install์œผ๋กœ package.josn ํŒŒ์ผ์— ์˜์กด์„ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • ๋ฒ„์ „๊ด€๋ฆฌ ์ง€์›

    ํŒจํ‚ค์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
    npm i ํŒจํ‚ค์ง€๋ช… ํ˜น์€ npm install ํŒจํ‚ค์ง€๋ช… ์œผ๋กœ ๋‹ค์šด ๊ฐ€๋Šฅ
    ์ธ์Šคํ†จ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ• ๋•Œ -D๋Š” --save-dev -P๋Š” --save-prod -g๋Š” ๊ธ€๋กœ๋ฒŒ์— ์ธ์Šคํ†จ

npx

  • node ํŒจํ‚ค์ง€๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๋„๊ตฌ(npm5.2.0 ์ด์ƒ ์ง€์›) npx ํŒจํ‚ค์ง€๋ช… ์œผ๋กœ ์‚ฌ์šฉ

    npx์˜ ์—ญํ• 

    1. ์‹คํ–‰ํ•  ํŒจํ‚ค์ง€๊ฐ€ ๊ฒฝ๋กœ์— ์žˆ๋Š”์ง€ ํ™•์ธ
    2. ๊ฒฝ๋กœ์— ์žˆ์œผ๋ฉด ์‹คํ–‰
    3. ๊ฒฝ๋กœ์— ์—†์„ ๊ฒฝ์šฐ npx๊ฐ€ ์ตœ์‹  ๋ฒ„์ „ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ ํ•œ ํ›„ ์‹คํ–‰

create-react-app

  • npm i create-react-app
  • ๋ฆฌ์•กํŠธ์˜ ๊ธฐ์ดˆํ™˜๊ฒฝ์„ ์„ค์ •ํ•ด์ฃผ๋Š” ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ์ด๋‹ค.
  • ๋ฐ”๋ฒจ, ์›นํŒฉ๋“ฑ ๋‹ค์–‘ํ•œ ํŒจํ‚ค์ง€๊ฐ€ ํฌํ•จ๋˜์–ด์žˆ๋‹ค (ES6+ ๋ฌธ๋ฒ•, CSS ํ›„์ฒ˜๋ฆฌ๋„ ํฌํ•จ)

ESLint & Prettier

ESLint

์†Œ์Šค์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด ๋ฌธ๋ฒ•์  ์˜ค๋ฅ˜, ์Šคํƒ€์ผ์  ์˜ค๋ฅ˜, ๊ตฌ์กฐ ๋“ฑ์— ํ‘œ์‹œ๋ฅผ ๋‹ฌ์•„์ฃผ๋Š” ๋„๊ตฌ
ํ˜‘์—… ์‹œ ์Šคํƒ€์ผ์„ ํ†ต์ผ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค

Prettier

์ฝ”๋“œ๋ฅผ ์ •๋ ฌํ•ด ์ฃผ๋Š” Code Formatter ์ •ํ•ด์ง„ ๊ทœ์น™์— ๋”ฐ๋ผ Prettier๊ฐ€ ์ž๋™์œผ๋กœ formatting์„ ํ•ด์คŒ

์‚ฌ์šฉ๋ฒ•

root ํด๋”์— .prettierrc ์ƒ์„ฑ ๋ฐ ์„ค์ •

    {
    "singleQuote": true, // '' ๋กœ ์‚ฌ์šฉํ• ๊ฒƒ์ธ์ง€
    "semi": true, //์„ธ๋ฏธ์ฝœ๋ก  ์‚ฌ์šฉํ• ์ง€
    "tabWidth": 2, //๋“ค์—ฌ์“ฐ๊ธฐ ์นธ์ˆ˜
    "trailingComma": "all", //์‰ผํ‘œ๋ฅผ ๋ถ™์ผ์ง€ "none", "es5", "all" ๊ฐ€๋Šฅ
    "printWidth": 80 //ํ•œ์ค„์— ๋ช‡์นธ๊นŒ์ง€ ์ž‘์„ฑํ• ์ง€
    }
//์ถ”๊ฐ€์˜ต์…˜์€ https://prettier.io/docs/en/options.ahtml ์—์„œ ํ™•์ธ

VSCode ํ™•์žฅ์—์„œ Prettier ์„ค์น˜ ํ›„ ํ™˜๊ฒฝ์„ค์ •์—์„œ Format On Save ์ฒดํฌ

ESLint ์„ค์น˜ ํ›„ ํ™˜๊ฒฝ์„ค์ •์—์„œ Auto Fix on Save ์ฒดํฌ
npm install eslint-config-prettier ํ›„ pakage.json์— ์•„๋ž˜์ฝ”๋“œ ์ถ”๊ฐ€

    "eslintConfig" :{
        "extends":[
            "prettier"
        ],
        "rules": {
        "react/jsx-filename-extension": 0 //ํŒŒ์ผ์„ .jsx ํ™•์žฅ์ž ๊ทœ์น™ ๋ฌด์‹œ
        }
    }

auto Import ๋„ vscode์˜ ํ™•์žฅ์—์„œ ๋‹ค์šด ๋ฐ›์œผ๋ฉด ํŽธํ•œ ๊ฐœ๋ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชฉ์ฐจ๋กœ ๋Œ์•„๊ฐ€๊ธฐ