[React/연습] #05. 레이아웃 만들고 링크 걸기

Updated:

오늘은 프론트엔드 화면 레이아웃을 구성하고, 페이지 이동과 axios로 데이터를 뽑아오는 것까지 구현하는 것이 목표다.

설치 파일

본격적인 개발에 앞서, 오늘 할 일에 필요한 프로그램을 설치한다.

react-router

리액트에서 라우팅을 구현하기 위해서 front-end 프로젝트에 react-router를 설치한다.
(라우팅: 사용자가 요청한 링크주소 즉, URL에 맞는 페이지를 찾아서 보여주는 것)

$ npm install react-router-dom

axios

axios는 HTTP 통신을 가능하게 해주는 라이브러리다.
간단히 말해서 프론트엔드와 백엔드의 통신을 쉽게 만들어주는 장치다. 여기서는 데이터 통신을 위해 설치하려고 한다.

$ npm install -g yarn  # yarn 패키지 매니저 설치
$ yarn add axios

참고: yarn을 설치하면 서버 실행 시 npm start 대신 yarn start을 쓸 수가 있는데, yarn startnpm start보다 속도가 빠르다는 장점이 있고 단점으로는 메모리를 많이 차지한다고 한다.

레이아웃 만들기

front-end 맛보기 글에서 만들었던 프로젝트를 바탕으로 인덱스 페이지 화면을 구성하려고 한다.

pages/TableList.js

import React from "react";
import Table from "../components/molecules/Table";
import TableColumn from "../components/atoms/TableColumn";
import TableRow from "../components/atoms/TableRow";

const TableList = props => {
    return (
        <>
            <Table headersName={['글번호', '제목', '등록일']}>
                <TableRow>
                    <TableColumn>1</TableColumn>
                    <TableColumn>첫번째</TableColumn>
                    <TableColumn>2023-10</TableColumn>
                </TableRow>
                <TableRow>
                    <TableColumn>2</TableColumn>
                    <TableColumn>두번째</TableColumn>
                    <TableColumn>2023-11</TableColumn>
                </TableRow>
            </Table>
        </>
    );
};

export default TableList;

atoms/Header.js

import React from "react";

const Header = () => {
    return (
        <header>
            <a href="/"></a>
            &nbsp;&nbsp;|&nbsp;&nbsp;
            <a href="/board">게시판</a>
            <hr />
        </header>
    );
};

export default Header;

atoms/Footer.js

import React from "react";

const Footer = () => {
    return (
        <footer>
            <hr />
            푸터.
        </footer>
    );
};

export default Footer;

index.js

컴포넌트 등록:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import Header from './components/atoms/Header';
import Footer from './components/atoms/Footer';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
    <Header />
    <App />
    <Footer />
  </>
);

터미널에서 yarn start 명령어로 서버를 실행하면,

layout

이렇게 페이지가 잘 뜨는 것을 확인할 수 있다.
링크를 클릭하면 주소만 바뀌고 화면상으로 달라지는 건 없다.

라우팅

이제는 테이블리스트를 게시판 메뉴로 보내고, 화면을 따로 만들어보려 한다.

pages/Home.js

pages 폴더 안에 Home.js 파일을 만든다.

import React from 'react';

const Home = () => {
    return (
        <div>
            홈화면.
        </div>
    );
};

export default Home;

App.js

URL 걸기.

import React from "react";
import { Route, Routes } from "react-router-dom";
import Home from "./pages/Home";
import TableList from "./pages/TableList";

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/board" element={<TableList />} />
    </Routes>
  );
}

export default App;

index.js

화면 구성.

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import Header from './components/atoms/Header';
import Footer from './components/atoms/Footer';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <>
    <BrowserRouter>
      <Header />
      <App />
      <Footer />
    </BrowserRouter>
  </>
);

이렇게 수정하고 나서 서버를 실행하면 홈 화면과 게시판 화면이 각각 아래와 같다.

home-1

board-1

백엔드 연동

pages/TableList.js

axios를 통해 데이터를 조회하는 코드를 작성한다.

import React, { useEffect, useState } from "react";
import axios from 'axios';
import Table from "../components/molecules/Table";
import TableColumn from "../components/atoms/TableColumn";
import TableRow from "../components/atoms/TableRow";

const TableList = props => {
    const [boardList, setBoardList] = useState([]);

    const getBoardList = async () => {
        const resp = await (await axios.get('//localhost:8080/board')).data; //2
        setBoardList(resp.data);//3
        console.log(boardList);
    }

    useEffect(() => {
        getBoardList(); // 1
    }, []);

    return (
        <>
            <Table headersName={['글번호', '제목', '등록일']}>
                <TableRow>
                    <TableColumn>1</TableColumn>
                    <TableColumn>첫번째</TableColumn>
                    <TableColumn>2023-10</TableColumn>
                </TableRow>
                <TableRow>
                    <TableColumn>2</TableColumn>
                    <TableColumn>두번째</TableColumn>
                    <TableColumn>2023-11</TableColumn>
                </TableRow>
            </Table>
        </>
    );
};

export default TableList;

데이터를 조회하기 위해서 지난번에 만들었던 백엔드 서버를 실행한다.

terminal

이렇게 서버가 잘 실행되었으면 다시 프론트엔드로 돌아와서 데이터를 잘 받는지 확인한다.
그런데 나는 처음에 네트워크 에러가 발생했다…

network-error

이건 간단하게 해결할 수 있다. 여기로 가서 해결하자.

정상 작동할 경우 콘솔창에 데이터가 출력되는 것을 확인할 수 있다.

console-data

데이터 뿌리기

이제 저 테이블리스트의 내용으로 백엔드에서 가져온 데이터를 띄울 것이다.

import React, { useEffect, useState } from "react";
import axios from 'axios';
import Table from "../components/molecules/Table";
import TableColumn from "../components/atoms/TableColumn";
import TableRow from "../components/atoms/TableRow";

const TableList = props => {
    const [boardList, setBoardList] = useState([]);

    const getBoardList = async () => {
        const resp = await (await axios.get('//localhost:8080/board')).data; //2
        setBoardList(resp.data);//3

        const pngn = resp.pagination;
        console.log(pngn);
    }

    useEffect(() => {
        getBoardList(); // 1
    }, []);

    return (
        <>
            <Table headersName={['글번호', '제목', '등록일']}>
                {boardList.map((board) => (
                    <TableRow>
                        <TableColumn>{board.idx}</TableColumn>
                        <TableColumn>{board.title}</TableColumn>
                        <TableColumn>{board.createdAt}</TableColumn>
                    </TableRow>
                ))}
            </Table>
        </>
    );
};

export default TableList;

data-connected

화면에 데이터가 예쁘게 잘 출력되고 있다.

Network Error

AxiosError: Network Error at XMLHttpRequest.handleError 해결 방법

백엔드 프로젝트로 가서, Main 클래스와 같은 위치에 WebConfig.java 파일을 만들고 서버를 재실행한다.

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .maxAge(3000);

        // addMapping - CORS를 적용할 url의 패턴을 정의 (/** 로 모든 패턴을 가능하게 함)
        // allowedOrigins - 허용할 origin을 정의 (* 로 모든 origin을 허용, 여러개도 지정가능)
        // allowedMethods - HTTP Method를 지정 (* 로 모든 Method를 허용)
        // maxAge - 원하는 시간만큼 request를 cashing함
    }
}

참고자료

Leave a comment