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

자바 풀 스택 3/6 오후 기록 068-2

파티피플지선 2025. 3. 6. 17:17

<14:30 5교시>

if로 작성한코드와 Optional로 작성한 코드가 같은 내용인데, 아래꺼가 한줄 코딩이라 예쁘긴 하네.

 

 

 

새로운거 배우기

생성자로부터 주입받기



 

 

pageable 객체를 이용해서 참조값얻어내서 페이징하는 예제임

 

 

1페이지를 0페이지로, 2페이지를 1페이지로 인식하기 때문에 파라미터에서 받은 페이지번호에서 1씩 빼야 한다.

 

 

정렬과 관련된 타입을 만들기.

 

 

 

JPA에 내장된 페이지 리스트를 얻어내는 기능을 사용해서 페이지 별로 데이터 얻어내기

 

 

 

페이징 처리가 된다.

 

SWAGGER UI는 쓰다보니까 알겠다.

매번 리액트로 확인하기는 불편하니까 개발자들이 확인하기 편하라고 만들어진 임시 html 페이지 같은 것이네. 

 

 

 

<15:30 6교시>

 

 

 

SWAGGER에서 그냥 요청하면 들어가지는걸 막아야 한다. 토큰 정보도 같이 넣어주게 될 것이다. 지금은 완전 OpenAPI

API인데 인증절차가 없는데, 어떻게 할 것인가?

다음에 배울 것 : 보안 토큰

세션으로 하지 않고 아이디 계정유저네임이 일치하는지 확인해서 유효기간이 있는 토큰을 발급해주면 그걸 웹브라우저에서 어딘가(보통 로컬 스토리지)에 저장해놨다가 SpringSecurity에서 이 토큰을 검사해서 자격 증명을 확인해서 인증절차를 진행할 수 있음. 시큐리티를 잘 이해하고 있으면 크게 어려울 건 없음.

 

 

내 삽질: 되긴하던데 애매한거 같아서 바꾸던 중간의 코드를 백업함.

const[pageNum, setpageNum]=useState([]);

    const getList= ()=>{
        axios.get("/v3/posts").then(response=>{
            setPosts(response.data.list)
        }).catch(error=>console.log(error))
    }
    useEffect(()=>{getList()},[])
    return(
        <div className="container">
            <h1>글 목록</h1>
            <table>
                <thead>
                    <tr>
                        <th>번호</th>
                        <th>제목</th>
                        <th>작성자</th>
                    </tr>
                </thead>
                <tbody>
                    {posts.map(item=>
                        <tr key={item.id}>
                            <td>{item.id}</td>
                            <td>{item.title}</td>
                            <td>{item.author}</td>
                        </tr>
                    )}

                </tbody>
            </table>
            <a href="/v3/posts">{posts.startPageNum}</a>
        </div>
    )

}
export default App;

 

백엔드가 API를 만들어내면, 프론트엔드는 아래와 같이 출력해내는 걸 한다.

 

 

 

CSR과 SSR은 어떤게 어떤 장단점이 있을까? 챗지피티에게 물어봐야징

더보기

웹 브라우저에서 **Client-Side Rendering (CSR)**과 **Server-Side Rendering (SSR)**은 두 가지 주요 렌더링 방식입니다. 이 두 가지 방식은 각각 장단점이 있으며, 사용되는 상황에 따라 선택이 달라질 수 있습니다.

1. Client-Side Rendering (CSR)

CSR의 작동 방식

  • CSR은 처음 페이지를 로드할 때 HTML, CSS, JavaScript 파일을 클라이언트(브라우저)로 전송하고, 이후 모든 렌더링은 클라이언트 측에서 처리됩니다.
  • 페이지는 JavaScript를 통해 동적으로 렌더링되며, 데이터는 API를 통해 비동기적으로 받아와서 화면을 업데이트합니다.

CSR의 장점

  • 빠른 사용자 경험: 첫 페이지 로딩 후, 페이지 간 이동이 빠릅니다. 서버로부터 전체 HTML을 다시 로드할 필요 없이 클라이언트 측에서 데이터만 갱신하고, UI를 빠르게 업데이트할 수 있습니다.
  • 서버 부담 감소: 서버는 HTML을 처음 한 번만 전달하고, 그 이후에는 주로 API 요청만 처리하므로 서버의 부담이 적습니다.
  • 유연한 인터랙티브 UI: JavaScript를 활용해 동적이고 복잡한 사용자 인터페이스를 쉽게 구현할 수 있습니다. 예를 들어, SPA(Single Page Application) 형태로 동작하는 사이트에서 CSR은 매우 유리합니다.

CSR의 단점

  • 첫 로딩 속도: JavaScript 파일과 다른 리소스를 모두 다운로드하고 실행해야 하므로 첫 번째 페이지 로딩 속도가 느릴 수 있습니다. 초기 렌더링이 지연될 수 있습니다.
  • SEO 문제: 페이지 콘텐츠가 JavaScript로 동적으로 로딩되기 때문에, 검색 엔진이 페이지 내용을 제대로 인식하지 못할 수 있습니다. 검색 최적화(SEO) 측면에서 불리할 수 있습니다.
  • 브라우저 성능에 의존: 클라이언트의 성능에 따라 렌더링 속도가 달라질 수 있습니다. 성능이 낮은 디바이스에서는 렌더링 성능이 떨어질 수 있습니다.

2. Server-Side Rendering (SSR)

SSR의 작동 방식

  • SSR은 클라이언트가 요청을 보내면, 서버에서 HTML을 생성해 클라이언트에 전달합니다. 서버에서 페이지를 렌더링하고, 그 결과를 클라이언트에 보내는 방식입니다.
  • 클라이언트는 HTML, CSS, JavaScript가 포함된 완성된 페이지를 받기 때문에, 페이지가 즉시 렌더링됩니다.

SSR의 장점

  • 빠른 첫 페이지 로딩: 서버에서 렌더링된 HTML이 바로 클라이언트에 전달되므로 첫 페이지 로딩이 빠릅니다. 콘텐츠가 미리 렌더링된 상태로 도달하기 때문에 초기 로딩 속도가 개선됩니다.
  • SEO 최적화: 서버에서 렌더링된 HTML을 클라이언트가 받기 때문에, 검색 엔진은 페이지의 내용을 쉽게 인식할 수 있습니다. SEO 측면에서 매우 유리합니다.
  • 모든 클라이언트 지원: JavaScript가 비활성화된 환경에서도 서버 측에서 렌더링된 HTML을 받을 수 있기 때문에, 모든 클라이언트에서 정상적으로 작동합니다.

SSR의 단점

  • 서버 부하: 매번 페이지 요청에 대해 서버에서 HTML을 렌더링해야 하므로 서버의 부담이 커집니다. 사용자 수가 많을수록 서버의 부하가 증가할 수 있습니다.
  • 느린 페이지 전환: 페이지를 전환할 때마다 서버에 새로운 요청을 보내야 하므로, 클라이언트 측에서 즉각적인 페이지 전환을 경험할 수 없습니다.
  • 유연성 부족: JavaScript를 통한 동적 UI 업데이트가 제한적입니다. 서버에서 렌더링된 HTML이 그대로 전달되기 때문에, 클라이언트 측에서 추가적인 동적 변화가 필요하다면 JavaScript가 이를 처리해야 합니다.

결론

  • CSR은 빠른 페이지 전환과 클라이언트에서 동적이고 복잡한 UI를 구현할 수 있는 장점이 있지만, 첫 로딩 속도와 SEO에 불리할 수 있습니다.
  • SSR은 SEO 최적화와 빠른 첫 페이지 로딩을 제공하지만, 서버에 부하가 많고, 페이지 간 전환 속도가 상대적으로 느릴 수 있습니다.

사용할 상황에 따라 선택:

  • SEO가 중요한 사이트초기 로딩 성능을 중요시하는 사이트에서는 SSR이 적합합니다.
  • 사용자 경험빠른 페이지 전환을 중시하는 사이트에서는 CSR이 유리할 수 있습니다.

또한, 최근에는 SSR과 CSR을 결합한 하이브리드 방식도 많이 사용되며, React의 Next.js나 Nuxt.js 같은 프레임워크는 이러한 방식을 지원합니다.

 

 

<16:30 7교시>

 

 

 

 

npm install bootstrap 도 가능

 

 

 

 

5:20엔 출발해야징.

import axios from "axios";
import { useEffect, useState } from "react";
import {v4 as uuid} from "uuid"//key 값을 얻어내기 위한 함수 import

//npm install bootstrap 설치 후 "bootstrap/dist/css/bootstrap.css"입력하면 전역에서 사용 가능한 bootstrap css가 로딩됨됨
import "bootstrap/dist/css/bootstrap.css";

function App(){
    //페이지 정보를 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페이지 정보를 얻어온다.
    useEffect(()=>{
        refresh(1);
    },[]);

    return(
        <div className="container">
            <h1>글 목록</h1>
            <table className="table table-striped">
                <thead className="table-dark">
                    <tr>
                        <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>
                        </tr>
                    )}
                </tbody>
            </table>
            <ul className="pagination">
                {pageArray.map(num=>
                    <li className={`page-item ${pageInfo.pageNum===num? 'active' :''}`} key={uuid()}>
                        <a className="page-link" href="#" onClick={(e)=>{
                            e.preventDefault();//주소창의 반응이 없다=기본동작을 막아서
                            refresh(num);
                        }}>{num}</a>
                    </li>
                )}
            </ul>
        </div>
    )

}
export default App;

 

 

 

수단과 방법을 가리지 말고 다음과 이전 기능 만들기.라는데 집가서 할 수 있을랑가 모르겠다.

 

<17:30 8교시>  실습 시간 - 대학원 수업 때문에 조퇴로 인한 불참