wintertreey 님의 블로그

라우터 Router 본문

프론트엔드/React

라우터 Router

wintertreey 2024. 8. 1. 09:24

라우터란?

사용자가 요청한 URL에 따라 해당 URL에 맞는 페이지를 보여주는 것이라고 생각하면 된다. 

리액트에서는 라우팅 관련 라이브러리가 많은데, 이중 가장 많이 쓰이는 React Router 활용.

 

리액트는SPA SinglePageApplication 방식

 - 기존 웹 페이지 처럼MPA 여러 개의 페이지를 사용, 새 페이지를 로드하는 방식이 아니다.

 - 새 페이지를 로드 하지 않고 하나의 페이지 안에서 필요한 데이터만 가져오는 형태를 가진다.

React-Router는 신규 페이지를 불러오지 않는 상황에서 각각의 url에 따라 선택된 데이터를 하나의 페이지에서 렌더링 해주는 라이브러리라고 할 수 있다.

 

라우터를 사용하기 전에 설치해줘야한다. 터미널에서 다음과 같이 명령문을 적어주자.

npm install react-router-dom 

 

 

 


 

App.js

import React from "react";
import {BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";

import MyTest from "./exam/Test";
import HiAbout from "./exam/About";
import Counter from "./exam/Counter";
import Input1 from "./exam/Input1";
import Input2 from "./exam/Input2";
import Multidata from "./exam/Multidata";
import MyAjax from "./exam/MyAjax";

function App() {
  return (
    <Router>
    <div className="App">
     <h2>라우트 연습용 메인 화면</h2>
    <MyTest/>
    <hr/>
    {/* 메뉴 작성 : 라우팅 연습*/}
    <nav>
     
      <Link to="/">Test 화면</Link> | 
      <Link to="/about">About 보기</Link> | 
      <Link to="/kkount">친구추가및삭제</Link> | 
      <Link to="/input1">자료입력1</Link> | 
      <Link to="/input2">자료입력2</Link> | 
      <Link to="/multi">배열자료</Link> | 
      <Link to="/ajax">Ajax 요청</Link>
    </nav> 
      <Routes>
      <Route path="/" element={<MyTest/>}></Route>
      <Route path="/about" element={<HiAbout/>}></Route>
      <Route path="/kkount" element={<Counter/>}></Route>
      <Route path="/input1" element={<Input1/>}></Route>
      <Route path="/input2" element={<Input2/>}></Route>
      <Route path="/multi" element={<Multidata/>}></Route>
      <Route path="/ajax" element={<MyAjax/>}></Route>
      </Routes>
    </div>
    </Router>
  );
}

export default App;

 

<Link>

a 태그로 전환되며,요청명 개념으로 이해하면 된다. 요청하는 쪽. 

 

<Route>

컴포넌트에서 동적 라우팅 구현 가능하다. 요청을받는쪽.

test화면 링크를 누르면, route path / 와 매핑되고,
실질적으로 실행될 컴포넌트는 element에 적혀있는 <MyTest>이다. 

 

 

하이퍼링크처럼 구현된부분을 누르면, 새로고침없이 화면이 부분적으로 수정되어 내용이 바뀌어 나타난다.

 

 

 

버튼효과

import React, {useState} from "react";

const Counter = () => {
    const [member, setMember] = useState(0);

    const increase = () => {
        setMember(member +1); //member +=1
    }

    const decrease = () => {
        setMember(member -1); //member -=1
    }

    return(
        <div>
            <br/><br/>
            <button onClick={increase}>친구추가</button>&nbsp;&nbsp;
            <button onClick={decrease}>친구삭제</button>
            <p>친구수는 {member}</p>
        </div>
    );

}
export default Counter;

 

 

 

 

 

텍스트입력값 보여주기

import React, {useState} from "react";

const Input1 = () => {
    const [txtValue, setTxtValue] = useState('');

    const changeFunc = (e) => {
        setTxtValue(e.target.value);
    }
    return(
        <div>
            <input type="text" value={txtValue} onChange={changeFunc}></input>
            <br/>
            입력값 : {txtValue}
        </div>
    );
}

export default Input1;
import React, {useState} from "react";

const Input2 = () => {
    const [params, setParams] = useState({
        irum: '',
        nai: '', 
        juso: ''
    });

    const {irum, juso, nai} = params;

    const changeFunc = (e) => {
        const value = e.target.value;
        const id = e.target.id;

        setParams({ //js 연산자
            ...params, 
            [id]:value //에러방지용으로 작성. ?
        })

    }
  
    return(
        <div>
            <br/>
            <div>
                <lable for = "irum">이름: </lable>
                <input type="text" value={irum} id="irum" onChange={changeFunc}/>
            </div>  
            <div>
                <lable for = "nai">나이: </lable>
                <input type="text" value={nai} id="nai" onChange={changeFunc}/>
            </div>  
            <div>
                <lable for = "juso">주소: </lable>
                <input type="text" value={juso} id="juso" onChange={changeFunc}/>
            </div>  
        <br/>
        <h3>처리 결과</h3>
        <table>
        <tr>
            <td>이름은 {irum}</td>
            <td>나이는 {nai}</td>
            <td>주소는 {juso}</td>
        </tr>
        </table>
        </div>
    );
}

export default Input2;

 

 

 

여기서 드는 의문점. setParams

 


const [params, setParams] = useState({

    irum:'',

    nai:'',

    juso:''

});

 

const [params, setParams]:     배열 디스트럭처링을 사용하여 상태 변수 params와 그 상태를 업데이트하는 함수 setParams를 선언한다.

useState:      React Hook으로, 상태를 초기화한다. 초기 상태를 인수로 받음.

{ irum: '', nai: '', juso: '' }:       초기 상태 객체로, 세 가지 속성irum,nai,juso을 모두 빈 문자열로 초기화한다.

 

* 상태 디스트럭처링 : 구조분해할당destructuringassignment

const { irum, juso, nai } = params;

const { irum, juso, nai }:     객체 디스트럭처링을 사용하여 params 상태 객체에서 irum, juso, nai 속성을 추출한다.

= params:      params 객체에서 irum, juso, nai 값을 각각의 변수에 할당한다.

 

setParams

setParams 함수 호출: setParams 함수는 새로운 상태 객체를 인수로 받는다.

새로운 객체 생성: setParams 함수에 전달되는 객체는 다음과 같이 구성된다:

{

    ...params,

    [id]: value

}


 

배열자료 출력하기

 

배열자료를 출력할 경우, map함수를 이용한다.

import React from "react";

// Member 컴포넌트
const Member = ({memberData}) => {
    return(
        <tr>
            <td>{memberData.irum}</td>
            <td>{memberData.junhwa}</td>
        </tr>
    );

}

// 메인 컴포넌트
const Multidata = () => {
    const members = [
        {irum:'관우', junhwa:'111-1111'},
        {irum:'장비', junhwa:'222-1111'},
        {irum:'유비', junhwa:'333-1111'}
    ];

    return(
        <table>
            <thead>
            <tr>
                <th>이름</th><th>전화</th>
            </tr>
            </thead>
            <tbody>
                {/*배열렌더링시 각 요소 고유key를 추가 */}
                {members.map((mem, index) => (
                    <Member key={index} memberData={mem} />
                ))}
            </tbody>
        </table>
    );
}

export default Multidata;

 

 

 

 

ajax를 이용하여 jsp자료 읽기

 

이클립스에서 jsp파일 하나를 만들었다.

<%@ page language="java" contentType="application/json; charset=UTF-8"
    pageEncoding="UTF-8"%>
{
"fruits":[
	{"code":1, "name":"수박", "price":"25000"},
	{"code":2, "name":"복숭아", "price":"1200"}
]

}

 

이를 이클립스에서 아파치 톰캣 서버를 이용해 웹상에 띄운다. 

 

 

 

이클립스에서 아파치톰캣 서버 계속 켜두어 살려두어야 해당 자료를 읽어올 수 있다. 

이클립스 서버의 포트번호는 8080, vs code 서버의 포트번호는 3000.

 

이는 SOP sameoriginpolicy,의 정책에 위배되며, 원론적으로는 리소스를 읽어오는것이 불가능하다.

나에게 똥을 주다니..!

 

 

다른 출처의 리소스가 필요하다면?

그때 사용하는게 corscrossoriginresourcesharing이다. 

A server <> B server 는 cors 에러가 나지 않는다.

 

따라서 package.json에 proxy 부분을 추가해줘야한다.

 

추가해준 모습

 

 

ajax를 이용해 자료를 읽어받아올경우, useEffect를 반드시 사용할 수 밖에 없다. 

 

useEffect

부수 효과sideeffects를 수행하는 데 사용된다. 데이터 가져오기, 구독 설정, 수동 DOM 조작 등을 처리할 수 있다.

import React, {useState, useEffect} from "react";

const MyAjax = () => {
    const [error, setError] = useState(null);
    const [isLoaded, setIsLoaded] = useState(false);
    const [items, setItems] = useState([]);


    useEffect(() => {
        fetch("/web_react/abc.jsp", {method:'GET'})
        .then(res => {
            if(!res.ok){
                throw new Error('network response was not ok');
            }
            return res.json();
        })
        .then(
            (result) => {
                setIsLoaded(true);
                setItems(result.fruits); //fruits 받아오는자료값의 fruits. 상단useState와무관
            },
            (error) => {
                setIsLoaded(true);
                setError(error);
            }
        )
    }, []);

    
    if(error){
        return <div>에러: {error.message}</div>
    }else if(!isLoaded){
        return <div>자료 수신중</div>
    }else{
        return(
            <ul>
                {items.map(fitem => (
                    <li>
                        {fitem.code} {fitem.name} {fitem.price}
                    </li>
                ))}
            </ul>
        );
    }


}

export default MyAjax;

 

fetch를 이용해 jsp 자료Apacheserver 읽는다.

 

useEffect 시
Ajax 처리 성공하면 isLoaded, items갱신. 실패하면 error 갱신.

 

error가 나면 에러메시지를, isLoaded가 false이면 로딩메시지 보이기
그외의 경우 items를 출력rendering한다.

 

 

 

 


https://cafe.daum.net/flowlife/QbpR/73

https://cafe.daum.net/flowlife/QbpR/75