글 작성자: 망고좋아
반응형

📖 오늘 배운 내용 - 2022.01.18

  • json-server
  • 리액트, 리덕스, 라우터를 사용한 프로젝트 복습
  • Development, Production의 차이
  • CI/CD

 

📝 json-server

  • 개발 초기 api가 아직 안 나왔을 때 mock을 사용해서 작업할 수 있다.
  • db.json 파일 만들어주고 사용할 데이터를 객체로 넣어주기
  • npx json-server --w db.json 실행
  • npx json-server --w db.json --port 3333(포트 번호)
// db.json
{
  "topics": [
    {
      "title": "html5",
      "body": "html5 is ...",
      "id": 1
    },
    {
      "id": 2,
      "title": "css",
      "body": "css is..."
    },
    {
      "title": "js",
      "body": "js is ...",
      "id": 3
    }
  ]
}
async function test() {
    let response = await fetch('http://localhost:3000/topics', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({title:'js', body:'js is ...'})
        });
    let result = await response.json();
}
test()

 

📝 리액트, 리덕스, 라우터를 사용한 프로젝트 복습

📕 리덕스, 리액트-리덕스, 리액트 라우터 설치

npm i redux react-redux react-router-dom

 

📕 리덕스 세팅 ( 리덕스 스토어를 만든다.)

import { createStore } from "redux";

// 리덕스 스토어를 만든다.
function reducer(state, action) {
  // state 변경 코드
  if (state === undefined) {
    return {
      topics: [],
    };
  }

  const newState = { ...state }; // 객체는 불변하기 때문에 복제하여 사용

  return newState; // 변경된 state가 새로운 state가 된다.
}
const store = createStore(
  reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

 

📕 react-redux적용

import { Provider } from "react-redux";

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);
  • Provider 적용

 

📕 필요한 데이터 가져오기 (useEffect 사용)

useEffect(() => {
    fetch("http://localhost:3333/topics")
      .then((type) => type.json())
      .then((result) => {
        // state.topics 을 result의 값으로 변경한다.
        console.log(result);
      });
  }, []);
  • 앱이 실행될 때 딱 한 번만 실행 ⇒ useEffect 사용
  • 컴포넌트 내부적인 변화를 위한 코드는 메인 이펙트
  • 그 외를 사이드 이펙트라고 부른다. ⇒ useEffect에 위치시켜서 코드를 실행시킨다.
    • 예를 들면 서버와 통신해서 데이터를 가져오기
  • npx json-server --port 3333 db.json으로 실행

 

📕 fetch로 가져온 topics를 store에 저장 ⇒ 사용

// 수정하기
import { useDispatch } from "react-redux";

function App() {
  const dispatch = useDispatch();
  // topics 데이터를 1회 가져온다.
    useEffect(() => {
    fetch("http://localhost:3333/topics")
      .then((type) => type.json())
      .then((result) => {
        // state.topics 을 result의 값으로 변경한다.
        console.log(result);
        dispatch({ type: "SET_TOPICS", topics: result });
      });
  }, []);
  return (
    <div>
      <Header></Header>
      <Nav></Nav>
      <Article></Article>
    </div>
  );
}
  • useDispatch import 해주고, const dispatch = useDispatch(); 정의
  • dispatch({ type: "SET_TOPICS", topics: result }); 전달

 

// 리덕스 스토어를 만든다.
function reducer(state, action) {
  // state 변경 코드
  if (state === undefined) {
    return {
      topics: [],
    };
  }
  const newState = { ...state };

  if (action.type === "SET_TOPICS") {
    newState.topics = action.topic;
  }

  return newState;
}
  • reducer함수에서 action.type === "SET_TOPICS"로 store에 저장.

 

📕 store에 저장한 데이터를 보여주기 ⇒ useSelector

import { useSelector } from "react-redux";

function Nav() {
  const topics = useSelector((state) => state.topics);
  return (
    <nav>
      <ul>
        <li>nav</li>
      </ul>
    </nav>
  );
}

export default Nav;
  • useSelector는 state를 가져온다.
  • import { useSelector } from "react-redux";
  • const topics = useSelector((state) => state.topics);
  • useSelector는 선택한 상태만 변경이 되었을 때 해당 함수를 다시 실행해서 리 렌더링 한다.

 

📕 리액트 라우팅 돔 설정하기

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);
  • import { BrowserRouter } from "react-router-dom";
  • <BrowserRouter>로 감싸주기

 

📕 a태그는 <Link to="">로 바꿔주기

import { useSelector } from "react-redux";
import { Link } from "react-router-dom";

function Nav() {
  const topics = useSelector((state) => state.topics);
  let lis = [];
  for (let i = 0; i < topics.length; i++) {
    lis.push(
      <li key={topics[i].id}>
        <Link to={"/read/" + topics[i].id}>{topics[i].title}</Link>
      </li>
    );
  }
  return (
    <nav>
      <ul>{lis}</ul>
    </nav>
  );
}
export default Nav;

 

📕 Route, Routes 설정해주기

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

return (
  <div>
    <Header></Header>
    <Nav></Nav>
    <Article></Article>
    <Routes>
      <Route path="/" element={<article><h1>Welcome</h1>Hello, WEB</article>}></Route>
      <Route path="/read/:id" element={<article><h1>Read</h1></article>}></Route>
    </Routes>
  </div>
);
  • <Routes><Route path="/" element={<App />}></Route></Routes>
  • 이렇게 설정해주면 된다.
  • path는 경로를 적어주고 element로 해당 컴포넌트를 넘겨준다.

 

📕 id값 가져오기 (useParams)

import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";

export function Read() {
  // const params = useParams();
  // cosnt id = params.id
  const { id } = useParams();
  const [topic, setTopic] = useState();

  // id의 값이 바뀔 때 마다 useEffect가 실행.
  useEffect(() => {
    // topics/id 데이터를 가져온다.
    fetch("http://localhost:3333/topics/" + id)
      .then((type) => type.json())
      .then((result) => {
        setTopic(result);
      });
  }, [id]);
  if (topic === undefined) {
    return <>Loading...</>;
  }
  return (
    <article>
      <h1>Read</h1>
    </article>
  );
}
  • import { Route, Routes, useParams } from "react-router-dom";
  • const { id } = useParams();

 

📕 페이지 이동 설정 (useNavigate)

const go = useNavigate();

...
<form
    onSubmit={async (e) => {
    e.preventDefault();
    const newTopic = await postTopic(e);
    go("/read/" + newTopic.id);

    const response = await fetch("http://localhost:3333/topics");
    const topics = await response.json();
    dispatch({ type: "SET_TOPICS", topics: topics });
    }}
>
...

 

📝 리액트 프로젝트 Production으로 바꾸기

npm run build

// 설치
npm install -g serve

// 실행
serve -s build

 

📕 Production level인 경우에만 어떤 메시지를 출력하고 싶다면

// index.js
if (process.env.NODE_ENV !== "production") {
  console.log("현재 Production 빌드로 돌아가고 있어요!");
}
  • 이걸 사용하는 경우는 많지 않지만 이렇게 사용할 수 있다.

 

💡 오늘 깨달은 것

  • 오늘 전체적인 복습을 하니까 리액트의 전체적인 흐름에 대해서 감을 잡기 시작했다!! 역시 반복이 답이다!!
  • 만약 재사용성을 고려한다면 store로 받기보다는 props로 받는 것이 더 나을 수도 있다.
  • Development과 Production의 차이점은 디버깅 기능의 유무이다. 그래서 Development가 느리다.
  • 포트는 한정적인데 여러 개를 돌리고 싶다면? => Proxy Server 사용!!
    • 포트가 막혀있는데 더 필요하다면 리버스 프록시를 이용해서 포트를 다 뚫어 놓을 수 있다.
  • git 문제 상황 시나리오 연습 : Git Exercises
반응형