Python(Flask)+React+SASS+mongoDB로 웹 서비스 제작하기 프로젝트(2-2) – Login Component 만들기(React-Router)

지난 글에서 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에 그려지게
하겠다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다