๐ŸšจReact๋ฅผ ์ •๋ฆฌํ•ด์•ผ์ง€3 - ์ตœ์ ํ™”2, SPA

์ฟ ์šฐยท2023๋…„ 6์›” 20์ผ
0

React

๋ชฉ๋ก ๋ณด๊ธฐ
3/3

๐Ÿงน์ตœ์ ํ™”2

๐ŸšจuseReducer

๋ฆฌ์•กํŠธ์—์„œ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š” ํ›…(Hook) ํ•จ์ˆ˜์ค‘ ํ•˜๋‚˜๋กœ useState์™€ ๋น„์Šทํ•œ ์—ญํ• ์ด์ง€๋งŒ useState๋ณด๋‹ค ๋” ๋ณต์žกํ•œ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•  ๋•Œ ์‚ฌ์šฉ ๋œ๋‹ค. ์–ด๋–ป๊ฒŒ ๋ณต์žกํ•œ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•˜๊ฒŒ ๋˜๋Š”์ง€๋Š” ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์ž.

โž•reducer์— ๋Œ€ํ•ด์„œ ๋จผ์ € ์•Œ์•„์•ผํ•œ๋‹ค.

reducer๋Š” ์ปดํฌ๋„ŒํŠธ ๋ฐ–์—์„œ ์„ ์–ธ๋˜์–ด ํ˜„์žฌ ์ƒํƒœ์™€ ์•ก์…˜์„ ๋ฐ›์•„์„œ ์ƒˆ๋กœ์šด ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋กœ ๊ธฐ๋ณธ ๋ฌธ๋ฒ•์„ ๋ณด์•„๋ผ.

state: ํ˜„์žฌ ์ƒํƒœ
action : ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๊ฐ์ฒด๋กœ action ๊ฐ์ฒด๋Š” type ํ•„๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ๊ทธ ์™ธ์˜ ํ•„๋“œ๋Š” ์ƒํƒœ ๋ณ€๊ฒฝ์— ํ•„์š”ํ•œ ๊ฐ’๋“ค์„ ๋‹ด๊ณ  ์žˆ๋‹ค.


const reducer = (state, action) => {
  switch (action.type) {
    case "INIT": {
      return action.data;
    }
    case "CREATE": {
      const created_date = new Date().getTime();
      const newItem = {
        ...action.data,
        created_date
      };
      return [newItem, ...state];
    }
    case "REMOVE": {
      return state.filter((it) => it.id !== action.targetId);
    }
    case "EDIT": {
      return state.map((it) =>
        it.id === action.targetId
          ? {
              ...it,
              content: action.newContent
            }
          : it
      );
    }
    default:
      return state;
  }
};
.
.
.

โž•useReducer์— ๋Œ€ํ•œ ์ดํ•ด

const [state, dispatch] = useReducer(reducer, initialState);

state : ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ƒํƒœ
dispatch: ๋‚ด๋ถ€์— ๊ฐ์ฒด๋กœ type๊ณผ ํ˜„์žฌ state๊ฐ’์„ ๋‹ด๊ณ  useReducer์˜ ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ๋˜๋Š” ํ•จ์ˆ˜
reducer: reducerํ•จ์ˆ˜๋กœ ๋กœ์ง์ด ๋‹ด๊ฒจ ์žˆ์Œ
initialState: ์ดˆ๊ธฐํ™” ์ƒํƒœ

ํ๋ฆ„์„ ๋ณด๋ฉด
1. ํ™”๋ฉด ์š”์ฒญ๊ณผ ์ดˆ๊ธฐ ๋ Œ๋”๋ง.
2. initialState๊ฐ’์œผ๋กœ state ์ดˆ๊ธฐํ™” ๊ทธ๋ฆฌ๊ณ  reducer ํ•จ์ˆ˜ ๋ Œ๋”๋ง.
3. dispatchํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด useReducerํ•จ์ˆ˜๋ฅผ ๊ฑฐ์ณ reducerํ•จ์ˆ˜ ์‚ฌ์šฉ.
4. reducer ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฐ˜ํ™˜๋œ ์ƒํƒœ๋กœ ๋ณ€๊ฒฝ

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๋กœ์ง์ด ๋ถ„๋ฆฌ๋˜๊ณ  ์ปดํฌ๋„ŒํŠธ ๋ถ€๋ถ„์—์„œ๋Š” ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ• ์ง€ dispatch๋ฅผ ํ†ตํ•ด reducer์—์„œ ์‚ฌ์šฉ๋  ์ƒํƒœ์™€ ํ•จ์ˆ˜๋ฅผ ์ •ํ•œ๋‹ค.
{type: ์–ด๋–ค๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ณ  data: ์–ด๋–ค ์ƒํƒœ๋ฅผ ์ฃผ์ž…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.}

// ์œ„์™€ ๊ฐ™์ด ๋กœ์ง์ด ์ปดํฌ๋„ŒํŠธ์™€ ๋ถ„๋ฆฌ๊ฐ€ ๋œ๋‹ค.
const App = () => {
  const [data, dispatch] = useReducer(reducer, []);
  .
  .
  .
  const getData = async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/comments"
    ).then((res) => res.json());

    const initData = res.slice(0, 20).map((it) => {
      return {
        author: it.email,
        content: it.body,
        emotion: Math.floor(Math.random() * 5) + 1,
        created_date: new Date().getTime(),
        id: dataId.current++
      };
    });

    dispatch({ type: "INIT", data: initData });
  };

  const onCreate = useCallback((author, content, emotion) => {
    dispatch({
      type: "CREATE",
      data: { author, content, emotion, id: dataId.current }
    });
    dataId.current += 1;
  }, []);

โž•useReducer๋ฅผ ํ†ตํ•ด ๊ธฐ๋Šฅ์„ ๋ถ„๋ฆฌํ•˜๋Š” ์ด์œ 

๋ณดํ†ต์˜ useState๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํƒœ์— ๊ด€๋ จํ•œ ํ•จ์ˆ˜๋“ค์ด ๋งŽ์„ ๊ฒฝ์šฐ ํ˜ผ์žฌ๋˜์–ด ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์ฐพ์œผ๋ ค๋ฉด ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค. ๊ฐ€๋…์„ฑ์ด ์ €ํ•˜๋˜๊ณ  ์œ ์ง€๋ณด์ˆ˜์„ฑ๊นŒ์ง€ ์ €ํ•˜๋œ๋‹ค.

useReducer๋ฅผ ํ†ตํ•ด ์ƒํƒœ ์—…๋ฐ์ดํŠธ์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ์„ ์ปดํฌ๋„ŒํŠธ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ๋ถ„๋ฆฌ ์‹œํ‚ค๋ฉฐ ํ•ด๋‹น ๊ธฐ๋Šฅ๋“ค๋งŒ ์„ ์–ธํ•˜์—ฌ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์„ ์–ธ๊ณผ ์‚ฌ์šฉ์„ ๋ถ„๋ฆฌ ์‹œ์ผœ์„œ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์—์„œ๋„ ์žฅ์ ์„ ๊ฐ€์ง„๋‹ค.

๐Ÿšจcontext

์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค๋ฅธ ์–ธ์–ด์™€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋ฐฐ์šธ ๋•Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ context๋ผ๋Š” ๊ณต์œ ์˜์—ญ์„ ํ†ตํ•ด ์ „์—ญ์ ์ธ ๊ฐ’์ด๋‚˜ ํ–‰์œ„์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ ๋Š” ํ–ˆ๋‹ค.
React์—์„œ๋„ Context๋Š” ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ ์ „์ฒด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ์•„๋ž˜ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ๊ฐ™์ด ์ค‘๊ฐ„์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์ด props๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ํ•˜๋Š” ๊ณผ์ •์„ ์•ˆ๊ฑฐ์ณ๋„ ๋œ๋‹ค.

//App > DiaryList > DiaryItem๋กœ ์—ฐ๊ฒฐ๋˜๋Š” ์ปดํฌ๋„ŒํŠธ.
// DiaryList์—์„œ๋Š” onRemove์™€ onEdit์ด ๊ฑฐ์ณ๊ฐ€๊ธฐ๋งŒ ํ•œ๋‹ค.
const App = () => {
	return (
    .
    .
    .
     <DiaryList diaryList={data} onRemove={onRemove} onEdit={onEdit} />

    )
}

const DiaryItem = ({
  onRemove,
  onEdit,
  id,
  author,
  content,
  emotion,
  created_date
}) => {
  .
  .
  .
}

โž•context ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

Context๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Provider์™€ Consumer๋ผ๋Š” ๋‘ ๊ฐ€์ง€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค.

Provider๋Š” Context๋ฅผ ๊ตฌ๋…ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์—๊ฒŒ Context์˜ ๋ณ€ํ™”๋ฅผ ์•Œ๋ฆฌ๋Š” ์—ญํ• ๋กœ Provider ์ปดํฌ๋„ŒํŠธ๋Š” value๋ผ๋Š” prop์„ ๋ฐ›์•„์„œ ์ด ๊ฐ’์„ ํ•˜์œ„์— ์žˆ๋Š” ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ „๋‹ฌํ•œ๋‹ค.

Consumer๋Š” Provider๋กœ ๋ฐ›์€ ๊ฐ’์— ๋Œ€ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“œ๋Š”๋ฐ ์ด๋Š” useContext๋ผ๋Š” Hook ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋Œ€์ฒด ๊ฐ€๋Šฅํ•˜๋‹ค.

์•„๋ž˜๋Š” ์‚ฌ์šฉ์˜ˆ์ œ์ด๋‹ค.


// ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•  context ์˜์—ญ์„ ๋งŒ๋“ ๋‹ค.
// ์ƒํƒœ๋ฅผ ๋ณ€ํ™”์‹œํ‚ฌ ํ•จ์ˆ˜๋ฅผ ๊ณต์œ ํ•  context ์˜์—ญ์„ ๋งŒ๋“ ๋‹ค. ๋ถ„๋ฆฌ ์ด์œ  ์•„๋ž˜์— ์ ์Œ
export const DiaryStateContext = createContext(null);
export const DiaryDispatchContext = createContext(null);

const App = () => {
  /*
  context๊ฐ€ ๋žœ๋”๋ง ๋  ๋•Œ ์•ˆ์— ๋“ค์–ด๊ฐ„ ์š”์†Œ๋“ค๋„ ๋ชจ๋‘ ๋žœ๋”๋ง๋˜๊ธฐ๋•Œ๋ฌธ์— ์ตœ์ ํ™”๊ฐ€ ํ’€๋ฆฌ๊ฒŒ ๋œ๋‹ค. 
  ๋”ฐ๋ผ์„œ ์ƒํƒœ์— ๋Œ€ํ•œ context์™€ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ context๋ฅผ ๋ถ„๋ฆฌํ•ด์ค€๋‹ค.
  ๊ฑฐ๊ธฐ์— ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๊ฒƒ๋“ค์„ useMemo๋กœ ํ•œ๋ฒˆ ๋” ๊ฐ์‹ธ์ค˜์„œ context์— ๋“ฑ๋กํ•ด์ค€๋‹ค.  
  (์‚ฌ์šฉํ• ๋•Œ๋Š” ๊ฐ์‹ธ์ค€๊ฒƒ์ด ์•„๋‹Œ ๊ฐ๊ฐ์œผ๋กœ ๋ถˆ๋Ÿฌ๋„ ๊ดœ์ฐฎ์€ ๋“ฏ)
  */
  const memoizedDispatch = useMemo(() => {
    return { onCreate, onRemove, onEdit };
  }, []);
  .
  .
  .
  // ๊ฐ€์žฅ ๋ฐ”๊นฅ์— Provider์ปดํฌ๋„ŒํŠธ์— value๋ฅผ ์ค˜์„œ ๊ฐ์‹ธ์ฃผ๋ฉด ๋ 
  return (
    <DiaryStateContext.Provider value={data}>
      <DiaryDispatchContext.Provider value={memoizedDispatch}>
        <div className="App">
          <DiaryEditor />
          <div>์ „์ฒด ์ผ๊ธฐ : {data.length}</div>
          <div>๊ธฐ๋ถ„ ์ข‹์€ ์ผ๊ธฐ ๊ฐœ์ˆ˜ : {goodCount}</div>
          <div>๊ธฐ๋ถ„ ๋‚˜์œ ์ผ๊ธฐ ๊ฐœ์ˆ˜ : {badCount}</div>
          <div>๊ธฐ๋ถ„ ์ข‹์€ ์ผ๊ธฐ ๋น„์œจ : {goodRatio}%</div>
          <DiaryList />
        </div>
      </DiaryDispatchContext.Provider>
    </DiaryStateContext.Provider>
  );
};


//์‚ฌ์šฉ์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด useContext๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ

const DiaryList = () => {
  const diaryList = useContext(DiaryStateContext);
  .
  .
  .
  .
}


const DiaryItem = ({ id, author, content, emotion, created_date }) => {
  const { onRemove, onEdit } = useContext(DiaryDispatchContext);
  .
  .
  .
}

๐Ÿš€React์™€ SPA

๐ŸŽˆMulti Page Application

์ง€๊ธˆ๊นŒ์ง€ ๋‚ด๊ฐ€ ๋งŒ๋“ค์—ˆ๋˜ ์ž๋ฐ” ํ”„๋กœ์ ํŠธ๋ฅผ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ™”๋ฉด
์ฆ‰, html template๋ฅผ ๋งŒ๋“ค๊ณ  ์›น์„œ๋ฒ„์™€ ์†Œ์ผ“์„ ์ด์šฉํ•ด์„œ ์š”์ฒญ์„ ๋ฐ›๊ณ  ๋ฐ”์ธ๋”ฉ ๋˜์–ด์žˆ๋Š” ๊ฐ’๋“ค์— ๋งž์ถฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ™”๋ฉด์„ ๋„˜๊ฒจ์ฃผ์—ˆ๋‹ค.

์•„๋ž˜์—๋Š” MPA์ฆ‰ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑ๋˜์–ด์žˆ๋Š” ํŽ˜์ด์ง€์˜ ์ด๋™๊ฐ„์„ ์บก์ณํ•œ ์‚ฌ์ง„์ด๋‹ค.

ํ™”๋ฉด ์ด๋™ ์ค‘ ์ƒˆ๋กœ๊ณ ์นจ ํ‘œ์‹œ๊ฐ€ ๋Œ์•„๊ฐ€๋ฉด์„œ ๋‚ด๋ถ€์ ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์–ด ์‘๋‹ต์„ ์ค„ ๋•Œ๊นŒ์ง€ ๋”œ๋ ˆ์ด ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์žฅ์ ์œผ๋กœ๋Š” ์„œ๋ฒ„์—์„œ ์ด๋ฏธ ๋ Œ๋”๋งํ•ด ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์ฒซ ๋กœ๋”ฉ์ด ๋งค์šฐ ์งง๋‹ค๋Š” ๊ฒƒ์ด ์žˆ๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ ์„œ๋ฒ„๋‹จ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜์—ญ์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์•ˆ์ ์œผ๋กœ๋„ ์šฐ์ˆ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ์ ์œผ๋กœ๋Š” SPA์— ๋น„ํ•ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ์ข‹์ง€ ๋ชปํ•˜๋‹ค๋Š” ๊ฒƒ์ด ์žˆ๋‹ค.
(์˜ˆ์‹œ : ๋ฒค์ธ  ํ™ˆํŽ˜์ด์ง€)

๐ŸŽˆCSR๊ณผ SSR

๐Ÿšจ CSR(Client Side Rendering)

๋ธŒ๋ผ์šฐ์ €์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๋ฉฐ CSR์˜ ๊ฒฝ์šฐ HTML, CSS์™€ ๋ชจ๋“  ์Šคํฌ๋ฆฝํŠธ๋“ค์„ ํ•œ ๋ฒˆ์— ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
CSR์€ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋Š๋ฆฌ์ง€๋งŒ, ์‚ฌ์šฉ์ž์™€ ์ƒํ˜ธ์ž‘์šฉ ํ•  ๋•Œ๋งˆ๋‹ค ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์„œ๋ฒ„์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„์—๋Š” ๋น ๋ฅธ ๋ฐ˜์‘์„ฑ์„ ๋ณด์ธ๋‹ค.

๐Ÿšจ SSR(Server Side Rendering)

์„œ๋ฒ„์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๋ฉฐ ํ•„์š”ํ•œ ๋ถ€๋ถ„์˜ HTML๊ณผ ์Šคํฌ๋ฆฝํŠธ๋งŒ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.
SSR์€ ์ดˆ๊ธฐ ๋กœ๋”ฉ ์†๋„๊ฐ€ ๋น ๋ฅด์ง€๋งŒ, ์ดํ›„์—๋Š” ๋Š๋ฆฐ ๋ฐ˜์‘์„ฑ์„ ๋ณด์ธ๋‹ค.

๋‚˜๋Š” SSR์—์„œ ํŽ˜์ด์ง€ ์ด๋™๋งˆ๋‹ค ๋กœ๋”ฉ ๊ฑธ๋ฆฌ๋Š” ๊ฒƒ๋งŒ ๋Š๊ปด์ง„๋‹ค.
๊ทธ๋งŒํผ CSR์ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ์ข‹๋‹ค๋Š” ์ด์•ผ๊ธฐ

๐ŸŽˆSingle Page Application

index.html (entry point) ์—์„œ JS์™€ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ํ†ตํ•ด ์š”์ฒญ์— ๋”ฐ๋ฅธ HTML์š”์†Œ๋งŒ์„ ๋ณ€๊ฒฝํ•˜์—ฌ ํ™”๋ฉด์„ ๋ฐ”๊ฟ”์ฃผ๋ฉฐ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์šฐ์„ ์„ ๋‘” ๋ฐฉ๋ฒ•

๐ŸšจํŽ˜์ด์ง€ ๋ผ์šฐํŒ…

๋ผ์šฐํŒ…์ด๋ž€? ๊ฒฝ๋กœ๋ฅผ ์ •ํ•ด์ฃผ๋Š” ํ–‰์œ„ ๊ทธ ์ž์ฒด๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ํŽ˜์ด์ง€ ๋ผ์šฐํŒ…์ด๋ž€ ์š”์ฒญ์— ๋”ฐ๋ผ ์–ด๋–ค ํŽ˜์ด์ง€๋กœ ๊ฐ€์•ผํ•˜๋Š”์ง€ ๊ฒฝ๋กœ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ณผ์ •์„ ์˜๋ฏธํ•œ๋‹ค.

๐Ÿšจreact-router-dom@6

๋ฆฌ์•กํŠธ์—์„œ ํŽ˜์ด์ง€ ๋ผ์šฐํŒ…์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.
๋ผ์šฐํ„ฐ api์— ๋Œ€ํ•ด์„œ ์ถ”๊ฐ€ํ•˜๊ณ  ํ•ญ์ƒ ์ตœ์‹ ๋ฒ„์ „์ธ์ง€ ํ™•์ธ!

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ํ˜•์‹
BrowserRouter๋Š” HTML5 history API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๋ผ์šฐํŒ…์„ ์ฒ˜๋ฆฌ.
Routes๋Š” ์—ฌ๋Ÿฌ ๊ฒฝ๋กœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ,
Route๋Š” ๊ฒฝ๋กœ์™€ ํ•ด๋‹น ๊ฒฝ๋กœ์— ๋Œ€ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งคํ•‘.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ
path variable ์ด๋ผ๋Š” ๊ธฐ๋Šฅ -> useParams๋ฅผ ์ด์šฉํ•ด์„œ url์— ๋ณ€์ˆ˜๋กœ ์ง€์ •
Query String ์ฒ˜๋ฆฌ ๊ธฐ๋Šฅ -> useSearchParams ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด์„œ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์œผ๋กœ ์˜จ ๋ณ€์ˆ˜๋“ค์„ ์ €์žฅ
page moving - > useNavigate()์„ ์ด์šฉํ•ด์„œ ์ง€์ •ํ•œ ํŽ˜์ด์ง€๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ -1์„ ๋„ฃ์œผ๋ฉด ๋’ค๋กœ ๊ฐ€๊ธฐ ๊ฐ€๋Šฅ

์•„๋ž˜๋Š” ์‚ฌ์šฉ์— ๋Œ€ํ•œ ์˜ˆ์ œ ์ฝ”๋“œ

import { BrowserRouter, Route, Routes } from "react-router-dom";

import Home from "./pages/Home";
import New from "./pages/New";
import Edit from "./pages/Edit";
import Diary from "./pages/Diary";


function App() {
	return (
    	  <BrowserRouter>
            <div className="App">
              <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/new" element={<New />} />
                <Route path="/edit/:id" element={<Edit />} />
                <Route path="/diary/:id" element={<Diary />} />
              </Routes>
            </div>
        </BrowserRouter>
    )
}
import { useNavigate, useParams } from "react-router-dom";


const Diary = () => {
  const { id } = useParams();
  .
  .
  .
  return (
    <div className="DiaryPage">
    	<MyHeader
          headText={`${getStringDate(new Date(data.date))} ๊ธฐ๋ก`}
          leftChild={
            <MyButton text={"< ๋’ค๋กœ๊ฐ€๊ธฐ"} onClick={() => navigate(-1)} />
          }
          rightChild={
            <MyButton
              text={"์ˆ˜์ •ํ•˜๊ธฐ"}
              onClick={() => navigate(`/edit/${data.id}`)}
            />
          }
        />
    .
    .
    .
  )
}
profile
์ผ๋‹จ ํ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€