오늘은
학원 수료가 이제 한달도 채 남지 않았습니다
수료가 다가오면서 파이널 프로젝트 기간도 있고
설도 있기 때문에
취업 준비의 압박이 더욱 커질것으로 예상이 됩니다
그리고 동시에 정신이 없을 것 같다는 생각이 들어 긴장이 됩니다
Spring Boot 공부
* 검색
search form
<form action="/board/pagelist" method="get">// 자기 자신에게 보내줌
<input type="text" name="keyword">
<input type="submit" value="Search">
</form>
* 파일 업로드
게시판 - 업로드, 수정
<form action="/board/write" method="" enctype="multipart/form-data">
<input type="file" name="boardFile">
</form>
MultipartFile 클래스
파라미터 2개
(BoarDTO, MultipartFile boardFile)
1. 파일 저장 - 지정한 폴더 (서버)
2. 파일 이름 -> db에 저장 -> 이름 출력
(=> 파일이 직접적으로 db에 저장되는 것은 아님)
* BoardController
// 글쓰기 처리
@PostMapping("/write")
public String write(@Valid BoardDTO boardDTO,
MultipartFile boardFile,
BindingResult bindingResult) throws IOException, Exception {
// 에러 처리
if(bindingResult.hasErrors()) {
log.info("has errors......");
return "/board/write"; // error가 있으면 writeForm 폼으로 이동
}
// 글쓰기 처리
boardService.save(boardDTO, boardFile);
return "redirect:/board/pagelist";
}
* 동시에 파일을 업로드 했을 때 파일 이름 중복 방지
UUID 클래스 + 파일이름
System.currentmiliseconds() + 파일이름
* BoardService
public void save(BoardDTO boardDTO, MultipartFile boardFile) throws Exception, IOException {
// 1. 파일 저장 -> 서버
if(!boardFile.isEmpty()) { // 전달 된 파일이 있으면
// 저장 경로 (1. server에 만드는 방법, 2. 하드디스크에 만드는 방법)
String filepath = "C:\\bootworks\\bootboard\\src\\main\\resources\\static\\upload\\";
UUID uuid = UUID.randomUUID(); // 무작위 아이디 생성 = 중복파일의 이름 방지
String filename = uuid + "_" + boardFile.getOriginalFilename(); // 원본 파일
// File 클래스 객체 생성
File savedFile = new File(filepath, filename); // upload 폴더에 저장
boardFile.transferTo(savedFile);
// 2. 파일 이름 저장 -> DB
boardDTO.setFilename(filename);
boardDTO.setFilepath("/upload/" + filename); // 파일 경로 설정
}
//dto -> entity 변환 메서드 필요
Board board = Board.toSaveEntity(boardDTO);
// entity를 db에 저장
boardRepository.save(board);
}
<업로드 파일 수정>
* 수정 시 문제점
= 이미지가 사라지는 문제
=> service에서 처리
* BoardService
public void update(BoardDTO boardDTO, MultipartFile boardFile) throws Exception, IOException {
// save() = 삽입(id가 없는 경우), 수정(id가 있는 경우)로 나뉨
Board board = null;
// 1. 파일 저장 -> 서버
if(!boardFile.isEmpty()) { // 전달 된 파일이 있으면
// 저장 경로 (1. server에 만드는 방법, 2. 하드디스크에 만드는 방법)
String filepath = "C:\\bootworks\\bootboard\\src\\main\\resources\\static\\upload\\";
UUID uuid = UUID.randomUUID(); // 무작위 아이디 생성 = 중복파일의 이름 방지
String filename = uuid + "_" + boardFile.getOriginalFilename(); // 원본 파일
// File 클래스 객체 생성
File savedFile = new File(filepath, filename); // upload 폴더에 저장
boardFile.transferTo(savedFile);
// 2. 파일 이름 저장 -> DB
boardDTO.setFilename(filename);
boardDTO.setFilepath("/upload/" + filename); // 파일 경로 설정
}else {
// 수정할 파일이 없으면 게시글 번호 경로만 보여줌
boardDTO.setFilepath(findById(boardDTO.getId()).getFilepath());
}
// dto->entity
board = Board.toUpdateEntity(boardDTO);
boardRepository.save(board);
}
React 공부
<<Page Routuing>>
페이지 라우팅
* Router
= 데이터의 경로를 실시간으로 지정해주는 역할을 하는 무언가
* Routing
= 어떤 네트워크 내에서 통신 데이터를 보낼 경로를 선택하는 일련의 과정
경로를 정해주는 행위 자체와 그런 과정들을 다 포함하여 일컫는 말
* Page Routing
- 인터넷을 사용해서 웹 사이트에 접속한다
= 브라우저를 통해서 웹 서버에게 경로를 요청을 보내고 웹을 받아보는 과정
* SPA
= Single Page Application
= 단일 페이지 어플리케이션
페이지가 1개인 간단한 어플리케이션
=> 다른 페이지 요청을 해도 같은 html을 반환
=> 페이지 요청시 서버를 통하지 않고 React App에서 페이지를 업데이트 하는 것
= 페이지 전환 자체가 빨라진다
=> 데이터가 필요한 경우 = 서버와 데이터만 주고받게된다
* CSR
= Client Side Rendering
=> 브라우저, 클라이언트 측에서 알아서 페이지를 렌더링 하는 것
<React Router>
= React애플리케이션에서 페이지 네비게이션을 관리하기 위한 라이브러리
React애플레키이션에서 다양한 페이지 간의 전환 및 라우팅을 쉽게 구현할 수 있다
=> React Router는 React 컴포넌트를 사용하여 URL과 컴포넌트 간의 매핑을 정의하고
페이지간의 전환을 처리한다
* 라우팅(Routing)
= 웹 애플리케이션에서 사용자가 특정 URL로 이동할 때 해당하는 화면이나 컴포넌트를 보여주는 프로세스를 의미
즉, 사용자가 애플레케이션 내에서 다른 페이지로 이동할 때,
해당 페이지에 맞는 컴포넌트를 동적으로 로드하고 렌더링하는 것을 말한다
* 설치 명령어
= npm install react-router-dom@6(버전)
=> package.json - dependencies 에서 확인
* 주요 컴포넌트
1. BrowserRouter
= HTML의 History API를 사용하여 브라우저의 주소 표시줄을 업데이트하고, UI를 렌더링하는데 사용
2. Route
= 특정 URL에 대해 어떤 컴포넌트를 렌더링할지 정의
주어진 URL 경로에 대해 특정 컴포넌트를 연결
3. Link
= 사용자가 클릭할 수 있는 링크를 제공
클릭 시에 React Router는 지정된 URL로 이동하고 해당하는 컴포넌트를 렌더링
* ex
import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
const Home = () => <div>홈 페이지</div>;
const About = () => <div>소개 페이지</div>;
const App = () => (
<Router>
<div>
<nav>
<ul>
<li><Link to="/">홈</Link></li>
<li><Link to="/about">소개</Link></li>
</ul>
</nav>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
</div>
</Router>
);
export default App;
=> BrowserRouter -> 라우팅 설정
Link 컴포넌트 -> 페이지 간 이동 가능
Router 컴포넌트 -> 각 URL에 대한 컴포넌트 매핑
<<Emotion Diary Project>>
* 페이지로 사용될 component
- Home.js
- New.js
- Edit.js
- Diary.js
* 페이지 라우팅
1. 브라우저 url과 react app을 연결하는 기능을 하는 browser router라는 component로
app component가 return하는 부분을 감싸준다
=> 감싸져 있는 부분들은 브라우저 url과 매핑될 수 있다
2. pages 들을 app.js에 import 해준다
3. 페이지 경로 매핑
브라우저의 url이 바뀌게 되면 어떤 component를 rendering 해서
그 component가 페이지 역할을 하게 할 것인지 결정하기 위해서
<Routes>component로 <Route>component를 감싸준다
그리고 <Route> component 태그 안에 url경로를 적어준다
* Route
= 실질적으로 url경로와 component를 mapping시켜주는 component
=> <Route path="/root" element={<component/>} />
* 매핑된 경로에 따라 바뀌는 페이지는
<Routes>component로 감싸져 있는 부분만 해당되기 때문에
어떤 페이지를 가도 공통으로 보여주고 싶은 부분은
<Routes>component 밖으로 빼주면 된다
4. 페이지를 이동시키는 요소 생성
* <Link> component
=> <a> 태그가 아닌 <Link> 컴포넌트를 활용하여 매핑을 해주면
페이지가 새로고침 되지 않고 리렌더링만으로 페이지 전환을 할 수 있다 (CSR방식)
* CSR 방식으로 페이지 이동시키는 방식
= 실제로 페이지를 이동시킨다기 보다는
페이지 역할을 하는 컴퍼넌트를 갈아 끼우고
url도 바꾸어서 페이지를 이동하는 것 처럼 보이게 만드는 방식이라고 할 수 있다
=> 페이지 이동 시 깜빡임도 없고 이동 속도가 매우 빨라서 쾌적한 페이지 이동을 할 수 있다
* App.js
import "./App.css";
// 브라우저 url과 react app을 연결하는 기능
import { BrowserRouter, Route, Routes } from "react-router-dom";
// 페이지들을 import 해준다
import Home from "./pages/Home.js"; // .js 생략 가능
import New from "./pages/New";
import Edit from "./pages/Edit";
import Diary from "./pages/Diary";
import RouteTest from "./components/RouteTest.js";
function App() {
return (
// BrowserRouter로 감싸준다
// = 감싸져있는 부분은 브라우저 url과 매핑될 수 있다
<BrowserRouter>
<div className="App">
<h2>App.js</h2>
<Routes>
{/* 페이지 경로 매핑 */}
{/* path="/" == path="/index" */}
<Route path="/" element={<Home />} />
<Route path="/new" element={<New />} />
<Route path="/edit" element={<Edit />} />
{/* :id = ':'을 사용하여 id라는 이름으로 값을 전달하겠다 라는 의미 */}
<Route path="/diary/:id" element={<Diary />} />
</Routes>
<RouteTest />
</div>
</BrowserRouter>
);
}
export default App;
<React Router>
* React Router Dom의 유용한 기능
- React Router v6
= React에서 CSR기반의 페이지 라우팅을 할 수 있게 해주는 라이브러리
1. Path Variable
- useParams
= 경로에 변수 사용
- ex) Diary 페이지
경로 : /diary
특징 : 어떤 일기를 보여줘야 할 지 전달 받아야 함
=> /diary/1 = 1번 일기
* Diary.js
import { useParams } from "react-router-dom"; // = custom hooks의 하나
const Diary = () => {
// id로 정의된 path variable을 id로 꺼내온다
// useParams() = id로 전달된 path variable을 모아서 객체로 전달하는 기능을 함
const { id } = useParams();
console.log(id);
return (
<div>
<h1>Diary</h1>
<p>이 곳은 일기 상세 페이지입니다</p>
</div>
);
};
export default Diary;
2. Query String
- useSearchParams
= url과 함께 data를 전달
= path variable과 유사
- ex) edit?id=10&mode=dark
=> Query String 이라고 표현한다
- url을 사용하면서 '?'물음표 키워드를 사용하여 &로 묶어서 데이터를 전송할 수 있는 기법
= 간단하게 페이지에 데이터를 전달할 수 있는 방식이다
- useParams와는 다르게 비구조화 할당을 사용하여
searchParams와 setsearchParams, 이 두개로 전달받을 수 있는 배열을 반환하게 된다
=> 첫번째 반환받는 index = get()을 통해 전해받은 query string 들을 꺼내 쓸 수 있는 용도로 사용
두번재 반환받는 index = searchParams를 변경하는 기능 = 전달받은 query string을 바꿀 수 있다는 의미
= 상태변화 함수
3. Page Moving
- useNavigate
= 함수를 통해 페이지 이동
=> 로그인이 안된 사용자가 로그인을 하려고 로그인 페이지로 가려고 할 때
-> 로그인 값을 검사해서 로그인이 되어있지 않다면 강제로 로그인 페이지로 보내버리는 경우 사용 가능
=> 페이지를 클릭하지 않아도 의도적으로 페이지를 바꿔버릴 수 있다
* navigate 뒤로가기
=> <button onClick={() => { navigate(-1); }}> 뒤로가기 </button>
* Edit.js
import { useNavigate, useSearchParams } from "react-router-dom";
const Edit = () => {
// Query String 꺼내서 사용하기 = 비구조화 할당으로 사용
// useSearchParams() = query string을 처리하는 custom hook
const [searchParams, setSearchParams] = useSearchParams();
// useNavigate hook = 페이지를 이동시킬 수 있는 기능을 하는 함수 하나를 반환
// 그 함수의 이름을 navigate로 받음
const navigate = useNavigate();
const id = searchParams.get("id");
console.log("id: ", id);
const mode = searchParams.get("mode");
console.log("mode: ", mode);
return (
<div>
<h1>Edit</h1>
<p>이 곳은 일기 수정 페이지입니다</p>
{/* setSearchParams를 바꾸는 버튼(객체를 전달한다) */}
<button onClick={() => setSearchParams({ who: "name" })}>
QS 바꾸기
</button>
<button
onClick={() => {
// navigate의 인자로 경로를 작성하면
// navigate 함수를 호출해서 경로를 옮겨줄 수 있다
navigate("/home");
}}
></button>
<button
onClick={() => {
navigate(-1);
}}
>
뒤로가기
</button>
</div>
);
};
export default Edit;
2023. 01. 22 (월)
프로그래밍 도전기 107일차 (2) | 2024.01.25 |
---|---|
프로그래머 도전기 106일차 (2) | 2024.01.23 |
프로그래머 도전기 104일차 (0) | 2024.01.18 |
프로그래머 도전기 103일차 (0) | 2024.01.15 |
프로그래머 도전기 102일차 (2) | 2024.01.14 |