DEVELOP
article thumbnail

인프런 이정한님의 한입크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 ] 강의 수강 후 강의의 내용을 정리하며 공부한 것을 쓴 게시글입니다.

 

한입 크기로 잘라 먹는 리액트(React.js) : 기초부터 실전까지 - 인프런 | 강의

개념부터 독특한 프로젝트까지 함께 다뤄보며 자바스크립트와 리액트를 이 강의로 한 번에 끝내요. 학습은 짧게, 응용은 길게 17시간 분량의 All-in-one 강의!, - 강의 소개 | 인프런...

www.inflearn.com


1. 페이지 라우팅 0 - React SPA & CSR 

# 라우팅 

: 어떤 네트워크 내에서 통신 데이터를 보낼 경로를 선택하는 일련의 과정 

- 경로를 정해주는 행위 자체 

 

# 페이지 라우팅 

: 요청에 명시되어 있는 경로에 따라 알맞은 페이지를 선택하게 하는 과정 자체 

- 웹 서버가 처리 

 

# MPA (Multipage Application)

: 여러 개의 페이지를 준비해놨다가 요청이 들어오면 요청에 맞는 페이지를 응답해주는 방식 

 

# SPA (Single Page Application)

: 서버로부터 새로운 페이지를 불러오지 않고 현재의 페이지를 동적으로 다시 작성하는 방식 

- 페이지 전환이 빠름 

 

# CSR (Client Side Rendering) 

: 클라이언트 측에서 렌더링을 진행


2. 페이지 라우팅 1 - React Router 기본

# REACT ROUTER V6

 : REACT에서 CSR기반의 페이지 라우팅을 할 수 있게 해주는 라이브러리

 

- react-router 모듈 사용 : 

<shell />
npm install react-router-dom@6

- pages 폴더에  Home.js , Edit.js , New.js , Diary.js 파일 생성

- 라우팅을 test하기 위한 RouertTest 컴포넌트 작성

    - a태그를 사용하지 않고 Link 태그 사용 

    - 링크는 to 키워드로 연결 

<javascript />
import { Link } from "react-router-dom"; const RouterTest = () => { return ( <div> <Link to={"/"}>HOME</Link> <br /> <Link to={"/new"}>NEW</Link> <br /> <Link to={"/diary"}>DIARY</Link> <br /> <Link to={"/edit"}>EDIT</Link> </div> ); }; export default RouterTest;

- BrowserRouter, Route, Routes import 

<javascript />
import { BrowserRouter, Route, Routes } from "react-router-dom";

- Routes 태그 안에 Route 태그들을 작성하며 path 안에 경로를 적고, elenent 안에 컴포넌트들을 넣음 

- Routes 태그 밖은 어떤 페이지에서도 동일하게 유지되는 코드 

<javascript />
function App() { return ( <BrowserRouter> <div className="App"> <h2>App.js</h2> <Routes> <Route path="/" element={<Home />} /> <Route path="/new" element={<New />} /> <Route path="/edit" element={<Edit />} /> <Route path="/diary" element={<Diary />} /> </Routes> <RouterTest /> </div> </BrowserRouter> ); }


3. 페이지 라우팅 - React Router 응용 

# React Router Dom의 유용한 기능 

  1. Path Variable - useParams
  2. Query String - useSearchParams
  3. Page Moving - useNavigate

3.1. useParams 사용하기 

  - App.js 에서 Routh 의 path 수정

<javascript />
<Route path="/diary/:id" element={<Diary />} />

  - Diary 컴포넌트에서 id값 전달받기 

<javascript />
import { useParams } from "react-router-dom";
<javascript />
const { id } = useParams(); console.log(id);

-> http://localhost:3000/diary/123 접속하면 콘솔 창에 123 출력됨 

 

3.2. useSerachParams 사용하기

- Edit 컴포넌트에서 

<javascript />
import { useSearchParams } from "react-router-dom";
<javascript />
const Edit = () => { const [searchParams, setSearchParams] = useSearchParams(); const id = searchParams.get("id"); console.log(id); const mode = searchParams.get("mode"); console.log(mode); return ( <div> <h1>Edit</h1> <p>이곳은 일기 수정 페이지입니다.</p> <button onClick={() => setSearchParams({ who: "choi" })}> QS 바꾸기 </button> </div> ); };

-> http://localhost:3000/edit/?id=123&mode=dark 접속하면 콘솔창에 123 과 dark가 출력됨

-> QS바꾸기 버튼 클릭하면 setSearchParams가 되므로, 링크가 http://localhost:3000/edit/?who=choi 로 바뀜

 

3.3. useNavigate 사용하기 

- 링크 태그를 클릭하지 않아도 의도적으로 링크 바꾸기 가능

- Edit 컴포넌트에서 navigate하기

- 이전 페이지 이동 시 navigate(-1) 해줄 것 

<javascript />
import { useNavigate } from "react-router-dom";
<javascript />
const navigate = useNavigate();
<javascript />
<button onClick={() => { navigate("/new");}}>NEW로 가기</button> <button onClick={() => { navigate(-1);}}>뒤로 가기</button>

-> New로가기 버튼 클릭 시 New 컴포넌트로 이동함

-> 뒤로가기 버튼 클릭 시 이전 페이지로 이동함


4. 프로젝트 기초 공사 1

4.1. 폰트 세팅

- 구글 폰트 (https://fonts.google.com/ )에서 원하는 폰트 선택 

- import 코드를 붙여넣기 

- font-family로 사용가능 

<css />
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR&family=Nanum+Myeongjo&display=swap"); body { font-family: "Nanum Myeongjo", serif; }

4.2. 레이아웃 세팅

- 화면 너비가 650px일때는 App 컴포넌트 너비를 640px로 하고, 화면 너비가 650px이하일때는 App 컴포넌트 너비를 90vw(view width)로 함 

<css />
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+KR&family=Nanum+Myeongjo&display=swap"); body { background-color: lightslategray; display: flex; justify-content: center; /*가로축 기준 중앙 배치*/ align-items: center; font-family: "Nanum Myeongjo", serif; min-height: 100vh; /*vh=view height*/ margin: 0px; } /*650px 이상일때*/ @media (min-width: 650px) { .App { width: 640px; } } /*650px 이하일때*/ @media (max-width: 650px) { .App { width: 90vw; } } #root { background-color: lightsteelblue; box-shadow: rgba(165, 165, 255, 0.2) 0px 7px 29px 0px; } .App { min-height: 100vh; padding-left: 20px; padding-right: 20px; }

4.3. 이미지 에셋 세팅

- 강의자료의 emotion 이미지 다운로드해 public-assets에 넣기 

- process.enc.PUBLIC_URL 을 하면 어떤 위치애 있던 public 폴더에 접근 가능 

<html />
<img src={process.env.PUBLIC_URL + "/assets/emotion1.png"} /> <img src={process.env.PUBLIC_URL + "/assets/emotion2.png"} /> <img src={process.env.PUBLIC_URL + "/assets/emotion3.png"} /> <img src={process.env.PUBLIC_URL + "/assets/emotion4.png"} /> <img src={process.env.PUBLIC_URL + "/assets/emotion5.png"} />

4.4. 공통 컴포넌트 세팅 

- 모든 페이지에 공통으로 사용되는 버튼, 헤더 컴포넌트 세팅 

 

4.4.1. 버튼 세팅 

- MyButton 컴포넌트 생성 

- type에 따라 버튼의 색을 다르게 처리

- 만약 type에 positive 혹은 negative 외에 다른 것이 들어오면 default 로 바꿈 

- className을 여러개 쓸 때에는 배열로 전달 후 join 해줄것 

<javascript />
const MyButton = ({ text, type, onClick }) => { const btnType = ["positive", "negative"].includes(type) ? type : "default"; return ( <button className={["MyButton", `MyButton_${btnType}`].join(" ")} onClick={onClick} > {text} </button> ); }; MyButton.defaultProps = { type: "default", }; export default MyButton;
<css />
/* MyButton */ .MyButton { cursor: pointer; border: none; border-radius: 5px; padding: 10px 20px 10px 20px; font-size: 18px; white-space: nowrap; font-family: "Nanum Myeongjo", serif; } .MyButton_default { background-color: lightgray; color: black; } .MyButton_positive { background-color: lightseagreen; color: white; } .MyButton_negative { background-color: lightcoral; color: white; }

className에 따라 style 다르게 지정

4.4.2. 헤더 세팅

- MyHeader 컴포넌트 생성 

- 가운데 text , 왼쪽자식, 오른쪽 자식으로 이루어짐 

- 왼쪽자식, 오른쪽 자식에는 각각 버튼이 오거나 텍스트가 오거나 아무것도 없을수도 있음 

<javascript />
const MyHeader = ({ headText, leftChild, rightChild }) => { return ( <header> <div className="head_btn_left">{leftChild}</div> <div className="head_text">{headText}</div> <div className="head_btn_right">{rightChild}</div> </header> ); }; export default MyHeader;
<css />
/* Header */ header { padding-top: 20px; padding-bottom: 20px; display: flex; align-items: center; border-bottom: 1px solid lightcyan; } header > div { display: flex; } header .head_text { width: 50%; font-size: 25px; justify-content: center; } header .head_btn_left { width: 25%; justify-content: start; } header .head_btn_right { width: 25%; justify-content: end; }
<javascript />
<MyHeader headText={"Diary"} leftChild={ <MyButton text={"왼쪽 버튼"} onClick={() => alert("왼쪽 클릭")} /> } rightChild={ <MyButton text={"오른쪽 버튼"} onClick={() => alert("오른쪽 클릭")} /> } />

헤더 예시


5. 프로젝트 기초공사2

<javascript />
const onCreate = (date, content, emotion) => { dispatch({ type: "CREATE", data: { id: dataId.current, date: new moment(date).format("YYYY-MM-DDTHH:mm"), content, emotion, }, }); dataId.current++; }; const onRemove = (targetId) => { dispatch({ type: "REMOVE", targetId }); }; const onEdit = (targetId, date, content, emotion) => { dispatch({ type: "EDIT", data: { id: targetId, date: new moment(date).format("YYYY-MM-DDTHH:mm"), content, emotion, }, }); };

 

profile

DEVELOP

@JUNGY00N