100일 챌린지/빅데이터기반 인공지능 융합 서비스 개발자

Day 78 - React로 CRUD 프로그램 만들기 (2) spring에서 데이터셋 활용하기 [h2]

ksyke 2024. 11. 19. 17:54

목차

    Spring 프로젝트 만들기

    application.properties

    spring.application.name=sts14
    
    spring.datasource.url=jdbc:h2:mem:test
    
    spring.h2.console.path=/h2
    spring.h2.console.enabled=true
    
    spring.jpa.show-sql=true
    spring.jpa.hibernate.ddl-auto=update

    Dept.class

    package com.gimhae.sts14.model.entity;
    
    import jakarta.persistence.Entity;
    import jakarta.persistence.GeneratedValue;
    import jakarta.persistence.GenerationType;
    import jakarta.persistence.Id;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    //import lombok.Data;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @Entity
    public class Dept {
    	@Id
    	@GeneratedValue(strategy = GenerationType.IDENTITY)
    	int deptno;
    	String dname;
    	String loc;
    }

    DeptRepo.Interface

    package com.gimhae.sts14.model;
    
    import org.springframework.data.repository.CrudRepository;
    
    import com.gimhae.sts14.model.entity.Dept;
    
    public interface DeptRepo extends CrudRepository<Dept, Integer> {
    
    }

    DeptService.class

    package com.gimhae.sts14.service;
    
    import java.util.Collections;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.gimhae.sts14.model.DeptRepo;
    import com.gimhae.sts14.model.DeptVo;
    import com.gimhae.sts14.model.entity.Dept;
    
    @Service
    public class DeptService {
    
    	@Autowired
    	DeptRepo deptRepo;
    	
    	public Iterable<Dept> getList(){
    		return deptReppackage com.gimhae.sts14.service;
    
    import java.util.Collections;
    import java.util.Optional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.gimhae.sts14.model.DeptRepo;
    import com.gimhae.sts14.model.DeptVo;
    import com.gimhae.sts14.model.entity.Dept;
    
    @Service
    public class DeptService {
    
    	@Autowired
    	DeptRepo deptRepo;
    	
    	public Iterable<Dept> getList(){
    		return deptRepo.findAll();
    	}
    	
    	public void pushList(DeptVo bean) {
    		deptRepo.save(bean.deptBuild());
    	}
    	
    	public Optional<DeptVo> getOne(int deptno) {
    		Dept dept=deptRepo.findById(deptno).get();
    		return Optional.of(
    				DeptVo.builder()
    				.deptno(dept.getDeptno())
    				.dname(dept.getDname())
    				.loc(dept.getLoc())
    				.build());
    	}
    }
    o.findAll();
    	}
    	
    	public void pushList(DeptVo bean) {
    		deptRepo.save(bean.deptBuild());
    	}
    }

    ProjectApplication.class

    package com.gimhae.sts14;
    
    import java.util.Optional;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.gimhae.sts14.model.DeptVo;
    import com.gimhae.sts14.service.DeptService;
    
    @RestController
    @SpringBootApplication
    public class Sts14Application implements CommandLineRunner{
    
    	public static void main(String[] args) {
    		SpringApplication.run(Sts14Application.class, args);
    	}
    	@Autowired
    	DeptService deptService;
    	
    	@Override
    	public void run(String... args) throws Exception {
    		deptService.pushList(DeptVo.builder().dname("tester01").loc("서울").build());
    		deptService.pushList(DeptVo.builder().dname("tester02").loc("대전").build());
    		deptService.pushList(DeptVo.builder().dname("tester03").loc("대구").build());
    		deptService.pushList(DeptVo.builder().dname("tester04").loc("부산").build());
    	}
    
    	@CrossOrigin(origins = {
    	                        "http://192.168.11.213:3000",
    	                        "http://localhost:3000",
    	                        "http://127.0.0.1:3000"
    							}, methods = RequestMethod.GET)
    	@GetMapping("/dept/")
    	public ResponseEntity<?> list() {
    		return ResponseEntity.ok(deptService.getList());
    	}
    
    	@CrossOrigin
    	@PostMapping("/dept/")
    	public ResponseEntity<?> add(@RequestBody DeptVo bean){
    		try {
    			deptService.pushList(bean);
    			return ResponseEntity.ok().build();
    		}catch(Exception e) {
    			return ResponseEntity.badRequest().build();
    		}
    	}
    	
    	@CrossOrigin
    	@GetMapping("/dept/{deptno}")
    	public Optional<DeptVo> getOne(@PathVariable int deptno) {
    		return deptService.getOne(deptno);
    	}
    
    }

    React 프로젝트 만들기

    index.js

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    import { BrowserRouter, Route, Routes } from 'react-router-dom';
    import Main from './pages/Main';
    import Intro from './pages/Intro';
    import Depts from './pages/Depts';
    import Frame from './pages/Frame';
    import Errs from './pages/Errs';
    import AddDept from './pages/AddDept';
    import Dept from './pages/Dept';
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <BrowserRouter>
          <Routes>
            <Route path='/' element={<Frame/>}>
              <Route index element={<Main/>}/>
              <Route path='/intro' element={<Intro/>}/>
              <Route path='/dept/' element={<Depts/>}/>
              <Route path='/dept/add' element={<AddDept/>}/>
              <Route path='/dept/detail' element={<Dept/>}/>
              <Route path='/*' element={<Errs/>}/>
            </Route>
          </Routes>
        </BrowserRouter>
      </React.StrictMode>
    );
    
    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();

    Frame.js

    import React, { useEffect } from 'react'
    import { Link, Outlet } from 'react-router-dom'
    
    function Frame(props) {
    
        const st_ul={width:'100%',height:'35px',padding:0,listStyle:'none'};
        const st_li={float:'left',height:35,width:100};
        const st_Link={backgroundColor:'gray',margin:1,display:'block'};
        const st_Content={};
        const st_Footer={backgroundColor:'gray',color:'white'};
    
      return (
        <>
            <nav style={{backgroundColor:'darkgray'}}>
                <ul style={st_ul}>
                    <li style={st_li}><Link style={st_Link} to={'/'}>HOME</Link></li>
                    <li style={st_li}><Link style={st_Link} to={'/intro'}>INTRO</Link></li>
                    <li style={st_li}><Link style={st_Link} to={'/dept/'}>DEPT</Link></li>
                    <li style={st_li}><Link style={st_Link} to={'/login/'}>LOGIN</Link></li>
                </ul>
            </nav>
            <div id='content'  style={st_Content}>
                {<Outlet/>}
            </div>
            <div id='footer'  style={st_Footer}>
                <p>김해캠퍼스 (50834) 경남 김해시 인제로 197</p>
                <p>Copyright(c) 1996-2022 INJE University. All rights reserved.</p>
            </div>
        </>
      )
    }
    export 
    const st_title={borderBottom:'2px solid gray',width:200,textAlign:'center',margin:'auto'};
    export default Frame

    Main.js

    import React from 'react'
    
    function Main() {
      return (
        <div>Index Page</div>
      )
    }
    
    export default Main

    Intro.js

    import React from 'react'
    import campus from '../campus.jpg'
    
    function Intro() {
      return (
        <img src={campus}/>
      )
    }
    
    export default Intro

    Depts.js

    import React, { useEffect, useState } from 'react'
    import { Link } from 'react-router-dom';
    import { st_title } from './Frame';
    
    function Depts() {
    
      const [list,setList]=useState([]);
    
      useEffect(()=>{
        fetch('http://localhost:8080/dept/')
        .then(e=>e.json())
        .then(json=>{
          const array=json.map(ele=>{
            return(import React, { useEffect, useState } from 'react'
    import { Link } from 'react-router-dom';
    import { st_title } from './Frame';
    
    function Depts() {
    
      const [list,setList]=useState([]);
    
      useEffect(()=>{
        fetch('http://localhost:8080/dept/')
        .then(e=>e.json())
        .then(json=>{
          const array=json.map(ele=>{
            return(
              <tr>
                <td><Link to={'/dept/detail?deptno='+ele.deptno}>{ele.deptno}</Link></td>
                <td><Link to={'/dept/detail?deptno='+ele.deptno}>{ele.dname}</Link></td>
                <td><Link to={'/dept/detail?deptno='+ele.deptno}>{ele.loc}</Link></td>
              </tr>
            );
          });
          setList(array);
        });
      },[]);
    
      return (
        <>
        <h2 style={st_title}>List Page</h2>
        <table>
          <thead>
            <tr>
              <th>deptno</th>
              <th>dname</th>
              <th>loc</th>
            </tr>
          </thead>
          <tbody>
            {list}
          </tbody>
        </table>
        <p><Link to={'/dept/add'}>입력</Link></p>
        </>
      )
    }
    
    export default Depts
              <tr>
                <td>{ele.deptno}</td>
                <td>{ele.dname}</td>
                <td>{ele.loc}</td>
              </tr>
            );
          });
          setList(array);
        });
      },[]);
    
      return (
        <>
        <h2 style={st_title}>List Page</h2>
        <table>
          <thead>
            <tr>
              <th>deptno</th>
              <th>dname</th>
              <th>loc</th>
            </tr>
          </thead>
          <tbody>
            {list}
          </tbody>
        </table>
        <p><Link to={'/dept/add'}>입력</Link></p>
        </>
      )
    }
    
    export default Depts

    Dept.js

    import React, { useEffect, useState } from 'react'
    import { Navigate, useLocation, useNavigate, useSearchParams } from 'react-router-dom';
    import {st_title} from './Frame'
    
    function Dept() {
        const navigate=useNavigate();
        const location=useLocation();
        const [bean,setBean]=useState({deptno:'-',dname:'-',loc:'-'});
    
        useEffect(()=>{
          // console.log(typeof Number(location.search.split('=')[1]));
          const deptno=Number(location.search.split('=')[1]);
    
          fetch('http://localhost:8080/dept/'+deptno)
          .then(e=>e.json())
          .then(e=>{
            setBean({...e});
          });
        },[]);
    
      return (
        <>
        <h2 style={st_title}>Detail Page</h2>
        <form>
            <div><input name='deptno' value={bean.deptno}/></div>
            <div><input name='dname' value={bean.dname}/></div>
            <div><input name='loc' value={bean.loc}/></div>
        </form>
        </>
      )
    }
    
    export default Dept

    Errs.js

    import React from 'react'
    
    function Errs() {
      return (
        <div style={{color:'red',textAlign:'center'}}>404페이지 호출이 잘못되었습니다.</div>
      )
    }
    
    export default Errs

    AddDept.js

    import React from 'react'
    import { Navigate, useNavigate } from 'react-router-dom';
    import {st_title} from './Frame'
    
    function AddDept() {
        const navigate=useNavigate();
    
        const submitAction=e=>{
            e.preventDefault();
            console.log(e.target.dname.value,e.target.loc.value);
            const param={'dname':e.target.dname.value,'loc':e.target.loc.value};
    
            fetch('http://localhost:8080/dept/',{
                method: 'post',
                body: JSON.stringify(param),
                headers:{
                    'Content-Type':'application/json'
                }
            })
            .then(e=>{
                return e.ok;
            })
            .then(e=>{
                if(e) navigate('/dept/')
            });
        };
    
      return (
        <>
        <h2 style={st_title}>Add Page</h2>
        <form onSubmit={submitAction}>
            <div><input name='dname' placenolder='dname'/></div>
            <div><input name='loc' placenolder='loc'/></div>
            <div>
                <button>입력</button>
                <button type='reset'>취소</button>
                <button type='button' onClick={e=>navigate(-1)}>뒤로</button>
            </div>
        </form>
        </>
      )
    }
    
    export default AddDept

     

    method 또한 배열로 설정 가능.