국비교육(22-23)

47일차(2)/React(13) : SPA(Single Page Application) 예제

서리/Seori 2022. 12. 13. 23:38

47일차(2)/React(13) : SPA(Single Page Application) 예제

 

- react-router-dom 기능 사용하기 (NavLink, Route, withRouter)

- 컴포넌트의 property 로 제공되는 location, match, history 사용하기

- queryString 기능 사용하기 

 

 

- React로 웹페이지 전체를 만들면(SPA) 응답 방식도 전부 바뀐다.

 전체 페이지가 달라지지 않으므로(페이지 이동 X) json으로만 응답하게 된다.

 

 

- spa_app 새 리액트 앱 생성

(.css 등 필요없는 파일은 지우기)

 

App.js

import { NavLink, Route, withRouter } from "react-router-dom";
import { Home, Study, Game, Buy } from "./pages";

function App({location, match, history}) {

  //active 되었을때 어떤 css를 적용할지 미리 정한 다음 적용시킬 수 있다.
  const activeStyle = {
    color:"red",
    fontWeight:"bold"
  }

  return (
    <div className="App">
      <h1>React Router</h1>
      <button onClick={()=>{
        //함수의 인자로 전달받은 history객체의 push함수를 이용해서 이동할 수 있다.
        history.push("/study");
      }}>공부하러 가기</button>
      
      <ul>
        <li><NavLink activeStyle={activeStyle} to="/">home</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/study">study</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/game">game 홈</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/game/starcraft">game starcraft</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/game/mario">game mario</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/buy?code=1&name=handphone">1번 상품구매</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/buy?code=2&name=water">2번 상품구매</NavLink></li>
        <li><NavLink activeStyle={activeStyle} to="/buy?code=3&name=coffee">3번 상품구매</NavLink></li>

      </ul>
      <Route exact path="/" component={Home}/>
      <Route exact path="/study" component={Study}/>
      <Route exact path="/game" component={Game}/>
      {/* name 이라는 이름의 경로 파라미터를 읽을 수 있도록 설정 */}      
      <Route path="/game/:name" component={Game}/>
      <Route path="/buy" component={Buy}/>
    </div>
  );
}

//withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.
export default withRouter(App);

 

- 어떤 링크를 누르면 이 아래쪽 빨간 박스에 해당 컨텐츠만 나오도록 하려고 한다.

 

- 기존의 페이지 전환 방식은 home.jsp 등으로 페이지 이동이 일어난다. 다른 경로를 가진 페이지가 처음부터 로딩된다.

 

- 이번에는 페이지를 이동하지 않는 링크를 만들고자 한다!

- 페이지의 일부만 수정해서 누르는 링크에 맞는 컨텐츠를 아래 보여주는 방식으로 한다.

 

 

 

- npmjs.com에서 검색. react-router-dom 을 설치해서 사용할 예정이다.

 

- 위와 같이 json 폴더에 입력하는 것만으로도 설치할 수 있다.

 

- 설치하려는 이름을 입력하고 npm install 하면

 자동으로 package.json의 dependencies를 찾아서 이중에서 설치되지 않은 것을 설치해준다.

 

- 12개의 패키지가 설치되었다고 나온다!

- 다시 한 번 npm install 하면 up to date라고 나온다. 현재 dependencies에 있는 모듈들이 다 설치되어 있다는 뜻!

 

 

- src에 root.js 파일 생성

//root.js

import { BrowserRouter } from "react-router-dom";
import App from "./App";

const Root = () => {
    return(
        <BrowserRouter>
            <App />
        </BrowserRouter>
    );
}

//App을 감싼 BrowserRouter를 렌더링해주는 Root component 리턴해주기
export default Root

 

- 이제 브라우저 라우터를 쓸 수 있다. Root에서 import하기

 

<BrowserRouter>
    <App />
</BrowserRouter>

- return 안에 위 코드를 작성해준다.

 

- App을 BrowserRouter로 감싸서 리턴해준다고 생각하면 된다.

 

- index.js도 App에서 Root로 바꿔주기

 

 

- App 함수에 obj 변수를 넣으면 object 가 하나 전달되는 것을 확인할 수 있다.

 

- NavLink import 해주기

- NavLink도 react-router-dom 에 들어 있다.

 

 

- 클릭해도 페이지가 바뀌지는 않지만, 주소창의 경로가 달라지는 것을 볼 수 있다.

 

- console창을 확인해보면 <a> anchor로 바뀌어 있는 것을 볼 수 있다.

 

- navLink는 javascript가 동작하는 링크로 달라진다는 것을 알 수 있다.

 


 

src 안에 pages 폴더 - 안에 Home.js / Game.js / Study.js 만들어주기

 

 

Home.js

// pages/Home.js

const Home = ()=>{

    const homeStyle={
        backgroundColor:"pink",
        height:"300px"
    };

    return(
        <div style={homeStyle}>
            <h3>home 페이지 입니다.</h3>
            <p>어쩌구 저쩌구...</p>
        </div>
    );
}

export default Home;

Study.js

// pages/Study.js

import { NavLink } from "react-router-dom";

const Study = ()=>{

    const studyStyle={
        backgroundColor:"yellow",
        height:"300px"
    };

    return(
        <div style={studyStyle}>
            <h3>study 페이지 입니다.</h3>
            <p>어쩌구 저쩌구...</p>
            <NavLink to="/">홈으로</NavLink>
        </div>
    );
}

export default Study;

Game.js

// pages/Game.js

const Game = ({match})=>{

    const gameStyle={
        backgroundColor:"green",
        height:"300px"
    };

    // "/game/:name" 의 name을 읽어오기
    let gameName=match.params.name; //경로 파라미터
    if(!gameName){
        gameName="기본";
    }

    return(
        <div style={gameStyle}>
            <h3>game 페이지 입니다.</h3>
            <p><strong>{gameName}</strong> 게임을 시작합니다.</p>
        </div>
    );
}

export default Game;

 

- 현재 pages 폴더 안에 여러 개의 파일이 들어가 있으므로,

 해당 폴더를 폴더째로 import하고, 그 안의 특정요소를 export해서 편리하게 사용할 수 있도록 한다!

 

- 이 통합파일의 이름은 정해져 있다. index.js (소문자로 시작) - 최종본

// pages/index.js

//pages 폴더를 import 해서 Home, Study, Game, Buy 을 모두 사용할 수 있도록 설정
export { default as Home } from './Home';
export { default as Study } from './Study';
export { default as Game } from './Game';
export { default as Buy } from './Buy';

 

import { Home, Study, Game } from "./pages";

import{ 파일명1, 파일명2, 파일명3 } from "/폴더명(경로)";

- 그리고 App.js에 위와 같이 import 해주면 된다.

- 폴더명 하나로 전체 import 가능!

 

- 페이지 주소(경로)는 달라지지만 그렇게 보이지 않는다.

- 전체를 새로고침하는 것 같은 변화가 없다. 해당 부분만 달라진다.

 

- 각각의 컴포넌트에서 각각의 ui, 동작, 함수 등을 가질 수 있다.

- 이전에는 <a>로 페이지를 이동했지만 이렇게 하면 UI는 달라지지만 컨텐츠만 바뀌고 페이지 이동은 일어나지 않는다.

 

- 링크 클릭시 지정한 component로 change되는 것이다.

 

- 만약 글 목록보기(DB) 등이 필요한 경우 페이지 전환 없이, 서버에 ajax 요청을 통해서 가지고 온다.

 

- 이렇게 만드는 것이 Single Page Application이다.

 


 

<ul>
    <li><NavLink activeStyle={activeStyle} to="/">home</NavLink></li>
    <li><NavLink activeStyle={activeStyle} to="/study">study</NavLink></li>
    <li><NavLink activeStyle={activeStyle} to="/game">game</NavLink></li>
</ul>

< NaviLink activeStyle={ style명 } > 설정

- active 효과를 주는 class를 부여하는 것과 같이,

 active 되었을때 어떤 css를 적용할지 미리 정한 다음 적용시킬 수 있다

 

- 해당 페이지가 active 되었을 때 폰트에 수정된 스타일이 적용된다.

 


 

- withRouter 적용하기 (import)

 

//withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.
export default withRouter(App);

export default withRouter(컴포넌트명);

- withRouter() 함수를 호출해서 export 해주면 Router에 관련된 props가 이 컴포넌트에 전달된다.

 

- 위에서 매개변수에 전달된 obj값을 콘솔에서 확인하기!

 

- object가 전달되고, history, location, match 라는 방 이름이 있다.

- 이것을 사용하려면 obj.history 형태로 사용하면 된다.

- 구조분해 할당으로 받아서 사용할 수도 있다.

 

- 이 object가 여기로 전달되는 것이다.

 

function App({location, match, history}) { }

- obj의 history, location, match 방 안에 들어있는 {...} 값을 저 { , , } 안에다가 각각 할당하는 것

 

<li><NavLink activeStyle={activeStyle} to="/game">game 홈</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/starcraft">game starcraft</NavLink></li>
<li><NavLink activeStyle={activeStyle} to="/game/mario">game mario</NavLink></li>

- NavLink 추가해줌. 하위 경로가 생겨난다. 페이지 변화는 없지만(새로고침 X) 해당 경로로 이동한다.

 

- game 컴포넌트에서 to="" 를 읽어와서 여기에 있는 내용을 사용할 수 있다.

 

 

game.js 수정하기

 

const Game = ({match})=>{ }

 

let gameName=match.params.name;

- match만 구조분해할당 해주고 경로를 읽어오는 gameName 변수 추가

- match.params.name; 으로 읽어오는 이것을 경로 파라미터라고 부른다.

 

<Route path="/game/:name" component={Game}/>

- App.js에 위 내용을 추가해준다. 

- name 을 component로부터 읽어내서 뒤의 주소로 이동(페이지이동x) 하게 한다.

 

- 특정 경로(game) 내의 주소가 바뀌면 아래 보이는 텍스트(게임 이름)도 달라진다.

- param으로 읽어온 값이 보여주는 UI인 것!

 


 

buy.js 생성. 구매 페이지

// pages/buy.js

import queryString from "query-string";

const Buy = ({location})=>{
    //location을 구조분해 할당 받아서 search 라는 방에 있는 문자열 확인하기
    console.log(location.search);

    //queryString 함수를 이용해서 query 문자열을 파싱해서 object 얻어내기
    const parsed=queryString.parse(location.search);
    console.log(parsed);

    const buyStyle={
        backgroundColor:"#cecece",
        height:"300px"
    };

    return(
        <div style={buyStyle}>
            <h3>Buy 페이지 입니다.</h3>
            <p>
                <strong>{parsed.code}</strong>번 상품 
                <strong> {parsed.name}</strong>을 주문 하였습니다.
            </p>
        </div>
    );
}

export default Buy;

 

const Buy = ({location})=>{ }

- location 을 구조분해로 할당받는다.

 

- index.jsp에 새로 생성한 buy도 빼내주기

 

console.log(location.search);

- 콘솔창에 구매하는 내용이 기록된다.

- 이 중에서 code와 name 값만 뽑아내서 분리하려면?

 

- npm에서 install하기

query-string : 위와 같은 쿼리 문자열에서 필요한 내용을 추출하는 도구

 

 

- 사용방법: import해서 parse하면서 location.search 에서 읽어온 값을 사용한다.

- object 형태로 추출되므로 . 점 찍어서 빼내서 사용할 수 있다.

 

- 설치

 

const parsed=queryString.parse(location.search);

- parse 기능으로 담아서 사용하기

 

- 위와 같은 값을 읽어서 {} 안에 넣으면 아래와 같이 만들어준다!!

- 방을 분리해서 object의 형식에 넣어준다.

 

- query string을 사용한 값을 읽어와서 화면에 이렇게도 표시할 수 있다.

 

- 이 값(패러미터)을 읽어와서 페이지의 일부 내용을 변화시킬 수 있는 것.

 

- 이클립스로 만들었던 게시판의 글 자세히 보기(detail) 등의 기능에서도 해당 내용을 적용 가능하다.

 

* in jsp page

/cafe/detail.jsp?num=1

→ num=1이 주소인 페이지로 페이지가 바뀌면서 request.getParameter("num") 으로 읽어와서 처리했음

 

* in React js

/cafe/1 또는 /cafe/detail?num=1

 페이지 전환 없이 일부만 바꾸어 보여주는 처리들을 할 수 있다.

 

 


 

- study.js로 바로 이동하는 버튼 생성

- history를 사용해 버튼 클릭시 특정 페이지로 이동시키기

 

- 라우터의 history.push() 를 사용해서 특정 경로로 이동할 수도 있다.

 

- 기존 javascript 의 location.href=" "; 와 같은 기능

 

 

- study 페이지에 돌아오는 링크 추가

 <NavLink to="/">홈으로</NavLink>

- study.js 페이지에서 navLink 사용해서 홈으로 이동하기

 

 

- 위와 같이 SPA를 사용하면 페이지 전환 없이도 특정 어플리케이션을 생성할 수 있다.