자바풀스택 과정/자바 풀 스택 : 수업내용정리

자바 풀 스택 3/7 오후 기록 069-2

파티피플지선 2025. 3. 7. 18:18

<14:30 5교시>

App.jsx 는 최상위 컴포넌트로 currentOutlet이 표시된 부분을 뭘로 채울지 결정한다.

 

Router Provider가 있어서 useOutlet을 쓰려면 index.js에 Routerporvider로 router 정보가 있는 router를 설정해줘야 함.

 

 

일단 샘이 하는거 하기 전에 내가 삽질(Ctrl C+V)한거 먼저 백업 : 새글작성 폼은 기능이 되는데 삭제 수정 기능이 안됨

더보기

 

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';

function NewPost(props) {
    // "/posts?pageNum=x"에서 pageNum 과 같은 query parameter를 추출하기 위한 훅
    const [params, setParams] = useSearchParams({
        pageNum:1
    });

    //페이지 정보를 state로 관리한다
    const [pageInfo, setPageInfo] = useState({
        list: []
    });

    const [pageArray, setPageArray]=useState([]);
    function range(start, end){
        const result=[];
        for(let i=start; i<=end; i++){
            result.push(i);
        }
        return result;
    }

    const refresh= (pageNum)=>{
        axios.get("/v3/posts?pageNum="+pageNum)
        .then(res=>{
            //서버에서 응답한 data는 res.data에 들어있다.
            console.log(res);
            //상태값을 변경한다.
            setPageInfo(res.data);
            const result=range(res.data.startPageNum, res.data.endPageNum);
            setPageArray(result);
        })
        .catch(err=>console.log(err))
    }
    //컴포넌트가 활성화된 시점에 1페이지 정보를 얻어온다. -> params에서 찾은걸 읽어오고 싶다
    useEffect(()=>{
        //query parameter 값 읽어오기
        let pageNum=params.get("pageNum")

        refresh(pageNum);
    },[params]); // params가 변경될 때 useEffect()안의 함수가 다시 호출되도록 함.


    const navigate = useNavigate();//강제로 페이지 이동시키기 훅
    const move= (pageNum)=>{
        navigate(`/posts?pageNum=${pageNum}`) //navigate 함수를 이용해서 페이지를 변경하는 함수수
    }


    return (
        <div className="container">
            <h1>새글 작성 폼</h1>
            <form action="/v3/posts" onSubmit={(e)=>{
                e.preventDefault();//폼 전송 막고 fetch함수로 직접 전송하겠다
                //요청 url
                const url=e.target.action;
                //폼에 입력한 내용을 json 형식의 문자열로 바꾸기
                //1.0. FormData 객체 
                const formData=new FormData(e.target);
             
                //1. 폼에 입력한 내용을 object로 변환하기 : Object의 fromEntries()함수
                const obj =Object.fromEntries(formData);

                //2. object 에 있는 내용을 이용해서 json 문자열 만들기
                const json = JSON.stringify(obj);
                //console.log(obj);
                //console.log(json);

                //3. fetch 함수를 이용해서 페이지 전환 없이 post 방식의 요청을 하면서 json 문자열을 전송하기
                //fetch 함수 대신에 axios를 사용할거고 앞으로도 axios를 사용할거임
                //post(요청경로, object), obj에 담긴 내용이 자동으로 json 문자열로 변경되어서 서버에 전달됨됨
                axios.post("/v3/posts",obj)
                .then(response=>{
                    console.log(response);//response는 object 인데 응답에 관련된 여러 정보가 들어있음
                    //server가  응답한 json 문자열이 object 또는 array로 변환되어서 res.data라는 방에 들어있다
                    console.log(response.data)
                    navigate("/posts")
                })
                .catch(error=>{console.log(error)
                    console.log(error);
                })
               
            }}>
                <input type="text" name="title" placeholder="제목 입력" />
                <input type="text" name="author" placeholder="작성자 입력" />
                <button type="submit" >저장</button>
            </form>
    </div>
    );
}

export default NewPost;

 

 

 

import axios from 'axios';
import React, { useEffect, useState } from 'react';
import { NavLink, useNavigate, useSearchParams } from 'react-router-dom';

import {v4 as uuid} from "uuid"//key 값을 얻어내기 위한 함수 import

function Post(props) {
    // "/posts?pageNum=x"에서 pageNum 과 같은 query parameter를 추출하기 위한 훅
    const [params, setParams] = useSearchParams({
        pageNum:1
    });

    //페이지 정보를 state로 관리한다
    const [pageInfo, setPageInfo] = useState({
        list: []
    });

    const [pageArray, setPageArray]=useState([]);
    function range(start, end){
        const result=[];
        for(let i=start; i<=end; i++){
            result.push(i);
        }
        return result;
    }

    const refresh= (pageNum)=>{
        axios.get("/v3/posts?pageNum="+pageNum)
        .then(res=>{
            //서버에서 응답한 data는 res.data에 들어있다.
            console.log(res);
            //상태값을 변경한다.
            setPageInfo(res.data);
            const result=range(res.data.startPageNum, res.data.endPageNum);
            setPageArray(result);
        })
        .catch(err=>console.log(err))
    }
    //컴포넌트가 활성화된 시점에 1페이지 정보를 얻어온다. -> params에서 찾은걸 읽어오고 싶다
    useEffect(()=>{
        //query parameter 값 읽어오기
        let pageNum=params.get("pageNum")

        refresh(pageNum);
    },[params]); // params가 변경될 때 useEffect()안의 함수가 다시 호출되도록 함.


    const navigate = useNavigate();//강제로 페이지 이동시키기 훅
    const move= (pageNum)=>{
        navigate(`/posts?pageNum=${pageNum}`) //navigate 함수를 이용해서 페이지를 변경하는 함수수
    }


    return (
        <div className="container">
        <h1>글 목록</h1>
        <NavLink to="/posts">새글 작성</NavLink>
        <table className="table table-striped">
            <thead className="table-dark">
                <tr>
                    <th>번호</th>
                    <th>제목</th>
                    <th>작성자</th>
                    <th>수정</th>
                    <th>삭제</th>
                </tr>
            </thead>
            <tbody>
                {pageInfo.list.map(item=>
                    <tr key={item.id}>
                        <td>{item.id}</td>
                        <td>{item.title}</td>
                        <td>{item.author}</td>
                        <td><button onClick={()=>{
                                //수정할 제목을 입력받기
                                const title = prompt(item.id+"번글의 수정할 제목 입력")
                                //수정할 정보를 이용해서 object 만들기(id는 경로로 전달되니 패스)
                                const obj= {
                                        title:title, 
                                        author:item.author};
                                axios.put("/posts"+item.id,obj)
                                .then(res=>{
                                    console.log(res.data);
                                })
                               .catch(error=>console.log(error))

                            }}>수정</button></td>
                        <td><button onClick={()=>{
                                axios.delete("/posts"+item.id)
                                .then(res=>{
                                    alert(res.data.id+"번 글을 삭제했습니다")   
                                })
                                .catch(error=>console.log(error))
                            }}>삭제</button>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>
        <ul className="pagination">
                <li className={`page-item ${pageInfo.startPageNum===1? 'disabled':''}`}> 
                    <a className="page-link" href="/v3/" onClick={(e)=>{
                         e.preventDefault();
                        move(pageInfo.startPageNum-1)
                    }}> ◀  </a>
                </li>
            {pageArray.map(num=>
                <li className={`page-item ${pageInfo.pageNum===num? 'active' :''}`} key={uuid()}>
                    <a className="page-link" href="/v3/" onClick={(e)=>{
                        e.preventDefault();//주소창의 반응이 없다=기본동작을 막아서
                        move(num);
                    }}>{num}</a>
                </li>
                
            )}
                  <li className={`page-item ${pageInfo.endPageNum<pageInfo.totalPageCount? '':'disabled'}`}> 
                    <a className="page-link" href="/v3/" onClick={(e)=>{
                        e.preventDefault();
                        move(pageInfo.endPageNum+1)
                    }}> ▶ </a>
                </li>
        </ul>
    </div>
    );
}

export default Post;

 

 

delete 기능 왜 안되나 했더니 백엔드에서 바보짓 해놨었음.... service.delete 했어야 하는데 delete 해놔서 무한루프....ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ젠장.....

 

<15:30 6교시>

 

 

 

참조할 object 의 key 값이 변수에 들어있으면 그 변수 안에 있는 값이 key 값으로 쓰인다.

 

 

<16:30 7교시>

 

 

목록보기 삭제하기 수정하기 등등 모든 기능을 구현해서 최초의 SPA(single page application)을 만들어낸거임.

깜빡임이 절대 없이 화면의 부분 업데이트만 하는 것이 SPA의 장점. 난이도가 높음.

 

 

react bootstrap 설치해서 navbar 만들어보기

 

 

<17:30 8교시> 

집에서 이클립스 했을 때, lombok을 설치하니 자꾸 에러가 나고 이클립스가 튕겨서 다시 압축해제 다시 압축해제, 이걸 몇 번 했었는데 이번에는 집가서 

1. 메이븐부터 설치 해봐야 하나. 아니 근데 이클립스에 내장되어 있다며 왜째서.

 

2. lombok 버전 차이 문제이려나? 학원거는 1.18.36임

뭐가 문제였을까.

 

3. 리액트까지 있는 폴더를 돌리려고 해서 문제가 생겼던 것일수도

 vs코드로 리액트 환경도 만들어봐야지. 오전기록 64-1 참고하기