초반 프로젝트 설정하기React+REST API 게시판 구현/FE - React2021. 9. 26. 09:00
Table of Contents
📝 백엔드 서버 구동하기
- 우선 위 링크로 들어가서 typeORM으로 REST API를 작성한 후 서버를 구동해서 http://localhost:8080에 접속하자.
- 혹은 위 링크에서 프로젝트를 다운받아서 서버를 구동하자.
📝 개발환경
- 프론트 개발환경을 사용하기 위해 노드와 git이 설치되어야 한다!
- https://duckgugong.tistory.com/172
- 위 링크를 참고하여 Node, NVM, git을 설치하자
- 개발툴은 webstorm을 사용한다!
- https://eastflag.co.kr/frontend/webstorm-setup/
- 위 링크를 참고하여 webstorm 관련 환경설정을 해주자!
📝 프로젝트 생성
- 리액트 프로젝트를 만들고 싶은 폴더를 webstorm에서 열고 아래 명령어로 리액트 프로젝트를 생성하자
yarn create react-app board
- 생성한 프로젝트로 이동한 후, yarn start로 프로젝트를 실행시킬 수 있다!
- 프로젝트를 실행시키면 http://localhost:3000 주소로 접속이 되는 것을 확인할 수 있다.
📝 서브 디렉토리 설정
- src 폴더 아래 공통되는 컴포넌트를 정의하는 components 폴더를 생성
- src 폴더 아래 페이지를 구성하는 컴포넌트를 정의하는 pages를 폴더를 생성.
- pages 폴더 안에 페이지를 나타낼 컴포넌트와 scss 파일을 넣어준다!
- src 폴더 아래 jwt 토큰을 redux에서 처리하기 위해 redux 폴더를 생성하자.
📝 라이브러리 설치
- Material UI(CSS 프레임 워크) → 이미 디자인된 button이나 input과 페이지네이션 컴포넌트를 가져다 쓰자!
yarn add @mui/material @emotion/react @emotion/styled @mui/icons-material
- axios → HTTP를 호출할 클라이언트 라이브러리 - REST API 호출
yarn add axios
- scss 적용
yarn add node-sass
- react-router-dom → 라우팅 적용
yarn add react-router-dom
- formik → form 상태 관리를 위한 모듈
yarn add formik
- yup → form의 validation 검증을 위한 모듈
yarn add yup
- react-toasify → 사용자에게 처리 결과를 알려주기 위한 3rd party 라이브러리
yarn add react-toastify
- redux
yarn add redux react-redux
- redux-persist
- 로그인을 성공하면 서버에서 jwt 토큰을 받고 redux store에 저장하고 redux-persist 모듈을 사용해서 local storage나 session storage에 저장해야 한다.
- 페이지를 새로고침 하면 store에 저장된 정보는 모두 날아가기 때문에 local storage나 session storage에 저장하기 위해 redux-persist모듈 사용
yarn add redux-persist
- jwt-decode → jwt를 파싱하는데 도옴을 주는 라이브러리 ex) 토큰을 해독해서 유효성 검사 등등..
yarn add jwt-decode
- http-proxy-middleware → CORS 문제 해결하기 - 프록시 서버를 만들어주는 미들웨어
yarn add http-proxy-middleware
- momment → JavaScript에서 사용되는 날짜관련 라이브러리 중 가장 많이 사용되었던 라이브러리
yarn add momment
📝CORS 해결하기
- src 폴더 아래에 setupProxy.js 파일을 만들고 아래처럼 설정하자!
setupProxy.js
const {createProxyMiddleware} = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
createProxyMiddleware('/api', {
target: 'http://localhost:8080', //접속하려는 서버의 루트 URL
changeOrigin: true,
})
);
};
- 이렇게 하면 로컬 환경에서 /api로 시작하는 URL로 보내는 요청에 대해 브라우저는 http://llocalhost:3000/api로 요청을 보낸 것으로 알고 있지만, 사실 뒤에서 웹팩이 http://localhost:8080으로 요청을 프록싱해주기 때문에 마치 CORS 정책을 지킨 것처럼 브라우저를 속일 수 있다. 즉, 프록싱을 통해 CORS 정책을 우회할 수 있게 된다.
- 따라서 이제 클라이언트에서 아래처럼 HTTP 요청을 보내면
axios.get("/api/add-board")
- 브라우저를 속여 아래처럼 요청을 보낸다!
axios.get("http://localhost:8080/api/add-board")
📝 index.js에 라우팅 설정하기
- 라우팅을 사용하기 위해 BrowserRouter로 App 컴포넌트를 감싸자
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
// antd 적용
import 'antd/dist/antd.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// BrowerRouter 적용
<BrowserRouter>
<App />
</BrowserRouter>
);
reportWebVitals();
📝기본 화면 구성
index.css 파일 수정하기
- 사용할 폰트 import 해오기
- 배경 Header를 상단에 고정해서 사용하기 위해 padding을 rem으로 넣어주자.
- 모든 화면에서 사용할배경 색깔을 지정해주자
- media 쿼리를 이용해서 페이지 최대 넓이마다 다른 rem을 사용할 수 있게 하자
→ 크로스 브라우징
@import url('https://fonts.googleapis.com/css2?family=Pacifico&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap');
@media all and (min-width: 1024px){
html{
font-size: 100%
}
}
@media all and (max-width: 1024px) {
html{
font-size: 85%;
}
}
@media all and (max-width: 768px) {
html {
font-size: 70%;
}
}
@media all and (max-width: 500px) {
html {
font-size: 55%;
}
}
@media all and (max-width: 400px) {
html {
font-size: 45%;
}
}
body {
margin: 0;
padding-top: 10rem;
background-color: rgb(231, 235, 240);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Header 컴포넌트 만들기
- Header 컴포넌트는 모든 컴포넌트에서 공용으로 사용할 컴포넌트이므로 components 파일 아래에 Header.js 파일과 header.scss 파일을 만들자.
- Header 컴포넌트는 단지 페이지를 이동시켜주는 기능을 담당한다!
components/Header.js
import "./header.scss";
import {Link} from "react-router-dom";
const Header = () => {
return (
<div className="header-wrapper">
<div className="header-title">
<Link to="/">
<span>Duckgugong</span>
</Link>
</div>
<div className="header-menu">
<Link to="board-list">게시판</Link>
<Link to="add-board">글쓰기</Link>
<Link to="/login">로그인</Link>
<Link to="/sign-up">회원가입</Link>
</div>
</div>
);
};
export default Header;
- Header 컴포넌트는 스크롤이 아래로 내려가더라도 상단에 항상 고정되고 제일 위에 보이게 하기 위해 display: fixed 값과 z-index 값을 주자.
- 화면이 작아져도 flex 요소들이 아래로 내려가기 하기 위해 flex-wrap 속성을 추가하자
components/header.scss
a {
list-style: none;
margin: 0;
padding: 0;
text-decoration-line: none;
font-weight: bold;
color: black;
&:hover { color: blue; }
}
.header-wrapper {
z-index: 10;
position: fixed;
top: 0;
left: 0;
right: 0;
padding: 1.2rem 4rem;
color: #282c34;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
background-color: snow;
.header-title{
a {
font-size: 3rem;
display: flex;
align-items: center;
font-family: 'Pacifico', cursive;
}
}
.header-menu{
display: flex;
flex-wrap: wrap;
a {
font-size: 1.5rem;
font-family: 'Noto Sans KR', sans-serif;
flex-shrink: 0;
margin: 0 1rem;
}
}
}
Home 컴포넌트 만들기
- pages 디렉토리 아래 home 디렉토리를 만들고 "/" 경로에서 보여줄 Home 컴포넌트 Home.js 파일과 home.scss 파일을 만들자.
pages/home/Home.js
- Home 컴포넌트는 별도의 기능이 존재하지 않고 단지 프로젝트의 설명을 예쁘게 보여주고 내 Tistory와 GitHub로 이동할 수 있게만 한다
import "./home.scss";
const Home = () => {
return (
<div className="home-wrapper">
<div className="home-title">
<span>Duckgugong</span>에 오신걸 환영합니다
</div>
<div className="home-contents">
자유롭게 게시판에 글을 작성하고📝<br/>
댓글로 여러 의견을 나눠보세요✏️
</div>
<div className="about-project">
이 프로젝트는 Duckgugong이 레퍼런스로 쓰기위해<br/>
<span>React</span>와
<span> TypeORM</span>으로 만들었습니다😎
</div>
<div className="my-website">
<div className="my-website-title">Duckgugong's Website</div>
<a href="https://github.com/ejzl521/Board-FE-React" target="_blank">
🏴GitHub
</a>
<a href="https://duckgugong.tistory.com/" target="_blank">
📖 Tistory
</a>
</div>
</div>
)
}
export default Home;
pages/home/home.scss
- Home 컴포넌트 안의 내용물들이 하나씩 Fade-in하는 효과를 주기 위해 keyframes와 opacity, animation, animation-delay를 적절하게 섞어썼다.
- 각 요소의 처음 opacity를 0으로 두고 animation의 forwards 속성을 사용하면 초반에 안보이던 요소가 animation이 끝나면 보이게 해준다.
- animation-delay 요소는 각 요소별로 animaition이 시작할 시간을 정해준다.
@keyframes smoothAppear {
from {
opacity: 0;
transform: translate3d(0, -100%, 0);
}
to {
opacity: 1;
transform: translateZ(0);
}
}
.home-wrapper{
padding: 5rem 0;
display: flex;
flex-direction: column;
align-items: center;
font-family: 'Noto Sans KR', sans-serif;
.home-title{
opacity: 0;
animation: smoothAppear 1s forwards;
animation-delay: 0.5s;
margin: 15px 0;
font-size: 2.4rem;
font-weight: bold;
color: midnightblue;
span{
font-size: 2.7rem;
font-family: 'Pacifico', cursive;
}
}
.home-contents{
opacity: 0;
animation: smoothAppear 1s forwards;
animation-delay: 1s;
margin: 15px 0;
font-size: 1.5rem;
color: #282c34;
}
.about-project{
opacity: 0;
animation: smoothAppear 1s forwards;
animation-delay: 1.5s;
margin: 15px 0;
font-size: 1.5rem;
color: #282c34;
text-align: center;
span{
font-size: 1.8rem;
font-weight: bold;
color: blue;
}
}
.my-website{
opacity: 0;
animation: smoothAppear 1s forwards;
animation-delay: 2.0s;
margin: 15px 0;
text-align: center;
.my-website-title{
margin-bottom: 5px;
font-size: 1.8rem;
font-weight: bold;
color: midnightblue;
}
a{
font-size: 1.5rem;
margin: 0 10px;
}
}
}
App.js 구성하기
App.js
- App.js 파일에 모든 컴포넌트에서 위에서 작성했던 모든 컴포넌트에서 사용할 Header 컴포넌트와 Route로 홈 화면을 추가하자
import React from "react";
import {Routes, Route} from "react-router-dom"
import Header from "./components/Header";
import Home from "./pages/home/Home";
const App = () => {
return (
<React.Fragment>
<Header/>
<Routes>
<Route path="/" element={<Home/>}/>
</Routes>
</React.Fragment>
)
}
export default App
- App.js에 적절히 컴포넌트를 배치하면 기본 화면 구성은 아래처럼 나름 예쁘게 나온다 😎
'React+REST API 게시판 구현 > FE - React' 카테고리의 다른 글
게시물 등록하기 페이지 구현 (0) | 2021.10.11 |
---|---|
axios interceptor 구현하기 (0) | 2021.10.04 |
인증 처리하기+PrivateRoute+로그아웃 (0) | 2021.10.04 |
로그인 구현 (redux-persist) (0) | 2021.10.02 |
회원가입 구현하기 (0) | 2021.09.29 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!