ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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에 그려지게
    하겠다.

Designed by Tistory.