-
Python(Flask)+React+SASS+mongoDB로 웹 서비스 제작하기 프로젝트(2-2) – Login Component 만들기(React-Router)Node 2021. 4. 27. 19:41
지난 글에서 Login, Join component 를 만들었고 구조를 설명했듯
접속시 회원가입 컴포넌트를 보여주고 로그인을 하기 위해 로그인
버튼을 누르면 로그인 컴포넌트로 전환시켜줄 것이다.React-Router
react는 SPA를 만들기에 정말 좋은 JavaScript 라이브러리. 변화하는 데이터를 빠르게 View로 보여주기 위해 가상 DOM에 View에 그려져야 할 부분이 있는지를 분류하고
다른 부분이 있다면 기존의 DOM을 날려버리고 새롭게 DOM을 re-rendering하는
조금은 괴팍하고 강력한 친구… 하지만 이런 React는 가볍고 빠르게 하기 위해
그리고 본연의 기능에 충실하기 위해 최소한의 기능만 가지고 있고 추가적으로
필요한 라이브러리를 설치해서 사용할 수 있는 구조이다. 그 중 하나가 React-Router!React에는 URL이 변화함에 따라 다른 View를 보여주는 route 기능이 없다.
따라서 React-Router를 이용해 변화하는 URL값을 이용해 Join, Login 컴포넌트를
전환시켜 줄 것이다.먼저 react-router 를 설치하자!
$ yarn add react-router-dom
컴포넌트 수정 전에 디렉토리 구조를 어느정도 손봐주자
간단하게 설명하면 client는 최종적으로 우리가 만들 SPA를 담아둘 곳 public/index.html에 그려질 놈이 들어간다고 생각하면 된다.
componens 는 필요한 컴포넌트들이 들어가는 곳
pages는 각 URL에 따라 보여질 view들이 들어가는 곳
shated는 Root.js에 URL의 변화에 맞춰 페이지를 Switch 시켜주는 곳
style은 말 그대로 스타일을 몰아두는 곳이다.왜 이런 구조로 했는지 이해가 잘 되지 않을 수 있으나 글을 마져 읽어보면 납득이 될수도…
먼저 Root.js 작성
import React from 'react'; import { BrowserRouter } from 'react-router-dom'; import App from 'shared/App'; const Root = () => ( <BrowserRouter> <App /> </BrowserRouter> ); export default Root;
이 컴포넌트는 BrowserRouter를 적용한다. velopert님의 글을 보고 구조를 어느정도 짜놨는데 이 컴포넌트는 나중에 리덕스를 적용 하게 될 때, 여기서 Provider 를 통하여 프로젝트에 리덕스를 연결시켜 줄 수 있다 한다. 리덕스를 사용하지 않을 것이라고 했지만 전에 얘기했듯 뭔가 쓰게 될 것 같아서 그대로 따라했다.
shared/app.js 작성
import React, { Component } from 'react'; import { Route, Switch } from 'react-router-dom'; import { Home, Main } from 'pages'; import Menu from 'components/Menu'; class App extends Component { render() { return( <div> <Menu /> <Route exact path="/" component={Home} /> <Switch> <Route path="/main/:name" component={Main} /> <Route path="/main" component={Main} /> </Switch> </div> ); } } export default App;
import 한 것들 중 경로가 조금 이상할 수 있는 것들이 있는데 이는 ‘src/’를 포함해서 생각하면 된다. cross-env 를 사용해서 환경변수 설정을 해놔서 그렇다.
특히나 3번라인은 Home과 Main을 한번에 가져오는데 이는 ‘src/pages/index.js’에
설정을 해서 그렇다 바로 확인하자.
그리고 여기까지 작성하면 path에 따라서 각 컴포넌트가 URL에 따라서 다르게 렌더링 된다. 하지만 컴포넌트 작성을 안했음.
Switch를 쓰면 매칭되는 컴포넌트 중 하나만 보여줌 만약 Switch로 /main과 /main:을
묶지 않는다면 hostaddress/main?login 으로 접속하게 되면 로그인 컴포넌트와 회원가입 컴포넌트 둘 다 보여지게 될 것!src/pages/index.js 작성
export { default as Home } from './Home'; export { default as Main } from './Main';
간단하다. 근데 사실 이 부분에 확신이 없다. 해보고 문제있으면 댓글바람
pages/main 작성
import React, { Component } from 'react'; import Join from 'components/Join'; import Login from 'components/Login'; import queryString from "query-string"; import 'style/Main.scss'; import leftImg from '/home/linesys/OLLOC/src/img/main.png' class Main extends Component { // address/main/detail=login이면 false 아니면 true loginsplit = (query) => { if(query === 'login') return false; else return true; } render() { const {location} = this.props; // 현재 경로 정보를 가져옴 const query = queryString.parse(location.search); // URL중 쿼리 부분만 가져옴 const detail = this.loginsplit(query.detail); // 쿼리 정보에 따른 반환값을 가져옴 return ( <div id = "main"> <img src={leftImg} alt="이미지"/> {// 쿼리 정보에 따른 값을 가져온 것이 true이면 회원가입 false이면 로그인 컴포넌트를 보여줌 detail ? <Join/> : <Login/> } </div> ); }; } export default Main;
라우트로 설정한 컴포넌트는, 3가지의 props 를 전달받는다.
- history 이 객체를 통해 push, replace 를 통해 다른 경로로 이동하거나 앞 뒤 페이지로 전환이 가능.
- location 이 객체는 현재 경로에 대한 정보를 지니고 있고 URL 쿼리 (/main/?detail=login 형식) 정보도 포함되어 있다.
- match 이 객체에는 어떤 라우트에 매칭이 되었는지에 대한 정보가 있고 params (/main/:test 형식) 정보를 가지고있음.
난 이 중 쿼리를 이용해 회원가입/로그인 창을 전환할 것임.
여기까지 하면
components/Join.js 수정
import React, {Component} from "react"; import { Link } from 'react-router-dom'; class Join extends Component{ render(){ return( <div id ="join"> <form id="loginForm"> <h1>OLLoc</h1> <span className="loginText">친구들의 지도에 그려진 사진과 글을 보려면 가입하세요</span> <button className="mainBtn">facebook으로 로그인</button> <div id="line">또는</div> <input className="textInput" placeholder="휴대폰 번호 또는 이메일 주소" name="mail" /> <input className="textInput" placeholder="성명" name="name" /> <input className="textInput" placeholder="사용자 이름" name="userName" /> <input className="textInput" placeholder="비밀번호" name="passWord" /> <button className="mainBtn">가입</button> <span className="loginText">가입하면 OLLoc의 약관, 데이터 정책 및 쿠키 정책에 동의하게 됩니다.</span> </form> <div id="checkMem" className={this.state.animation}> 계정이 있으신가요? <Link to="/main?detail=login"로그인</Link> </div> </div> ); } } export default Join;
하단에 계정이 있으신가요? 로그인 에서 로그인을 누르면 새로고침 없이 컴포넌트가 join -> login으로 전환되는 것을 확인할 수 있다!
components/menu 작성…
깜빡할 뻔 했다. 개발 단계에서 편안하게 로그인 전과 로그인 후 페이지를 개발하기 위해 menu navigation을 만들었다.
import React from 'react'; import { Link } from 'react-router-dom'; const Menu = () => { return ( <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/main">Login</Link></li> </ul> <hr/> </div> ); }; export default Menu;
간단하다 아 이거 보니까 Home을 또 뭘로 할지 설정을 안해줬던게 생각나서
마지막으로 pages/Home.js를 작성하자..
import React from 'react' import Map from 'components/Map' const Home = () => { return ( <div> <Map></Map> <h2> 홈 </h2> </div> ) }; export default Home;
이게 홈(localhost:3000 or your domain address)으로 접속했을 때 ‘src/shared/App.js’를 통해 ‘src/client/Root.js’에 그려지고 ‘public/index.html’의 <root></root>에 최종적으로 그려질 돔이다 근데.. index.html을 설정 안해줬구나.
진짜 마지막 public/index.html 수정
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <script src="https://use.fontawesome.com/releases/v5.2.0/js/all.js"></script> <title>OLLOC</title> </head> <body style="background-color: #FAFAFA"> <div id="root"></div> </body> </html>
script를 불러온건 후에 아이콘 사용을 위해 font-awesome을 로드했다.
다음엔 애니매이션을 적용시켜 새롭게 DOM이 그려질 때 예쁘게 View에 그려지게
하겠다.'Node' 카테고리의 다른 글